@mutagent/cli 0.1.15 → 0.1.16
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 +438 -693
- package/dist/bin/cli.js.map +15 -18
- package/dist/index.js +11 -2
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
package/dist/bin/cli.js
CHANGED
|
@@ -464,6 +464,7 @@ class SDKClientWrapper {
|
|
|
464
464
|
systemPrompt: data.systemPrompt ?? undefined,
|
|
465
465
|
humanPrompt: data.humanPrompt ?? undefined,
|
|
466
466
|
rawPrompt: data.rawPrompt ?? undefined,
|
|
467
|
+
inputSchema: data.inputSchema,
|
|
467
468
|
outputSchema: data.outputSchema,
|
|
468
469
|
metadata: data.metadata,
|
|
469
470
|
tags: data.tags ?? undefined
|
|
@@ -529,11 +530,13 @@ class SDKClientWrapper {
|
|
|
529
530
|
labels: item.labels,
|
|
530
531
|
metadata: item.metadata
|
|
531
532
|
}));
|
|
533
|
+
const missingExpectedOutputCount = mappedItems.filter((item) => item.expectedOutput === undefined).length;
|
|
532
534
|
await this.request(`/api/prompts/datasets/${String(dataset.id)}/items/bulk`, {
|
|
533
535
|
method: "POST",
|
|
534
536
|
body: JSON.stringify({ items: mappedItems })
|
|
535
537
|
});
|
|
536
538
|
itemCount = mappedItems.length;
|
|
539
|
+
return { ...dataset, itemCount, missingExpectedOutputCount };
|
|
537
540
|
}
|
|
538
541
|
return { ...dataset, itemCount };
|
|
539
542
|
} catch (error) {
|
|
@@ -588,7 +591,7 @@ class SDKClientWrapper {
|
|
|
588
591
|
body: JSON.stringify({
|
|
589
592
|
datasetId: parseInt(datasetId, 10),
|
|
590
593
|
config: {
|
|
591
|
-
maxIterations: config?.maxIterations ??
|
|
594
|
+
maxIterations: config?.maxIterations ?? 1,
|
|
592
595
|
targetScore: config?.targetScore,
|
|
593
596
|
patience: config?.patience,
|
|
594
597
|
model: config?.model,
|
|
@@ -849,6 +852,12 @@ class SDKClientWrapper {
|
|
|
849
852
|
this.handleError(error);
|
|
850
853
|
}
|
|
851
854
|
}
|
|
855
|
+
getCurrentWorkspaceId() {
|
|
856
|
+
return this.workspaceId;
|
|
857
|
+
}
|
|
858
|
+
getCurrentOrgId() {
|
|
859
|
+
return this.organizationId;
|
|
860
|
+
}
|
|
852
861
|
async testProvider(id) {
|
|
853
862
|
try {
|
|
854
863
|
const response = await this.sdk.providerConfigs.testProvider({
|
|
@@ -924,7 +933,7 @@ var init_sdk_client = __esm(() => {
|
|
|
924
933
|
// src/bin/cli.ts
|
|
925
934
|
import { Command as Command14 } from "commander";
|
|
926
935
|
import chalk18 from "chalk";
|
|
927
|
-
import { readFileSync as
|
|
936
|
+
import { readFileSync as readFileSync12 } from "fs";
|
|
928
937
|
import { join as join7, dirname } from "path";
|
|
929
938
|
import { fileURLToPath } from "url";
|
|
930
939
|
|
|
@@ -1779,12 +1788,10 @@ async function runIntegrationPath() {
|
|
|
1779
1788
|
name: "framework",
|
|
1780
1789
|
message: "Which AI framework are you using?",
|
|
1781
1790
|
choices: [
|
|
1782
|
-
{ name: "Mastra", value: "mastra" },
|
|
1783
1791
|
{ name: "LangChain", value: "langchain" },
|
|
1784
1792
|
{ name: "LangGraph", value: "langgraph" },
|
|
1785
1793
|
{ name: "Vercel AI SDK", value: "vercel-ai" },
|
|
1786
|
-
{ name: "
|
|
1787
|
-
{ name: "Other / Generic", value: "generic" }
|
|
1794
|
+
{ name: "OpenAI SDK", value: "openai" }
|
|
1788
1795
|
]
|
|
1789
1796
|
}]);
|
|
1790
1797
|
console.log("");
|
|
@@ -2419,17 +2426,39 @@ function isValidJsonSchema(schema) {
|
|
|
2419
2426
|
function buildSchemaFromVariables(variables) {
|
|
2420
2427
|
const properties = {};
|
|
2421
2428
|
for (const variable of variables) {
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
}
|
|
2426
|
-
properties[variable.name] = prop;
|
|
2429
|
+
properties[variable.name] = {
|
|
2430
|
+
type: variable.type,
|
|
2431
|
+
description: variable.description
|
|
2432
|
+
};
|
|
2427
2433
|
}
|
|
2428
2434
|
return {
|
|
2429
2435
|
type: "object",
|
|
2430
2436
|
properties
|
|
2431
2437
|
};
|
|
2432
2438
|
}
|
|
2439
|
+
function validateSchemaDescriptions(schema) {
|
|
2440
|
+
if (schema === null || schema === undefined)
|
|
2441
|
+
return [];
|
|
2442
|
+
if (typeof schema !== "object" || Array.isArray(schema))
|
|
2443
|
+
return [];
|
|
2444
|
+
const obj = schema;
|
|
2445
|
+
const properties = obj.properties;
|
|
2446
|
+
if (!properties || typeof properties !== "object" || Array.isArray(properties))
|
|
2447
|
+
return [];
|
|
2448
|
+
const missing = [];
|
|
2449
|
+
const props = properties;
|
|
2450
|
+
for (const [key, value] of Object.entries(props)) {
|
|
2451
|
+
if (value === null || value === undefined || typeof value !== "object") {
|
|
2452
|
+
missing.push(key);
|
|
2453
|
+
continue;
|
|
2454
|
+
}
|
|
2455
|
+
const prop = value;
|
|
2456
|
+
if (typeof prop.description !== "string" || prop.description.trim() === "") {
|
|
2457
|
+
missing.push(key);
|
|
2458
|
+
}
|
|
2459
|
+
}
|
|
2460
|
+
return missing;
|
|
2461
|
+
}
|
|
2433
2462
|
function formatSchemaWarning(fieldName) {
|
|
2434
2463
|
return [
|
|
2435
2464
|
`${fieldName} doesn't appear to be a valid JSON Schema.`,
|
|
@@ -2593,10 +2622,11 @@ async function runGuidedEvalCreator(promptId) {
|
|
|
2593
2622
|
} else {
|
|
2594
2623
|
scoringRubric = rubric;
|
|
2595
2624
|
}
|
|
2625
|
+
const evaluationParameter = targetField.startsWith("output.") ? targetField.slice("output.".length) : targetField.startsWith("input.") ? targetField.slice("input.".length) : targetField;
|
|
2596
2626
|
criteria.push({
|
|
2597
2627
|
name: criterionName.trim(),
|
|
2598
|
-
|
|
2599
|
-
|
|
2628
|
+
description: scoringRubric,
|
|
2629
|
+
evaluationParameter,
|
|
2600
2630
|
weight: 1
|
|
2601
2631
|
});
|
|
2602
2632
|
const { continueAdding } = await inquirer3.prompt([{
|
|
@@ -2618,7 +2648,7 @@ async function runGuidedEvalCreator(promptId) {
|
|
|
2618
2648
|
console.log(` Type: ${evalType}`);
|
|
2619
2649
|
console.log(` Criteria: ${String(criteria.length)}`);
|
|
2620
2650
|
for (const c of criteria) {
|
|
2621
|
-
console.log(` - ${chalk5.cyan(c.name)} → ${c.
|
|
2651
|
+
console.log(` - ${chalk5.cyan(c.name)} → ${c.evaluationParameter}`);
|
|
2622
2652
|
}
|
|
2623
2653
|
console.log("");
|
|
2624
2654
|
const { confirmed } = await inquirer3.prompt([{
|
|
@@ -2691,6 +2721,38 @@ function renderScorecard(data) {
|
|
|
2691
2721
|
console.log(line(` Prompt: ${chalk6.cyan(truncateText(optimizedText, 38))}`));
|
|
2692
2722
|
console.log(line(` Score: ${formatScore(bestScore)}${formatScoreChange(originalScore, bestScore)}`));
|
|
2693
2723
|
console.log(separator);
|
|
2724
|
+
if (data.criteriaScores && data.criteriaScores.length > 0) {
|
|
2725
|
+
console.log(line(chalk6.dim(" Criterion Before After Change")));
|
|
2726
|
+
console.log(line(chalk6.dim(" " + "─".repeat(45))));
|
|
2727
|
+
for (const c of data.criteriaScores) {
|
|
2728
|
+
const name = c.name.length > 16 ? c.name.substring(0, 13) + "..." : c.name;
|
|
2729
|
+
const paddedName = name + " ".repeat(18 - name.length);
|
|
2730
|
+
const beforeStr = c.before !== undefined ? c.before.toFixed(2) : "N/A ";
|
|
2731
|
+
const afterStr = c.after !== undefined ? c.after.toFixed(2) : "N/A ";
|
|
2732
|
+
const changeStr = c.before !== undefined && c.after !== undefined && c.before > 0 ? (() => {
|
|
2733
|
+
const pct = Math.round((c.after - c.before) / c.before * 100);
|
|
2734
|
+
if (pct > 0)
|
|
2735
|
+
return chalk6.green(`+${String(pct)}%`);
|
|
2736
|
+
if (pct < 0)
|
|
2737
|
+
return chalk6.red(`${String(pct)}%`);
|
|
2738
|
+
return chalk6.dim("0%");
|
|
2739
|
+
})() : "";
|
|
2740
|
+
console.log(line(` ${paddedName}${beforeStr} ${afterStr} ${changeStr}`));
|
|
2741
|
+
}
|
|
2742
|
+
console.log(line(chalk6.dim(" " + "─".repeat(45))));
|
|
2743
|
+
const overallBefore = originalScore !== undefined ? originalScore.toFixed(2) : "N/A ";
|
|
2744
|
+
const overallAfter = bestScore !== undefined ? bestScore.toFixed(2) : "N/A ";
|
|
2745
|
+
const overallChange = originalScore !== undefined && bestScore !== undefined && originalScore > 0 ? (() => {
|
|
2746
|
+
const pct = Math.round((bestScore - originalScore) / originalScore * 100);
|
|
2747
|
+
if (pct > 0)
|
|
2748
|
+
return chalk6.green(`+${String(pct)}%`);
|
|
2749
|
+
if (pct < 0)
|
|
2750
|
+
return chalk6.red(`${String(pct)}%`);
|
|
2751
|
+
return chalk6.dim("0%");
|
|
2752
|
+
})() : "";
|
|
2753
|
+
console.log(line(` ${"Overall" + " ".repeat(11)}${overallBefore} ${overallAfter} ${overallChange}`));
|
|
2754
|
+
console.log(separator);
|
|
2755
|
+
}
|
|
2694
2756
|
const statusStr = job.status === "completed" ? chalk6.green("completed") : chalk6.yellow(job.status);
|
|
2695
2757
|
console.log(line(`Status: ${statusStr} | Iterations: ${String(iterations)}`));
|
|
2696
2758
|
if (job.config?.model) {
|
|
@@ -2699,19 +2761,16 @@ function renderScorecard(data) {
|
|
|
2699
2761
|
if (data.scoreProgression && data.scoreProgression.length > 0) {
|
|
2700
2762
|
console.log(line(""));
|
|
2701
2763
|
console.log(line(chalk6.dim("Score Progression:")));
|
|
2702
|
-
const
|
|
2703
|
-
|
|
2704
|
-
const
|
|
2705
|
-
const
|
|
2706
|
-
const
|
|
2707
|
-
console.log(line(chalk6.dim(
|
|
2708
|
-
console.log(line(chalk6.dim(line2)));
|
|
2709
|
-
} else {
|
|
2710
|
-
console.log(line(chalk6.dim(progression)));
|
|
2764
|
+
const barWidth = 10;
|
|
2765
|
+
for (let i = 0;i < data.scoreProgression.length; i++) {
|
|
2766
|
+
const s = data.scoreProgression[i] ?? 0;
|
|
2767
|
+
const filled = Math.round(s * barWidth);
|
|
2768
|
+
const bar = "█".repeat(filled) + "░".repeat(barWidth - filled);
|
|
2769
|
+
console.log(line(chalk6.dim(` #${String(i + 1)}: ${bar} ${s.toFixed(2)}`)));
|
|
2711
2770
|
}
|
|
2712
2771
|
}
|
|
2713
2772
|
console.log(separator);
|
|
2714
|
-
console.log(line(`Dashboard: ${chalk6.underline(optimizerLink(job.
|
|
2773
|
+
console.log(line(`Dashboard: ${chalk6.underline(optimizerLink(job.id))}`));
|
|
2715
2774
|
console.log(bottomBorder);
|
|
2716
2775
|
console.log("");
|
|
2717
2776
|
}
|
|
@@ -2780,18 +2839,6 @@ function isSchemaEmpty(schema) {
|
|
|
2780
2839
|
return true;
|
|
2781
2840
|
return false;
|
|
2782
2841
|
}
|
|
2783
|
-
function warnMissingSchemas(data, output) {
|
|
2784
|
-
if (isSchemaEmpty(data.inputSchema)) {
|
|
2785
|
-
output.warn("No inputSchema provided. Optimization requires inputSchema with defined variables.");
|
|
2786
|
-
} else if (!isValidJsonSchema(data.inputSchema)) {
|
|
2787
|
-
output.warn(formatSchemaWarning("inputSchema"));
|
|
2788
|
-
}
|
|
2789
|
-
if (isSchemaEmpty(data.outputSchema)) {
|
|
2790
|
-
output.warn("No outputSchema provided. This may limit optimization effectiveness.");
|
|
2791
|
-
} else if (!isValidJsonSchema(data.outputSchema)) {
|
|
2792
|
-
output.warn(formatSchemaWarning("outputSchema"));
|
|
2793
|
-
}
|
|
2794
|
-
}
|
|
2795
2842
|
async function collectSchemaInteractively() {
|
|
2796
2843
|
const inquirer3 = (await import("inquirer")).default;
|
|
2797
2844
|
const variables = [];
|
|
@@ -2820,13 +2867,18 @@ async function collectSchemaInteractively() {
|
|
|
2820
2867
|
{
|
|
2821
2868
|
type: "input",
|
|
2822
2869
|
name: "description",
|
|
2823
|
-
message: "Description (
|
|
2870
|
+
message: "Description (required):",
|
|
2871
|
+
validate: (input) => {
|
|
2872
|
+
if (!input.trim())
|
|
2873
|
+
return "Variable description is required";
|
|
2874
|
+
return true;
|
|
2875
|
+
}
|
|
2824
2876
|
}
|
|
2825
2877
|
]);
|
|
2826
2878
|
variables.push({
|
|
2827
2879
|
name: answers.name.trim(),
|
|
2828
2880
|
type: answers.type,
|
|
2829
|
-
description: answers.description.trim()
|
|
2881
|
+
description: answers.description.trim()
|
|
2830
2882
|
});
|
|
2831
2883
|
const continueAnswer = await inquirer3.prompt([{
|
|
2832
2884
|
type: "confirm",
|
|
@@ -2963,14 +3015,22 @@ ${chalk7.dim("Tip: Use --json for machine-readable output (AI agents, CI pipelin
|
|
|
2963
3015
|
}));
|
|
2964
3016
|
output.output(withLinks);
|
|
2965
3017
|
} else {
|
|
2966
|
-
const
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
}
|
|
2973
|
-
|
|
3018
|
+
const wsId = client.getCurrentWorkspaceId();
|
|
3019
|
+
if (wsId) {
|
|
3020
|
+
output.info(`Workspace: ${wsId}`);
|
|
3021
|
+
}
|
|
3022
|
+
if (limited.length === 0) {
|
|
3023
|
+
output.info("No prompts found in current workspace. Run 'mutagent config list' to check workspace context.");
|
|
3024
|
+
} else {
|
|
3025
|
+
const formatted = limited.map((p) => ({
|
|
3026
|
+
id: p.id,
|
|
3027
|
+
name: p.name,
|
|
3028
|
+
version: p.version,
|
|
3029
|
+
updated: p.updatedAt ? new Date(p.updatedAt).toLocaleDateString() : "N/A",
|
|
3030
|
+
url: promptLink(p.id)
|
|
3031
|
+
}));
|
|
3032
|
+
output.output(formatted);
|
|
3033
|
+
}
|
|
2974
3034
|
}
|
|
2975
3035
|
} catch (error) {
|
|
2976
3036
|
handleError(error, isJson);
|
|
@@ -3120,17 +3180,32 @@ ${chalk7.dim("Note: --data and --file are mutually exclusive. outputSchema is re
|
|
|
3120
3180
|
if (schema) {
|
|
3121
3181
|
data.inputSchema = schema;
|
|
3122
3182
|
}
|
|
3123
|
-
} else {
|
|
3124
|
-
output.warn("No inputSchema provided. Optimization requires inputSchema with defined variables.");
|
|
3125
3183
|
}
|
|
3126
3184
|
}
|
|
3127
|
-
|
|
3185
|
+
if (isSchemaEmpty(data.inputSchema)) {
|
|
3186
|
+
throw new MutagentError("VALIDATION_ERROR", "inputSchema is required. Optimization cannot run without defined input variables.", `Provide inputSchema via --data, --file, or interactive mode. Example:
|
|
3187
|
+
--data '{"inputSchema":{"type":"object","properties":{"query":{"type":"string","description":"User query"}}}}'
|
|
3188
|
+
Or use interactive mode (TTY) to define variables step by step.`);
|
|
3189
|
+
} else if (!isValidJsonSchema(data.inputSchema)) {
|
|
3190
|
+
throw new MutagentError("VALIDATION_ERROR", "inputSchema is not a valid JSON Schema object.", formatSchemaWarning("inputSchema"));
|
|
3191
|
+
} else {
|
|
3192
|
+
const missingDescs = validateSchemaDescriptions(data.inputSchema);
|
|
3193
|
+
if (missingDescs.length > 0) {
|
|
3194
|
+
throw new MutagentError("VALIDATION_ERROR", `inputSchema properties missing descriptions: ${missingDescs.join(", ")}`, `Add a 'description' field to each property in your inputSchema. Example: { "properties": { "field": { "type": "string", "description": "What this field contains" } } }`);
|
|
3195
|
+
}
|
|
3196
|
+
}
|
|
3197
|
+
if (isSchemaEmpty(data.outputSchema)) {
|
|
3198
|
+
output.warn("No outputSchema provided. This may limit optimization effectiveness.");
|
|
3199
|
+
} else if (!isValidJsonSchema(data.outputSchema)) {
|
|
3200
|
+
output.warn(formatSchemaWarning("outputSchema"));
|
|
3201
|
+
}
|
|
3128
3202
|
const client = getSDKClient();
|
|
3129
3203
|
const prompt = await client.createPrompt(data);
|
|
3130
3204
|
if (isJson) {
|
|
3131
3205
|
output.output({ ...prompt, _links: promptLinks(prompt.id) });
|
|
3132
3206
|
} else {
|
|
3133
3207
|
output.success(`Created prompt: ${prompt.name} (id: ${String(prompt.id)})`);
|
|
3208
|
+
output.info(`Workspace: ${client.getCurrentWorkspaceId() ?? "auto-inferred from API key"}`);
|
|
3134
3209
|
const hints = formatCreationHints({
|
|
3135
3210
|
resourceType: "Prompt",
|
|
3136
3211
|
id: prompt.id,
|
|
@@ -3152,13 +3227,15 @@ ${chalk7.dim("Note: --data and --file are mutually exclusive. outputSchema is re
|
|
|
3152
3227
|
handleError(error, isJson);
|
|
3153
3228
|
}
|
|
3154
3229
|
});
|
|
3155
|
-
prompts.command("update").description("Update a prompt").argument("<id>", "Prompt ID (from: mutagent prompts list)").option("-d, --data <json>", "Update fields as JSON string (recommended — curl-style inline)").option("-f, --file <path>", "Update from JSON file").option("--raw-file <path>", "Update from plain text file (used as rawPrompt)").option("-n, --name <name>", "New name").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":"..."}]')`).addHelpText("after", `
|
|
3230
|
+
prompts.command("update").description("Update a prompt").argument("<id>", "Prompt ID (from: mutagent prompts list)").option("-d, --data <json>", "Update fields as JSON string (recommended — curl-style inline)").option("-f, --file <path>", "Update from JSON file").option("--raw-file <path>", "Update from plain text file (used as rawPrompt)").option("-n, --name <name>", "New name").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", `
|
|
3156
3231
|
Examples:
|
|
3157
3232
|
${chalk7.dim("$")} mutagent prompts update <id> -d '{"name":"new-name","systemPrompt":"Updated prompt"}'
|
|
3158
3233
|
${chalk7.dim("$")} mutagent prompts update <id> --name "new-name"
|
|
3159
3234
|
${chalk7.dim("$")} mutagent prompts update <id> --system "Updated system prompt"
|
|
3160
3235
|
${chalk7.dim("$")} mutagent prompts update <id> --raw-file updated-prompt.txt
|
|
3161
3236
|
${chalk7.dim("$")} mutagent prompts update <id> --file updated-prompt.json
|
|
3237
|
+
${chalk7.dim("$")} mutagent prompts update <id> --input-schema '{"type":"object","properties":{"text":{"type":"string","description":"Input text"}}}'
|
|
3238
|
+
${chalk7.dim("$")} mutagent prompts update <id> --input-schema-file schema.json
|
|
3162
3239
|
|
|
3163
3240
|
${chalk7.dim("Note: --data and --file are mutually exclusive. CLI flags (--name) override --data fields.")}
|
|
3164
3241
|
`).action(async (id, options) => {
|
|
@@ -3214,8 +3291,52 @@ ${chalk7.dim("Note: --data and --file are mutually exclusive. CLI flags (--name)
|
|
|
3214
3291
|
data.rawPrompt = options.content;
|
|
3215
3292
|
}
|
|
3216
3293
|
}
|
|
3294
|
+
if (options.inputSchema && options.inputSchemaFile) {
|
|
3295
|
+
throw new MutagentError("INVALID_ARGUMENTS", "Cannot use --input-schema and --input-schema-file together", "Use --input-schema for inline JSON or --input-schema-file for file-based input, not both");
|
|
3296
|
+
}
|
|
3297
|
+
if (options.inputSchema) {
|
|
3298
|
+
try {
|
|
3299
|
+
data.inputSchema = JSON.parse(options.inputSchema);
|
|
3300
|
+
} catch {
|
|
3301
|
+
throw new MutagentError("INVALID_JSON", "Invalid JSON in --input-schema flag", `Provide a valid JSON Schema, e.g., '{"type":"object","properties":{"text":{"type":"string","description":"Input text"}}}'`);
|
|
3302
|
+
}
|
|
3303
|
+
} else if (options.inputSchemaFile) {
|
|
3304
|
+
if (!existsSync4(options.inputSchemaFile)) {
|
|
3305
|
+
throw new MutagentError("FILE_NOT_FOUND", `File not found: ${options.inputSchemaFile}`, "Check the file path and try again");
|
|
3306
|
+
}
|
|
3307
|
+
try {
|
|
3308
|
+
data.inputSchema = JSON.parse(readFileSync4(options.inputSchemaFile, "utf-8"));
|
|
3309
|
+
} catch {
|
|
3310
|
+
throw new MutagentError("INVALID_JSON", `Failed to parse JSON from ${options.inputSchemaFile}`, "Ensure the file contains valid JSON Schema");
|
|
3311
|
+
}
|
|
3312
|
+
}
|
|
3313
|
+
if (options.outputSchema && options.outputSchemaFile) {
|
|
3314
|
+
throw new MutagentError("INVALID_ARGUMENTS", "Cannot use --output-schema and --output-schema-file together", "Use --output-schema for inline JSON or --output-schema-file for file-based input, not both");
|
|
3315
|
+
}
|
|
3316
|
+
if (options.outputSchema) {
|
|
3317
|
+
try {
|
|
3318
|
+
data.outputSchema = JSON.parse(options.outputSchema);
|
|
3319
|
+
} catch {
|
|
3320
|
+
throw new MutagentError("INVALID_JSON", "Invalid JSON in --output-schema flag", `Provide a valid JSON Schema, e.g., '{"type":"object","properties":{"result":{"type":"string"}}}'`);
|
|
3321
|
+
}
|
|
3322
|
+
} else if (options.outputSchemaFile) {
|
|
3323
|
+
if (!existsSync4(options.outputSchemaFile)) {
|
|
3324
|
+
throw new MutagentError("FILE_NOT_FOUND", `File not found: ${options.outputSchemaFile}`, "Check the file path and try again");
|
|
3325
|
+
}
|
|
3326
|
+
try {
|
|
3327
|
+
data.outputSchema = JSON.parse(readFileSync4(options.outputSchemaFile, "utf-8"));
|
|
3328
|
+
} catch {
|
|
3329
|
+
throw new MutagentError("INVALID_JSON", `Failed to parse JSON from ${options.outputSchemaFile}`, "Ensure the file contains valid JSON Schema");
|
|
3330
|
+
}
|
|
3331
|
+
}
|
|
3332
|
+
if (data.inputSchema && isValidJsonSchema(data.inputSchema)) {
|
|
3333
|
+
const missingDescs = validateSchemaDescriptions(data.inputSchema);
|
|
3334
|
+
if (missingDescs.length > 0) {
|
|
3335
|
+
throw new MutagentError("VALIDATION_ERROR", `inputSchema properties missing descriptions: ${missingDescs.join(", ")}`, `Add a 'description' field to each property in your inputSchema. Example: { "properties": { "field": { "type": "string", "description": "What this field contains" } } }`);
|
|
3336
|
+
}
|
|
3337
|
+
}
|
|
3217
3338
|
if (Object.keys(data).length === 0) {
|
|
3218
|
-
throw new MutagentError("MISSING_ARGUMENTS", "No update data provided", "Use --data, --file, --raw-file, --name, --raw, --system/--human, or --
|
|
3339
|
+
throw new MutagentError("MISSING_ARGUMENTS", "No update data provided", "Use --data, --file, --raw-file, --name, --raw, --system/--human, --messages, --input-schema, or --output-schema");
|
|
3219
3340
|
}
|
|
3220
3341
|
const promptContent = data.rawPrompt ?? data.systemPrompt ?? data.humanPrompt ?? "";
|
|
3221
3342
|
if (promptContent && !isJson) {
|
|
@@ -3386,6 +3507,9 @@ ${chalk7.dim("Note: --file and -d are mutually exclusive. Provide one or the oth
|
|
|
3386
3507
|
if (datasetResult.itemCount !== undefined && datasetResult.itemCount > 0) {
|
|
3387
3508
|
output.info(`Items uploaded: ${String(datasetResult.itemCount)}`);
|
|
3388
3509
|
}
|
|
3510
|
+
if (datasetResult.missingExpectedOutputCount !== undefined && datasetResult.missingExpectedOutputCount > 0) {
|
|
3511
|
+
output.warn(`${String(datasetResult.missingExpectedOutputCount)} of ${String(datasetResult.itemCount ?? 0)} items have no expectedOutput. Optimization may fail without expected outputs.`);
|
|
3512
|
+
}
|
|
3389
3513
|
const hints = formatCreationHints({
|
|
3390
3514
|
resourceType: "Dataset",
|
|
3391
3515
|
id: datasetResult.id,
|
|
@@ -3460,8 +3584,8 @@ Examples:
|
|
|
3460
3584
|
${chalk7.dim("$")} mutagent prompts evaluation create <prompt-id> --name "Full Eval" --file criteria.json --dataset <dataset-id>
|
|
3461
3585
|
${chalk7.dim("$")} mutagent prompts evaluation create <prompt-id> --name "QA" --description "Quality assurance eval" --json
|
|
3462
3586
|
|
|
3463
|
-
Criteria
|
|
3464
|
-
${chalk7.dim('{ "name": "...", "evalConfig": { "criteria": [...
|
|
3587
|
+
Criteria format (each criterion needs: name, description, evaluationParameter):
|
|
3588
|
+
${chalk7.dim('{ "name": "...", "evalConfig": { "criteria": [{ "name": "...", "description": "...", "evaluationParameter": "outputField" }] } }')}
|
|
3465
3589
|
|
|
3466
3590
|
${chalk7.dim("Note: --data and --file are mutually exclusive. CLI flags (--name, --description) override --data fields.")}
|
|
3467
3591
|
${chalk7.dim("Tip: Use --guided for an interactive walkthrough of criteria creation.")}
|
|
@@ -3549,6 +3673,32 @@ ${chalk7.dim("Get prompt IDs: mutagent prompts list | Get dataset IDs: mutagent
|
|
|
3549
3673
|
evalData.name = options.name;
|
|
3550
3674
|
if (options.description)
|
|
3551
3675
|
evalData.description = options.description;
|
|
3676
|
+
const criteria = evalData.evalConfig?.criteria;
|
|
3677
|
+
if (!criteria || !Array.isArray(criteria) || criteria.length === 0) {
|
|
3678
|
+
throw new MutagentError("VALIDATION_ERROR", "Evaluation criteria are required. Provide criteria via --data, --file, or use --guided mode.", `Each criterion needs: name, description, evaluationParameter.
|
|
3679
|
+
|
|
3680
|
+
Example JSON (--data flag):
|
|
3681
|
+
--data '{"evalConfig":{"criteria":[{"name":"Accuracy","description":"Score 1.0 if output matches expected, 0.0 otherwise","evaluationParameter":"classification"}]}}'
|
|
3682
|
+
|
|
3683
|
+
Or use --guided for interactive creation: mutagent prompts evaluation create <id> --guided`);
|
|
3684
|
+
}
|
|
3685
|
+
for (const c of criteria) {
|
|
3686
|
+
const hasDescription = c.description ?? c.scoringRubric;
|
|
3687
|
+
const hasEvalParam = c.evaluationParameter ?? c.targetField;
|
|
3688
|
+
if (!c.name || !hasDescription || !hasEvalParam) {
|
|
3689
|
+
const cName = typeof c.name === "string" ? c.name : "unnamed";
|
|
3690
|
+
throw new MutagentError("VALIDATION_ERROR", `Criterion "${cName}" is missing required fields. Need: name, description (or scoringRubric), evaluationParameter (or targetField).`, 'evaluationParameter maps to the output field to evaluate (e.g., "classification", "riskLevel"). Use --guided for interactive creation.');
|
|
3691
|
+
}
|
|
3692
|
+
if (c.scoringRubric && !c.description) {
|
|
3693
|
+
c.description = c.scoringRubric;
|
|
3694
|
+
delete c.scoringRubric;
|
|
3695
|
+
}
|
|
3696
|
+
if (c.targetField && !c.evaluationParameter) {
|
|
3697
|
+
const tf = c.targetField;
|
|
3698
|
+
c.evaluationParameter = tf.startsWith("output.") ? tf.slice("output.".length) : tf.startsWith("input.") ? tf.slice("input.".length) : tf;
|
|
3699
|
+
delete c.targetField;
|
|
3700
|
+
}
|
|
3701
|
+
}
|
|
3552
3702
|
if (options.dataset) {
|
|
3553
3703
|
evalData.datasetId = parseInt(options.dataset, 10);
|
|
3554
3704
|
if (isNaN(evalData.datasetId)) {
|
|
@@ -3618,6 +3768,38 @@ ${chalk7.dim("Monitor progress with: mutagent prompts optimize status <job-id>")
|
|
|
3618
3768
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
3619
3769
|
try {
|
|
3620
3770
|
const client = getSDKClient();
|
|
3771
|
+
if (!isJson) {
|
|
3772
|
+
output.info("Running pre-flight checks...");
|
|
3773
|
+
const prompt = await client.getPrompt(promptId);
|
|
3774
|
+
if (isSchemaEmpty(prompt.outputSchema)) {
|
|
3775
|
+
throw new MutagentError("MISSING_OUTPUT_SCHEMA", "Prompt is missing outputSchema — required for optimization", `Update your prompt: mutagent prompts update ${promptId} -d '{"outputSchema":{"type":"object","properties":{"result":{"type":"string"}}}}'`);
|
|
3776
|
+
}
|
|
3777
|
+
if (isSchemaEmpty(prompt.inputSchema)) {
|
|
3778
|
+
output.warn("Prompt has no inputSchema. Optimization works best with defined input variables.");
|
|
3779
|
+
}
|
|
3780
|
+
try {
|
|
3781
|
+
const evals = await client.listEvaluations(promptId);
|
|
3782
|
+
if (evals.length === 0) {
|
|
3783
|
+
throw new MutagentError("MISSING_EVALUATION", "No evaluations found for this prompt — required for optimization", `Create an evaluation: mutagent prompts evaluation create ${promptId} --guided`);
|
|
3784
|
+
}
|
|
3785
|
+
const validEvals = evals.filter((e) => {
|
|
3786
|
+
const config = e.evalConfig;
|
|
3787
|
+
const criteria = config?.criteria;
|
|
3788
|
+
if (!criteria || criteria.length === 0)
|
|
3789
|
+
return false;
|
|
3790
|
+
return criteria.some((c) => c.evaluationParameter ?? c.targetField);
|
|
3791
|
+
});
|
|
3792
|
+
if (validEvals.length === 0) {
|
|
3793
|
+
output.warn(`Evaluations exist but none have evaluationParameter set. Optimization works best with criteria targeting specific output fields. Re-create: mutagent prompts evaluation create ${promptId} --guided`);
|
|
3794
|
+
} else {
|
|
3795
|
+
output.info(`Found ${String(validEvals.length)} evaluation(s) with proper criteria.`);
|
|
3796
|
+
}
|
|
3797
|
+
} catch (e) {
|
|
3798
|
+
if (e instanceof MutagentError)
|
|
3799
|
+
throw e;
|
|
3800
|
+
output.warn("Could not validate evaluations. Optimization will use default evaluation.");
|
|
3801
|
+
}
|
|
3802
|
+
}
|
|
3621
3803
|
const job = await client.startOptimization(promptId, options.dataset, {
|
|
3622
3804
|
maxIterations: options.maxIterations ? parseInt(options.maxIterations, 10) : undefined,
|
|
3623
3805
|
targetScore: options.targetScore ? parseFloat(options.targetScore) : undefined,
|
|
@@ -3629,27 +3811,55 @@ ${chalk7.dim("Monitor progress with: mutagent prompts optimize status <job-id>")
|
|
|
3629
3811
|
output.output({
|
|
3630
3812
|
...job,
|
|
3631
3813
|
_links: {
|
|
3632
|
-
dashboard: optimizerLink(job.
|
|
3633
|
-
api: `/api/prompts/${promptId}/optimizations/${job.
|
|
3814
|
+
dashboard: optimizerLink(job.id),
|
|
3815
|
+
api: `/api/prompts/${promptId}/optimizations/${job.id}`
|
|
3634
3816
|
}
|
|
3635
3817
|
});
|
|
3636
3818
|
} else {
|
|
3637
|
-
output.success(`Started optimization job: ${job.
|
|
3819
|
+
output.success(`Started optimization job: ${job.id}`);
|
|
3638
3820
|
const hints = formatCreationHints({
|
|
3639
3821
|
resourceType: "Optimization",
|
|
3640
|
-
id: job.
|
|
3641
|
-
dashboardUrl: optimizerLink(job.
|
|
3642
|
-
apiPath: `/api/prompts/${promptId}/optimizations/${job.
|
|
3822
|
+
id: job.id,
|
|
3823
|
+
dashboardUrl: optimizerLink(job.id),
|
|
3824
|
+
apiPath: `/api/prompts/${promptId}/optimizations/${job.id}`
|
|
3643
3825
|
});
|
|
3644
3826
|
console.log(hints);
|
|
3645
3827
|
}
|
|
3646
3828
|
} catch (error) {
|
|
3647
3829
|
if (error instanceof ApiError) {
|
|
3648
3830
|
const messages = parseValidationErrors(error);
|
|
3831
|
+
const errorText = messages.join(" ");
|
|
3832
|
+
const suggestions = [];
|
|
3833
|
+
if (errorText.includes("Output Schema is not present") || errorText.includes("outputSchema")) {
|
|
3834
|
+
suggestions.push(`Update prompt: mutagent prompts update ${promptId} -d '{"outputSchema":{"type":"object","properties":{...}}}'`);
|
|
3835
|
+
}
|
|
3836
|
+
if (errorText.includes("Outputs are not valid") || errorText.includes("Parameters Mismatch")) {
|
|
3837
|
+
suggestions.push("Dataset items may not match the prompt schema. Check expectedOutput fields in your dataset.");
|
|
3838
|
+
}
|
|
3839
|
+
if (errorText.includes("Inputs are not valid")) {
|
|
3840
|
+
suggestions.push("Dataset item inputs don't match the prompt's inputSchema. Verify field names and types.");
|
|
3841
|
+
}
|
|
3842
|
+
if (errorText.includes("has no items") || errorText.includes("Dataset") && errorText.includes("not found")) {
|
|
3843
|
+
suggestions.push(`Upload data: mutagent prompts dataset add ${promptId} --file data.json`);
|
|
3844
|
+
}
|
|
3845
|
+
if (errorText.includes("Evaluations are not present")) {
|
|
3846
|
+
suggestions.push(`Create evaluation: mutagent prompts evaluation create ${promptId} --guided`);
|
|
3847
|
+
}
|
|
3848
|
+
if (errorText.includes("Trial") && errorText.includes("limit")) {
|
|
3849
|
+
suggestions.push("Trial optimization limit reached. Contact support to upgrade.");
|
|
3850
|
+
}
|
|
3649
3851
|
if (!isJson) {
|
|
3650
|
-
console.error(chalk7.red(
|
|
3852
|
+
console.error(chalk7.red(`
|
|
3853
|
+
Optimization failed:`));
|
|
3651
3854
|
for (const msg of messages) {
|
|
3652
|
-
console.error(chalk7.red(`
|
|
3855
|
+
console.error(chalk7.red(` ${msg}`));
|
|
3856
|
+
}
|
|
3857
|
+
if (suggestions.length > 0) {
|
|
3858
|
+
console.error(chalk7.yellow(`
|
|
3859
|
+
Suggested fixes:`));
|
|
3860
|
+
for (const s of suggestions) {
|
|
3861
|
+
console.error(chalk7.yellow(` → ${s}`));
|
|
3862
|
+
}
|
|
3653
3863
|
}
|
|
3654
3864
|
console.error("");
|
|
3655
3865
|
console.error(PREREQUISITES_TEXT);
|
|
@@ -3894,216 +4104,20 @@ ${chalk8.dim("Exports to stdout by default. Use --output to save to a file.")}
|
|
|
3894
4104
|
init_config();
|
|
3895
4105
|
import { Command as Command5 } from "commander";
|
|
3896
4106
|
import chalk9 from "chalk";
|
|
3897
|
-
import { writeFileSync as writeFileSync3, existsSync as
|
|
4107
|
+
import { writeFileSync as writeFileSync3, existsSync as existsSync9 } from "fs";
|
|
3898
4108
|
import { execSync } from "child_process";
|
|
3899
4109
|
init_errors();
|
|
3900
4110
|
|
|
3901
|
-
// src/lib/integrations/mastra.ts
|
|
3902
|
-
import { readFileSync as readFileSync5, existsSync as existsSync5 } from "fs";
|
|
3903
|
-
function renderPrerequisites(config) {
|
|
3904
|
-
const keyPreview = config.apiKey.slice(0, 8) + "..." + config.apiKey.slice(-4);
|
|
3905
|
-
return `✓ MUTAGENT_API_KEY: ${keyPreview}
|
|
3906
|
-
✓ MUTAGENT_ENDPOINT: ${config.endpoint}
|
|
3907
|
-
✓ API Connection: Verified`;
|
|
3908
|
-
}
|
|
3909
|
-
var mastraIntegration = {
|
|
3910
|
-
name: "mastra",
|
|
3911
|
-
description: "Mastra AI framework",
|
|
3912
|
-
async detect() {
|
|
3913
|
-
const files = ["mastra.config.ts", "mastra.config.js"];
|
|
3914
|
-
const found = [];
|
|
3915
|
-
for (const file of files) {
|
|
3916
|
-
if (existsSync5(file)) {
|
|
3917
|
-
found.push(file);
|
|
3918
|
-
}
|
|
3919
|
-
}
|
|
3920
|
-
let hasMastraDep = false;
|
|
3921
|
-
if (existsSync5("package.json")) {
|
|
3922
|
-
try {
|
|
3923
|
-
const pkg = JSON.parse(readFileSync5("package.json", "utf-8"));
|
|
3924
|
-
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
3925
|
-
hasMastraDep = "@mastra/core" in deps;
|
|
3926
|
-
} catch {}
|
|
3927
|
-
}
|
|
3928
|
-
return {
|
|
3929
|
-
detected: found.length > 0 || hasMastraDep,
|
|
3930
|
-
confidence: found.length > 0 ? 0.95 : hasMastraDep ? 0.7 : 0,
|
|
3931
|
-
files: found
|
|
3932
|
-
};
|
|
3933
|
-
},
|
|
3934
|
-
async generate(config) {
|
|
3935
|
-
return `---
|
|
3936
|
-
name: mutagent-mastra-integration
|
|
3937
|
-
description: Integrate MutagenT with Mastra framework for prompt optimization and trace observability
|
|
3938
|
-
framework: mastra
|
|
3939
|
-
version: 1.0.0
|
|
3940
|
-
---
|
|
3941
|
-
|
|
3942
|
-
# MutagenT + Mastra Integration
|
|
3943
|
-
|
|
3944
|
-
## Prerequisites Verification
|
|
3945
|
-
|
|
3946
|
-
${renderPrerequisites(config)}
|
|
3947
|
-
|
|
3948
|
-
## Installation
|
|
3949
|
-
|
|
3950
|
-
\`\`\`bash
|
|
3951
|
-
bun add @mutagent/sdk
|
|
3952
|
-
# or
|
|
3953
|
-
npm install @mutagent/sdk
|
|
3954
|
-
\`\`\`
|
|
3955
|
-
|
|
3956
|
-
## Configuration
|
|
3957
|
-
|
|
3958
|
-
### 1. Environment Variables
|
|
3959
|
-
|
|
3960
|
-
Add to your \`.env\` file:
|
|
3961
|
-
|
|
3962
|
-
\`\`\`env
|
|
3963
|
-
MUTAGENT_API_KEY=${config.apiKey}
|
|
3964
|
-
MUTAGENT_ENDPOINT=${config.endpoint}
|
|
3965
|
-
\`\`\`
|
|
3966
|
-
|
|
3967
|
-
### 2. Mastra Config Integration
|
|
3968
|
-
|
|
3969
|
-
Update \`mastra.config.ts\`:
|
|
3970
|
-
|
|
3971
|
-
\`\`\`typescript
|
|
3972
|
-
import { defineConfig } from '@mastra/core';
|
|
3973
|
-
import { MutagentObserver } from '@mutagent/sdk/mastra';
|
|
3974
|
-
|
|
3975
|
-
export default defineConfig({
|
|
3976
|
-
observers: [
|
|
3977
|
-
new MutagentObserver({
|
|
3978
|
-
apiKey: process.env.MUTAGENT_API_KEY!,
|
|
3979
|
-
endpoint: process.env.MUTAGENT_ENDPOINT,
|
|
3980
|
-
// Optional: auto-capture all agent traces
|
|
3981
|
-
captureTraces: true,
|
|
3982
|
-
})
|
|
3983
|
-
],
|
|
3984
|
-
});
|
|
3985
|
-
\`\`\`
|
|
3986
|
-
|
|
3987
|
-
### 3. Per-Agent Configuration
|
|
3988
|
-
|
|
3989
|
-
For specific agents only:
|
|
3990
|
-
|
|
3991
|
-
\`\`\`typescript
|
|
3992
|
-
import { Agent } from '@mastra/core';
|
|
3993
|
-
import { withMutagent } from '@mutagent/sdk/mastra';
|
|
3994
|
-
|
|
3995
|
-
const agent = new Agent({
|
|
3996
|
-
name: 'support-agent',
|
|
3997
|
-
instructions: '...',
|
|
3998
|
-
});
|
|
3999
|
-
|
|
4000
|
-
// Wrap with MutagenT observability
|
|
4001
|
-
export default withMutagent(agent, {
|
|
4002
|
-
promptId: 'support-template',
|
|
4003
|
-
autoOptimize: true,
|
|
4004
|
-
});
|
|
4005
|
-
\`\`\`
|
|
4006
|
-
|
|
4007
|
-
## Usage
|
|
4008
|
-
|
|
4009
|
-
### Trace Collection (Replaces Langfuse)
|
|
4010
|
-
|
|
4011
|
-
All agent calls are automatically traced to MutagenT:
|
|
4012
|
-
|
|
4013
|
-
\`\`\`typescript
|
|
4014
|
-
const result = await agent.generate('How do I reset my password?');
|
|
4015
|
-
// Trace automatically captured with latency, tokens, input/output
|
|
4016
|
-
\`\`\`
|
|
4017
|
-
|
|
4018
|
-
### Prompt Optimization
|
|
4019
|
-
|
|
4020
|
-
\`\`\`typescript
|
|
4021
|
-
import { optimizePrompt } from '@mutagent/sdk';
|
|
4022
|
-
|
|
4023
|
-
// Run optimization for a prompt
|
|
4024
|
-
const optimized = await optimizePrompt({
|
|
4025
|
-
promptId: 'support-template',
|
|
4026
|
-
datasetId: 'support-tickets',
|
|
4027
|
-
metric: 'response_quality',
|
|
4028
|
-
});
|
|
4029
|
-
|
|
4030
|
-
// Update agent with optimized prompt
|
|
4031
|
-
agent.instructions = optimized.content;
|
|
4032
|
-
\`\`\`
|
|
4033
|
-
|
|
4034
|
-
### Manual Tracing
|
|
4035
|
-
|
|
4036
|
-
For custom traces:
|
|
4037
|
-
|
|
4038
|
-
\`\`\`typescript
|
|
4039
|
-
import { trace } from '@mutagent/sdk';
|
|
4040
|
-
|
|
4041
|
-
const span = trace.start({
|
|
4042
|
-
name: 'custom-operation',
|
|
4043
|
-
promptId: 'my-prompt',
|
|
4044
|
-
});
|
|
4045
|
-
|
|
4046
|
-
try {
|
|
4047
|
-
const result = await doSomething();
|
|
4048
|
-
span.end({ output: result });
|
|
4049
|
-
} catch (error) {
|
|
4050
|
-
span.error(error);
|
|
4051
|
-
}
|
|
4052
|
-
\`\`\`
|
|
4053
|
-
|
|
4054
|
-
## Migration from Langfuse
|
|
4055
|
-
|
|
4056
|
-
Replace Langfuse imports:
|
|
4057
|
-
|
|
4058
|
-
\`\`\`typescript
|
|
4059
|
-
// Before
|
|
4060
|
-
import { Langfuse } from 'langfuse';
|
|
4061
|
-
|
|
4062
|
-
// After
|
|
4063
|
-
import { MutagentObserver } from '@mutagent/sdk/mastra';
|
|
4064
|
-
\`\`\`
|
|
4065
|
-
|
|
4066
|
-
## Verification
|
|
4067
|
-
|
|
4068
|
-
Run this to verify your integration:
|
|
4069
|
-
|
|
4070
|
-
\`\`\`bash
|
|
4071
|
-
mutagent integrate mastra --verify
|
|
4072
|
-
\`\`\`
|
|
4073
|
-
|
|
4074
|
-
## Next Steps
|
|
4075
|
-
|
|
4076
|
-
1. Create your first prompt: \`mutagent prompts create --interactive\`
|
|
4077
|
-
2. Add a dataset: \`mutagent prompts datasets:add <prompt-id> --file data.jsonl\`
|
|
4078
|
-
3. Run optimization: \`mutagent prompts optimize <prompt-id> --dataset <dataset-id>\`
|
|
4079
|
-
4. View traces: \`mutagent traces list --prompt <prompt-id>\`
|
|
4080
|
-
|
|
4081
|
-
## CLI Commands Reference
|
|
4082
|
-
|
|
4083
|
-
\`\`\`bash
|
|
4084
|
-
# List prompts
|
|
4085
|
-
mutagent prompts list
|
|
4086
|
-
|
|
4087
|
-
# Get prompt with traces
|
|
4088
|
-
mutagent prompts get <id> --with-datasets
|
|
4089
|
-
|
|
4090
|
-
# Analyze traces
|
|
4091
|
-
mutagent traces analyze <prompt-id>
|
|
4092
|
-
\`\`\`
|
|
4093
|
-
`;
|
|
4094
|
-
}
|
|
4095
|
-
};
|
|
4096
|
-
|
|
4097
4111
|
// src/lib/integrations/langchain.ts
|
|
4098
|
-
import { readFileSync as
|
|
4112
|
+
import { readFileSync as readFileSync5, existsSync as existsSync5 } from "fs";
|
|
4099
4113
|
var langchainIntegration = {
|
|
4100
4114
|
name: "langchain",
|
|
4101
4115
|
description: "LangChain framework",
|
|
4102
4116
|
async detect() {
|
|
4103
4117
|
let hasLangchain = false;
|
|
4104
|
-
if (
|
|
4118
|
+
if (existsSync5("package.json")) {
|
|
4105
4119
|
try {
|
|
4106
|
-
const pkg = JSON.parse(
|
|
4120
|
+
const pkg = JSON.parse(readFileSync5("package.json", "utf-8"));
|
|
4107
4121
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
4108
4122
|
hasLangchain = "langchain" in deps || "@langchain/core" in deps;
|
|
4109
4123
|
} catch {}
|
|
@@ -4235,15 +4249,15 @@ mutagent traces analyze <prompt-id>
|
|
|
4235
4249
|
};
|
|
4236
4250
|
|
|
4237
4251
|
// src/lib/integrations/langgraph.ts
|
|
4238
|
-
import { readFileSync as
|
|
4252
|
+
import { readFileSync as readFileSync6, existsSync as existsSync6 } from "fs";
|
|
4239
4253
|
var langgraphIntegration = {
|
|
4240
4254
|
name: "langgraph",
|
|
4241
4255
|
description: "LangGraph agent workflow framework",
|
|
4242
4256
|
async detect() {
|
|
4243
4257
|
let hasLanggraph = false;
|
|
4244
|
-
if (
|
|
4258
|
+
if (existsSync6("package.json")) {
|
|
4245
4259
|
try {
|
|
4246
|
-
const pkg = JSON.parse(
|
|
4260
|
+
const pkg = JSON.parse(readFileSync6("package.json", "utf-8"));
|
|
4247
4261
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
4248
4262
|
hasLanggraph = "@langchain/langgraph" in deps;
|
|
4249
4263
|
} catch {}
|
|
@@ -4259,7 +4273,7 @@ var langgraphIntegration = {
|
|
|
4259
4273
|
name: mutagent-langgraph-integration
|
|
4260
4274
|
description: Integrate MutagenT with LangGraph for agent workflow observability
|
|
4261
4275
|
framework: langgraph
|
|
4262
|
-
version:
|
|
4276
|
+
version: 2.0.0
|
|
4263
4277
|
---
|
|
4264
4278
|
|
|
4265
4279
|
# MutagenT + LangGraph Integration
|
|
@@ -4270,33 +4284,51 @@ version: 1.0.0
|
|
|
4270
4284
|
- MUTAGENT_ENDPOINT: ${config.endpoint}
|
|
4271
4285
|
- API Connection: Verified
|
|
4272
4286
|
|
|
4287
|
+
> **Note**: LangGraph is built on LangChain. The same \`MutagentCallbackHandler\` from
|
|
4288
|
+
> \`@mutagent/langchain\` works for both LangChain and LangGraph — no separate package needed.
|
|
4289
|
+
|
|
4273
4290
|
## Installation
|
|
4274
4291
|
|
|
4275
4292
|
\`\`\`bash
|
|
4276
|
-
|
|
4277
|
-
# If you need to install manually:
|
|
4278
|
-
bun add @mutagent/langgraph
|
|
4293
|
+
bun add @mutagent/langchain @mutagent/sdk
|
|
4279
4294
|
# or
|
|
4280
|
-
npm install @mutagent/
|
|
4295
|
+
npm install @mutagent/langchain @mutagent/sdk
|
|
4281
4296
|
\`\`\`
|
|
4282
4297
|
|
|
4283
|
-
|
|
4298
|
+
> **Deprecation Notice**: The \`@mutagent/langgraph\` package is deprecated.
|
|
4299
|
+
> Use \`@mutagent/langchain\` instead — it supports both LangChain and LangGraph.
|
|
4284
4300
|
|
|
4285
|
-
|
|
4301
|
+
## Integration
|
|
4286
4302
|
|
|
4287
4303
|
\`\`\`typescript
|
|
4288
|
-
import {
|
|
4289
|
-
import { MutagentGraphTracer } from '@mutagent/langgraph';
|
|
4304
|
+
import { MutagentCallbackHandler } from '@mutagent/langchain';
|
|
4290
4305
|
import { initTracing } from '@mutagent/sdk/tracing';
|
|
4291
4306
|
|
|
4292
|
-
// Initialize tracing (
|
|
4293
|
-
initTracing({
|
|
4294
|
-
|
|
4295
|
-
|
|
4307
|
+
// Initialize tracing (once at app startup)
|
|
4308
|
+
initTracing({ apiKey: process.env.MUTAGENT_API_KEY! });
|
|
4309
|
+
|
|
4310
|
+
// Create the handler
|
|
4311
|
+
const handler = new MutagentCallbackHandler({
|
|
4312
|
+
sessionId: 'my-session', // optional
|
|
4313
|
+
userId: 'user-123', // optional
|
|
4296
4314
|
});
|
|
4297
4315
|
|
|
4298
|
-
//
|
|
4299
|
-
const
|
|
4316
|
+
// Pass to any LangGraph invoke/stream call
|
|
4317
|
+
const result = await graph.invoke(input, { callbacks: [handler] });
|
|
4318
|
+
\`\`\`
|
|
4319
|
+
|
|
4320
|
+
## Full Graph Example
|
|
4321
|
+
|
|
4322
|
+
\`\`\`typescript
|
|
4323
|
+
import { StateGraph, Annotation } from '@langchain/langgraph';
|
|
4324
|
+
import { ChatOpenAI } from '@langchain/openai';
|
|
4325
|
+
import { MutagentCallbackHandler } from '@mutagent/langchain';
|
|
4326
|
+
import { initTracing } from '@mutagent/sdk/tracing';
|
|
4327
|
+
|
|
4328
|
+
// Initialize tracing (once at app startup)
|
|
4329
|
+
initTracing({ apiKey: process.env.MUTAGENT_API_KEY! });
|
|
4330
|
+
|
|
4331
|
+
const handler = new MutagentCallbackHandler();
|
|
4300
4332
|
|
|
4301
4333
|
// Define your graph as usual
|
|
4302
4334
|
const StateAnnotation = Annotation.Root({
|
|
@@ -4310,29 +4342,24 @@ const graph = new StateGraph(StateAnnotation)
|
|
|
4310
4342
|
.addEdge('__start__', 'agent')
|
|
4311
4343
|
.compile();
|
|
4312
4344
|
|
|
4313
|
-
//
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4345
|
+
// All nodes, edges, and LLM calls are automatically traced
|
|
4346
|
+
const result = await graph.invoke(
|
|
4347
|
+
{ input: 'Hello' },
|
|
4348
|
+
{ callbacks: [handler] },
|
|
4349
|
+
);
|
|
4317
4350
|
\`\`\`
|
|
4318
4351
|
|
|
4319
|
-
|
|
4352
|
+
## Streaming
|
|
4320
4353
|
|
|
4321
4354
|
\`\`\`typescript
|
|
4322
|
-
|
|
4323
|
-
tracer.handleNodeStart('agent', { query: 'Hello' });
|
|
4324
|
-
// ... node logic ...
|
|
4325
|
-
tracer.handleNodeEnd('agent', { result: 'response' });
|
|
4326
|
-
|
|
4327
|
-
// Track edge transitions
|
|
4328
|
-
tracer.handleEdgeTransition('agent', 'tools', {
|
|
4329
|
-
isConditional: true,
|
|
4330
|
-
condition: 'needsTools',
|
|
4331
|
-
conditionResult: true,
|
|
4332
|
-
});
|
|
4355
|
+
const handler = new MutagentCallbackHandler();
|
|
4333
4356
|
|
|
4334
|
-
|
|
4335
|
-
|
|
4357
|
+
for await (const event of graph.stream(
|
|
4358
|
+
{ input: 'Hello' },
|
|
4359
|
+
{ callbacks: [handler] },
|
|
4360
|
+
)) {
|
|
4361
|
+
console.log(event);
|
|
4362
|
+
}
|
|
4336
4363
|
\`\`\`
|
|
4337
4364
|
|
|
4338
4365
|
## Verification
|
|
@@ -4346,30 +4373,20 @@ mutagent integrate langgraph --verify
|
|
|
4346
4373
|
- Full guide: https://docs.mutagent.io/integrations/langgraph
|
|
4347
4374
|
- API Reference: https://docs.mutagent.io/sdk/tracing
|
|
4348
4375
|
- Dashboard: https://app.mutagent.io
|
|
4349
|
-
|
|
4350
|
-
## CLI Commands
|
|
4351
|
-
|
|
4352
|
-
\`\`\`bash
|
|
4353
|
-
# View workflow traces
|
|
4354
|
-
mutagent traces list --prompt <graph-id>
|
|
4355
|
-
|
|
4356
|
-
# Analyze node performance
|
|
4357
|
-
mutagent traces analyze <node-prompt-id>
|
|
4358
|
-
\`\`\`
|
|
4359
4376
|
`;
|
|
4360
4377
|
}
|
|
4361
4378
|
};
|
|
4362
4379
|
|
|
4363
4380
|
// src/lib/integrations/vercel-ai.ts
|
|
4364
|
-
import { readFileSync as
|
|
4381
|
+
import { readFileSync as readFileSync7, existsSync as existsSync7 } from "fs";
|
|
4365
4382
|
var vercelAiIntegration = {
|
|
4366
4383
|
name: "vercel-ai",
|
|
4367
4384
|
description: "Vercel AI SDK",
|
|
4368
4385
|
async detect() {
|
|
4369
4386
|
let hasAiSdk = false;
|
|
4370
|
-
if (
|
|
4387
|
+
if (existsSync7("package.json")) {
|
|
4371
4388
|
try {
|
|
4372
|
-
const pkg = JSON.parse(
|
|
4389
|
+
const pkg = JSON.parse(readFileSync7("package.json", "utf-8"));
|
|
4373
4390
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
4374
4391
|
hasAiSdk = "ai" in deps;
|
|
4375
4392
|
} catch {}
|
|
@@ -4385,7 +4402,7 @@ var vercelAiIntegration = {
|
|
|
4385
4402
|
name: mutagent-vercel-ai-integration
|
|
4386
4403
|
description: Integrate MutagenT with Vercel AI SDK for streaming and edge functions
|
|
4387
4404
|
framework: vercel-ai
|
|
4388
|
-
version:
|
|
4405
|
+
version: 2.0.0
|
|
4389
4406
|
---
|
|
4390
4407
|
|
|
4391
4408
|
# MutagenT + Vercel AI SDK Integration
|
|
@@ -4399,14 +4416,52 @@ version: 1.0.0
|
|
|
4399
4416
|
## Installation
|
|
4400
4417
|
|
|
4401
4418
|
\`\`\`bash
|
|
4402
|
-
|
|
4403
|
-
# If you need to install manually:
|
|
4404
|
-
bun add @mutagent/vercel-ai
|
|
4419
|
+
bun add @mutagent/vercel-ai @mutagent/sdk
|
|
4405
4420
|
# or
|
|
4406
|
-
npm install @mutagent/vercel-ai
|
|
4421
|
+
npm install @mutagent/vercel-ai @mutagent/sdk
|
|
4422
|
+
|
|
4423
|
+
# For Option A (OTel SpanExporter), also install:
|
|
4424
|
+
bun add @opentelemetry/sdk-trace-node @opentelemetry/sdk-trace-base
|
|
4407
4425
|
\`\`\`
|
|
4408
4426
|
|
|
4409
|
-
|
|
4427
|
+
---
|
|
4428
|
+
|
|
4429
|
+
## Option A (Recommended): OTel SpanExporter
|
|
4430
|
+
|
|
4431
|
+
Uses Vercel AI SDK's built-in \`experimental_telemetry\` with an OpenTelemetry exporter
|
|
4432
|
+
that sends spans directly to MutagenT.
|
|
4433
|
+
|
|
4434
|
+
\`\`\`typescript
|
|
4435
|
+
import { MutagentSpanExporter } from '@mutagent/vercel-ai';
|
|
4436
|
+
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
|
|
4437
|
+
import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base';
|
|
4438
|
+
import { initTracing } from '@mutagent/sdk/tracing';
|
|
4439
|
+
import { generateText } from 'ai';
|
|
4440
|
+
import { openai } from '@ai-sdk/openai';
|
|
4441
|
+
|
|
4442
|
+
// Initialize MutagenT tracing
|
|
4443
|
+
initTracing({ apiKey: process.env.MUTAGENT_API_KEY! });
|
|
4444
|
+
|
|
4445
|
+
// Set up OTel with MutagenT exporter
|
|
4446
|
+
const provider = new NodeTracerProvider();
|
|
4447
|
+
provider.addSpanProcessor(
|
|
4448
|
+
new SimpleSpanProcessor(new MutagentSpanExporter())
|
|
4449
|
+
);
|
|
4450
|
+
provider.register();
|
|
4451
|
+
|
|
4452
|
+
// Use Vercel AI SDK normally with telemetry enabled
|
|
4453
|
+
const result = await generateText({
|
|
4454
|
+
model: openai('gpt-4'),
|
|
4455
|
+
prompt: 'Hello!',
|
|
4456
|
+
experimental_telemetry: { isEnabled: true },
|
|
4457
|
+
});
|
|
4458
|
+
\`\`\`
|
|
4459
|
+
|
|
4460
|
+
---
|
|
4461
|
+
|
|
4462
|
+
## Option B (Alternative): Middleware
|
|
4463
|
+
|
|
4464
|
+
Uses the Vercel AI SDK \`wrapLanguageModel\` middleware pattern.
|
|
4410
4465
|
|
|
4411
4466
|
\`\`\`typescript
|
|
4412
4467
|
// app/api/chat/route.ts
|
|
@@ -4415,13 +4470,10 @@ import { openai } from '@ai-sdk/openai';
|
|
|
4415
4470
|
import { createMutagentMiddleware } from '@mutagent/vercel-ai';
|
|
4416
4471
|
import { initTracing } from '@mutagent/sdk/tracing';
|
|
4417
4472
|
|
|
4418
|
-
// Initialize tracing (
|
|
4419
|
-
initTracing({
|
|
4420
|
-
apiKey: process.env.MUTAGENT_API_KEY!,
|
|
4421
|
-
endpoint: process.env.MUTAGENT_ENDPOINT,
|
|
4422
|
-
});
|
|
4473
|
+
// Initialize tracing (once at app startup)
|
|
4474
|
+
initTracing({ apiKey: process.env.MUTAGENT_API_KEY! });
|
|
4423
4475
|
|
|
4424
|
-
// Create middleware
|
|
4476
|
+
// Create middleware
|
|
4425
4477
|
const middleware = createMutagentMiddleware();
|
|
4426
4478
|
|
|
4427
4479
|
// Wrap your model with MutagenT middleware
|
|
@@ -4467,30 +4519,20 @@ mutagent integrate vercel-ai --verify
|
|
|
4467
4519
|
- Full guide: https://docs.mutagent.io/integrations/vercel-ai
|
|
4468
4520
|
- API Reference: https://docs.mutagent.io/sdk/tracing
|
|
4469
4521
|
- Dashboard: https://app.mutagent.io
|
|
4470
|
-
|
|
4471
|
-
## CLI Commands
|
|
4472
|
-
|
|
4473
|
-
\`\`\`bash
|
|
4474
|
-
# View streaming traces
|
|
4475
|
-
mutagent traces list --prompt <prompt-id>
|
|
4476
|
-
|
|
4477
|
-
# Export for analysis
|
|
4478
|
-
mutagent traces export --prompt <prompt-id> --format json
|
|
4479
|
-
\`\`\`
|
|
4480
4522
|
`;
|
|
4481
4523
|
}
|
|
4482
4524
|
};
|
|
4483
4525
|
|
|
4484
4526
|
// src/lib/integrations/openai.ts
|
|
4485
|
-
import { readFileSync as
|
|
4527
|
+
import { readFileSync as readFileSync8, existsSync as existsSync8 } from "fs";
|
|
4486
4528
|
var openaiIntegration = {
|
|
4487
4529
|
name: "openai",
|
|
4488
4530
|
description: "OpenAI SDK integration with automatic tracing",
|
|
4489
4531
|
async detect() {
|
|
4490
4532
|
let hasOpenAI = false;
|
|
4491
|
-
if (
|
|
4533
|
+
if (existsSync8("package.json")) {
|
|
4492
4534
|
try {
|
|
4493
|
-
const pkg = JSON.parse(
|
|
4535
|
+
const pkg = JSON.parse(readFileSync8("package.json", "utf-8"));
|
|
4494
4536
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
4495
4537
|
hasOpenAI = "openai" in deps;
|
|
4496
4538
|
} catch {}
|
|
@@ -4506,7 +4548,7 @@ var openaiIntegration = {
|
|
|
4506
4548
|
name: mutagent-openai-integration
|
|
4507
4549
|
description: Integrate MutagenT with OpenAI SDK for automatic tracing
|
|
4508
4550
|
framework: openai
|
|
4509
|
-
version:
|
|
4551
|
+
version: 2.0.0
|
|
4510
4552
|
---
|
|
4511
4553
|
|
|
4512
4554
|
# MutagenT + OpenAI SDK Integration
|
|
@@ -4520,41 +4562,28 @@ version: 1.0.0
|
|
|
4520
4562
|
## Installation
|
|
4521
4563
|
|
|
4522
4564
|
\`\`\`bash
|
|
4523
|
-
|
|
4524
|
-
# If you need to install manually:
|
|
4525
|
-
bun add @mutagent/openai
|
|
4565
|
+
bun add @mutagent/openai @mutagent/sdk
|
|
4526
4566
|
# or
|
|
4527
|
-
npm install @mutagent/openai
|
|
4567
|
+
npm install @mutagent/openai @mutagent/sdk
|
|
4528
4568
|
\`\`\`
|
|
4529
4569
|
|
|
4530
|
-
##
|
|
4531
|
-
|
|
4532
|
-
### 1. Environment Variables
|
|
4533
|
-
|
|
4534
|
-
\`\`\`env
|
|
4535
|
-
MUTAGENT_API_KEY=${config.apiKey}
|
|
4536
|
-
MUTAGENT_ENDPOINT=${config.endpoint}
|
|
4537
|
-
OPENAI_API_KEY=your-openai-api-key
|
|
4538
|
-
\`\`\`
|
|
4539
|
-
|
|
4540
|
-
### 2. Traced OpenAI Client
|
|
4570
|
+
## Integration
|
|
4541
4571
|
|
|
4542
4572
|
\`\`\`typescript
|
|
4543
|
-
import
|
|
4573
|
+
import OpenAI from 'openai';
|
|
4574
|
+
import { observeOpenAI } from '@mutagent/openai';
|
|
4544
4575
|
import { initTracing } from '@mutagent/sdk/tracing';
|
|
4545
4576
|
|
|
4546
|
-
// Initialize tracing (
|
|
4547
|
-
initTracing({
|
|
4548
|
-
apiKey: process.env.MUTAGENT_API_KEY!,
|
|
4549
|
-
endpoint: process.env.MUTAGENT_ENDPOINT,
|
|
4550
|
-
});
|
|
4577
|
+
// Initialize tracing (once at app startup)
|
|
4578
|
+
initTracing({ apiKey: process.env.MUTAGENT_API_KEY! });
|
|
4551
4579
|
|
|
4552
|
-
//
|
|
4553
|
-
const openai = new
|
|
4554
|
-
|
|
4580
|
+
// Wrap the OpenAI client — ALL methods are automatically traced
|
|
4581
|
+
const openai = observeOpenAI(new OpenAI(), {
|
|
4582
|
+
sessionId: 'my-session', // optional
|
|
4583
|
+
userId: 'user-123', // optional
|
|
4555
4584
|
});
|
|
4556
4585
|
|
|
4557
|
-
//
|
|
4586
|
+
// Use exactly as normal — chat, embeddings, images, audio all work
|
|
4558
4587
|
const completion = await openai.chat.completions.create({
|
|
4559
4588
|
model: 'gpt-4o',
|
|
4560
4589
|
messages: [{ role: 'user', content: 'Hello!' }],
|
|
@@ -4563,21 +4592,12 @@ const completion = await openai.chat.completions.create({
|
|
|
4563
4592
|
console.log(completion.choices[0].message.content);
|
|
4564
4593
|
\`\`\`
|
|
4565
4594
|
|
|
4566
|
-
|
|
4595
|
+
ALL OpenAI SDK methods are preserved and traced automatically.
|
|
4596
|
+
No API changes — just wrap your client and everything is observed.
|
|
4567
4597
|
|
|
4568
|
-
|
|
4598
|
+
## Streaming
|
|
4569
4599
|
|
|
4570
|
-
|
|
4571
|
-
const response = await openai.chat.completions.create({
|
|
4572
|
-
model: 'gpt-4o',
|
|
4573
|
-
messages: [
|
|
4574
|
-
{ role: 'system', content: 'You are a helpful assistant.' },
|
|
4575
|
-
{ role: 'user', content: 'What is TypeScript?' },
|
|
4576
|
-
],
|
|
4577
|
-
});
|
|
4578
|
-
\`\`\`
|
|
4579
|
-
|
|
4580
|
-
### Streaming
|
|
4600
|
+
Streaming works out of the box with no extra configuration:
|
|
4581
4601
|
|
|
4582
4602
|
\`\`\`typescript
|
|
4583
4603
|
const stream = await openai.chat.completions.create({
|
|
@@ -4591,299 +4611,39 @@ for await (const chunk of stream) {
|
|
|
4591
4611
|
}
|
|
4592
4612
|
\`\`\`
|
|
4593
4613
|
|
|
4594
|
-
##
|
|
4595
|
-
|
|
4596
|
-
\`\`\`bash
|
|
4597
|
-
mutagent integrate openai --verify
|
|
4598
|
-
\`\`\`
|
|
4599
|
-
|
|
4600
|
-
## Documentation
|
|
4601
|
-
|
|
4602
|
-
- Full guide: https://docs.mutagent.io/integrations/openai
|
|
4603
|
-
- API Reference: https://docs.mutagent.io/sdk/tracing
|
|
4604
|
-
- Dashboard: https://app.mutagent.io
|
|
4605
|
-
|
|
4606
|
-
## CLI Reference
|
|
4607
|
-
|
|
4608
|
-
\`\`\`bash
|
|
4609
|
-
# View traces
|
|
4610
|
-
mutagent traces list --prompt <prompt-id>
|
|
4611
|
-
|
|
4612
|
-
# Analyze performance
|
|
4613
|
-
mutagent traces analyze <prompt-id>
|
|
4614
|
-
|
|
4615
|
-
# Export traces
|
|
4616
|
-
mutagent traces export --format json
|
|
4617
|
-
\`\`\`
|
|
4618
|
-
`;
|
|
4619
|
-
}
|
|
4620
|
-
};
|
|
4621
|
-
|
|
4622
|
-
// src/lib/integrations/claude-code.ts
|
|
4623
|
-
import { readFileSync as readFileSync10, existsSync as existsSync10 } from "fs";
|
|
4624
|
-
var claudeCodeIntegration = {
|
|
4625
|
-
name: "claude-code",
|
|
4626
|
-
description: "Claude Code SDK",
|
|
4627
|
-
async detect() {
|
|
4628
|
-
let hasClaudeCode = false;
|
|
4629
|
-
if (existsSync10("package.json")) {
|
|
4630
|
-
try {
|
|
4631
|
-
const pkg = JSON.parse(readFileSync10("package.json", "utf-8"));
|
|
4632
|
-
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
4633
|
-
hasClaudeCode = "@anthropic-ai/claude-code" in deps || "@anthropic-ai/sdk" in deps;
|
|
4634
|
-
} catch {}
|
|
4635
|
-
}
|
|
4636
|
-
return {
|
|
4637
|
-
detected: hasClaudeCode,
|
|
4638
|
-
confidence: hasClaudeCode ? 0.85 : 0,
|
|
4639
|
-
files: hasClaudeCode ? ["package.json"] : []
|
|
4640
|
-
};
|
|
4641
|
-
},
|
|
4642
|
-
async generate(config) {
|
|
4643
|
-
return `---
|
|
4644
|
-
name: mutagent-claude-code-integration
|
|
4645
|
-
description: Integrate MutagenT with Claude Code SDK
|
|
4646
|
-
framework: claude-code
|
|
4647
|
-
version: 1.0.0
|
|
4648
|
-
---
|
|
4649
|
-
|
|
4650
|
-
# MutagenT + Claude Code SDK Integration
|
|
4651
|
-
|
|
4652
|
-
## Prerequisites Verification
|
|
4653
|
-
|
|
4654
|
-
✓ MUTAGENT_API_KEY: ${config.apiKey.slice(0, 8)}...${config.apiKey.slice(-4)}
|
|
4655
|
-
✓ MUTAGENT_ENDPOINT: ${config.endpoint}
|
|
4656
|
-
✓ API Connection: Verified
|
|
4657
|
-
|
|
4658
|
-
## Installation
|
|
4659
|
-
|
|
4660
|
-
\`\`\`bash
|
|
4661
|
-
bun add @mutagent/sdk
|
|
4662
|
-
\`\`\`
|
|
4663
|
-
|
|
4664
|
-
## Basic Integration
|
|
4614
|
+
## Embeddings
|
|
4665
4615
|
|
|
4666
4616
|
\`\`\`typescript
|
|
4667
|
-
|
|
4668
|
-
|
|
4669
|
-
|
|
4670
|
-
const tracer = new MutagentTracer({
|
|
4671
|
-
apiKey: process.env.MUTAGENT_API_KEY!,
|
|
4672
|
-
endpoint: process.env.MUTAGENT_ENDPOINT,
|
|
4673
|
-
promptId: 'claude-prompt',
|
|
4674
|
-
});
|
|
4675
|
-
|
|
4676
|
-
const anthropic = new Anthropic({
|
|
4677
|
-
apiKey: process.env.ANTHROPIC_API_KEY!,
|
|
4617
|
+
const embedding = await openai.embeddings.create({
|
|
4618
|
+
model: 'text-embedding-3-small',
|
|
4619
|
+
input: 'Hello world',
|
|
4678
4620
|
});
|
|
4679
|
-
|
|
4680
|
-
// Wrap API calls
|
|
4681
|
-
const response = await tracer.wrap(
|
|
4682
|
-
() => anthropic.messages.create({
|
|
4683
|
-
model: 'claude-3-5-sonnet-20241022',
|
|
4684
|
-
max_tokens: 1024,
|
|
4685
|
-
messages: [{ role: 'user', content: 'Hello!' }],
|
|
4686
|
-
})
|
|
4687
|
-
);
|
|
4688
|
-
\`\`\`
|
|
4689
|
-
|
|
4690
|
-
## With Optimized Prompts
|
|
4691
|
-
|
|
4692
|
-
\`\`\`typescript
|
|
4693
|
-
import { getOptimizedPrompt } from '@mutagent/sdk';
|
|
4694
|
-
|
|
4695
|
-
const optimized = await getOptimizedPrompt('my-template');
|
|
4696
|
-
|
|
4697
|
-
const response = await tracer.wrap(
|
|
4698
|
-
() => anthropic.messages.create({
|
|
4699
|
-
model: 'claude-3-5-sonnet-20241022',
|
|
4700
|
-
system: optimized,
|
|
4701
|
-
messages,
|
|
4702
|
-
})
|
|
4703
|
-
);
|
|
4704
|
-
\`\`\`
|
|
4705
|
-
|
|
4706
|
-
## MCP Server Integration
|
|
4707
|
-
|
|
4708
|
-
For Claude Desktop / MCP:
|
|
4709
|
-
|
|
4710
|
-
\`\`\`json
|
|
4711
|
-
{
|
|
4712
|
-
"mcpServers": {
|
|
4713
|
-
"mutagent": {
|
|
4714
|
-
"command": "npx",
|
|
4715
|
-
"args": ["-y", "@mutagent/mcp-server"],
|
|
4716
|
-
"env": {
|
|
4717
|
-
"MUTAGENT_API_KEY": "${config.apiKey}"
|
|
4718
|
-
}
|
|
4719
|
-
}
|
|
4720
|
-
}
|
|
4721
|
-
}
|
|
4722
|
-
\`\`\`
|
|
4723
|
-
|
|
4724
|
-
## Verification
|
|
4725
|
-
|
|
4726
|
-
\`\`\`bash
|
|
4727
|
-
mutagent integrate claude-code --verify
|
|
4728
|
-
\`\`\`
|
|
4729
|
-
|
|
4730
|
-
## CLI Commands
|
|
4731
|
-
|
|
4732
|
-
\`\`\`bash
|
|
4733
|
-
# View Claude traces
|
|
4734
|
-
mutagent traces list --prompt <prompt-id>
|
|
4735
|
-
|
|
4736
|
-
# Optimize Claude prompts
|
|
4737
|
-
mutagent prompts optimize <prompt-id> --dataset <dataset-id>
|
|
4738
|
-
\`\`\`
|
|
4739
|
-
`;
|
|
4740
|
-
}
|
|
4741
|
-
};
|
|
4742
|
-
|
|
4743
|
-
// src/lib/integrations/generic.ts
|
|
4744
|
-
var genericIntegration = {
|
|
4745
|
-
name: "generic",
|
|
4746
|
-
description: "Generic OpenAI-compatible integration",
|
|
4747
|
-
async detect() {
|
|
4748
|
-
return {
|
|
4749
|
-
detected: false,
|
|
4750
|
-
confidence: 0,
|
|
4751
|
-
files: []
|
|
4752
|
-
};
|
|
4753
|
-
},
|
|
4754
|
-
async generate(config) {
|
|
4755
|
-
return `---
|
|
4756
|
-
name: mutagent-generic-integration
|
|
4757
|
-
description: Generic OpenAI-compatible API integration
|
|
4758
|
-
framework: generic
|
|
4759
|
-
version: 1.0.0
|
|
4760
|
-
---
|
|
4761
|
-
|
|
4762
|
-
# MutagenT + Generic (OpenAI-compatible) Integration
|
|
4763
|
-
|
|
4764
|
-
## Prerequisites Verification
|
|
4765
|
-
|
|
4766
|
-
✓ MUTAGENT_API_KEY: ${config.apiKey.slice(0, 8)}...${config.apiKey.slice(-4)}
|
|
4767
|
-
✓ MUTAGENT_ENDPOINT: ${config.endpoint}
|
|
4768
|
-
✓ API Connection: Verified
|
|
4769
|
-
|
|
4770
|
-
## Installation
|
|
4771
|
-
|
|
4772
|
-
\`\`\`bash
|
|
4773
|
-
bun add @mutagent/sdk
|
|
4774
|
-
\`\`\`
|
|
4775
|
-
|
|
4776
|
-
## Fetch-based Integration
|
|
4777
|
-
|
|
4778
|
-
\`\`\`typescript
|
|
4779
|
-
import { trace } from '@mutagent/sdk';
|
|
4780
|
-
|
|
4781
|
-
async function callLLM(prompt: string) {
|
|
4782
|
-
const span = trace.start({
|
|
4783
|
-
name: 'llm-call',
|
|
4784
|
-
promptId: 'my-prompt',
|
|
4785
|
-
input: { prompt },
|
|
4786
|
-
});
|
|
4787
|
-
|
|
4788
|
-
const start = Date.now();
|
|
4789
|
-
|
|
4790
|
-
try {
|
|
4791
|
-
const response = await fetch('https://api.openai.com/v1/chat/completions', {
|
|
4792
|
-
method: 'POST',
|
|
4793
|
-
headers: {
|
|
4794
|
-
'Authorization': \`Bearer \${process.env.OPENAI_API_KEY}\`,
|
|
4795
|
-
'Content-Type': 'application/json',
|
|
4796
|
-
},
|
|
4797
|
-
body: JSON.stringify({
|
|
4798
|
-
model: 'gpt-4o',
|
|
4799
|
-
messages: [{ role: 'user', content: prompt }],
|
|
4800
|
-
}),
|
|
4801
|
-
});
|
|
4802
|
-
|
|
4803
|
-
const data = await response.json();
|
|
4804
|
-
const latency = Date.now() - start;
|
|
4805
|
-
|
|
4806
|
-
span.end({
|
|
4807
|
-
output: data,
|
|
4808
|
-
latency,
|
|
4809
|
-
tokens: {
|
|
4810
|
-
input: data.usage?.prompt_tokens || 0,
|
|
4811
|
-
output: data.usage?.completion_tokens || 0,
|
|
4812
|
-
},
|
|
4813
|
-
});
|
|
4814
|
-
|
|
4815
|
-
return data;
|
|
4816
|
-
} catch (error) {
|
|
4817
|
-
span.error(error);
|
|
4818
|
-
throw error;
|
|
4819
|
-
}
|
|
4820
|
-
}
|
|
4821
|
-
\`\`\`
|
|
4822
|
-
|
|
4823
|
-
## With Optimized Prompts
|
|
4824
|
-
|
|
4825
|
-
\`\`\`typescript
|
|
4826
|
-
import { getOptimizedPrompt } from '@mutagent/sdk';
|
|
4827
|
-
|
|
4828
|
-
const optimized = await getOptimizedPrompt('template-id');
|
|
4829
|
-
const result = await callLLM(optimized);
|
|
4830
|
-
\`\`\`
|
|
4831
|
-
|
|
4832
|
-
## OpenAI SDK Wrapper
|
|
4833
|
-
|
|
4834
|
-
\`\`\`typescript
|
|
4835
|
-
import OpenAI from 'openai';
|
|
4836
|
-
import { wrapOpenAI } from '@mutagent/sdk/openai';
|
|
4837
|
-
|
|
4838
|
-
const openai = wrapOpenAI(
|
|
4839
|
-
new OpenAI({ apiKey: process.env.OPENAI_API_KEY }),
|
|
4840
|
-
{
|
|
4841
|
-
mutagentApiKey: process.env.MUTAGENT_API_KEY!,
|
|
4842
|
-
promptId: 'default',
|
|
4843
|
-
}
|
|
4844
|
-
);
|
|
4845
|
-
|
|
4846
|
-
// All calls are traced
|
|
4847
|
-
const completion = await openai.chat.completions.create({...});
|
|
4621
|
+
// Embedding call is traced automatically
|
|
4848
4622
|
\`\`\`
|
|
4849
4623
|
|
|
4850
4624
|
## Verification
|
|
4851
4625
|
|
|
4852
4626
|
\`\`\`bash
|
|
4853
|
-
mutagent integrate
|
|
4627
|
+
mutagent integrate openai --verify
|
|
4854
4628
|
\`\`\`
|
|
4855
4629
|
|
|
4856
|
-
##
|
|
4857
|
-
|
|
4858
|
-
\`\`\`bash
|
|
4859
|
-
# View traces
|
|
4860
|
-
mutagent traces list --prompt <prompt-id>
|
|
4630
|
+
## Documentation
|
|
4861
4631
|
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
4632
|
+
- Full guide: https://docs.mutagent.io/integrations/openai
|
|
4633
|
+
- API Reference: https://docs.mutagent.io/sdk/tracing
|
|
4634
|
+
- Dashboard: https://app.mutagent.io
|
|
4865
4635
|
`;
|
|
4866
4636
|
}
|
|
4867
4637
|
};
|
|
4868
4638
|
|
|
4869
4639
|
// src/lib/integrations/registry.ts
|
|
4870
4640
|
var frameworkRegistry = new Map([
|
|
4871
|
-
["mastra", mastraIntegration],
|
|
4872
4641
|
["langchain", langchainIntegration],
|
|
4873
4642
|
["langgraph", langgraphIntegration],
|
|
4874
4643
|
["vercel-ai", vercelAiIntegration],
|
|
4875
|
-
["openai", openaiIntegration]
|
|
4876
|
-
["claude-code", claudeCodeIntegration],
|
|
4877
|
-
["generic", genericIntegration]
|
|
4644
|
+
["openai", openaiIntegration]
|
|
4878
4645
|
]);
|
|
4879
4646
|
var frameworkMetadata = [
|
|
4880
|
-
{
|
|
4881
|
-
name: "mastra",
|
|
4882
|
-
displayName: "Mastra",
|
|
4883
|
-
description: "Modern AI agent framework with observability built-in",
|
|
4884
|
-
npmPackage: "@mastra/core",
|
|
4885
|
-
website: "https://mastra.ai"
|
|
4886
|
-
},
|
|
4887
4647
|
{
|
|
4888
4648
|
name: "langchain",
|
|
4889
4649
|
displayName: "LangChain",
|
|
@@ -4897,7 +4657,7 @@ var frameworkMetadata = [
|
|
|
4897
4657
|
displayName: "LangGraph",
|
|
4898
4658
|
description: "Agent workflow framework built on LangChain",
|
|
4899
4659
|
npmPackage: "@langchain/langgraph",
|
|
4900
|
-
mutagentPackage: "@mutagent/
|
|
4660
|
+
mutagentPackage: "@mutagent/langchain",
|
|
4901
4661
|
website: "https://langchain-ai.github.io/langgraphjs/"
|
|
4902
4662
|
},
|
|
4903
4663
|
{
|
|
@@ -4915,20 +4675,6 @@ var frameworkMetadata = [
|
|
|
4915
4675
|
npmPackage: "openai",
|
|
4916
4676
|
mutagentPackage: "@mutagent/openai",
|
|
4917
4677
|
website: "https://platform.openai.com"
|
|
4918
|
-
},
|
|
4919
|
-
{
|
|
4920
|
-
name: "claude-code",
|
|
4921
|
-
displayName: "Claude Code SDK",
|
|
4922
|
-
description: "Native Anthropic integration for Claude",
|
|
4923
|
-
npmPackage: "@anthropic-ai/claude-code",
|
|
4924
|
-
website: "https://docs.anthropic.com"
|
|
4925
|
-
},
|
|
4926
|
-
{
|
|
4927
|
-
name: "generic",
|
|
4928
|
-
displayName: "Generic (OpenAI-compatible)",
|
|
4929
|
-
description: "Any OpenAI-compatible API endpoint",
|
|
4930
|
-
npmPackage: "openai",
|
|
4931
|
-
website: "https://platform.openai.com"
|
|
4932
4678
|
}
|
|
4933
4679
|
];
|
|
4934
4680
|
function getFramework(name) {
|
|
@@ -4940,16 +4686,16 @@ function getFrameworkMetadata(name) {
|
|
|
4940
4686
|
|
|
4941
4687
|
// src/commands/integrate.ts
|
|
4942
4688
|
function detectPackageManager() {
|
|
4943
|
-
if (
|
|
4689
|
+
if (existsSync9("bun.lockb") || existsSync9("bun.lock")) {
|
|
4944
4690
|
return "bun";
|
|
4945
4691
|
}
|
|
4946
|
-
if (
|
|
4692
|
+
if (existsSync9("pnpm-lock.yaml")) {
|
|
4947
4693
|
return "pnpm";
|
|
4948
4694
|
}
|
|
4949
|
-
if (
|
|
4695
|
+
if (existsSync9("yarn.lock")) {
|
|
4950
4696
|
return "yarn";
|
|
4951
4697
|
}
|
|
4952
|
-
if (
|
|
4698
|
+
if (existsSync9("package-lock.json")) {
|
|
4953
4699
|
return "npm";
|
|
4954
4700
|
}
|
|
4955
4701
|
try {
|
|
@@ -4978,8 +4724,6 @@ AI AGENT: Please determine the framework by:
|
|
|
4978
4724
|
- \`@langchain/langgraph\` -> use \`mutagent integrate langgraph\`
|
|
4979
4725
|
- \`ai\` (vercel) -> use \`mutagent integrate vercel-ai\`
|
|
4980
4726
|
- \`openai\` -> use \`mutagent integrate openai\`
|
|
4981
|
-
- \`@mastra/core\` -> use \`mutagent integrate mastra\`
|
|
4982
|
-
- \`@anthropic-ai/claude-code\` -> use \`mutagent integrate claude-code\`
|
|
4983
4727
|
|
|
4984
4728
|
### Option 2: Ask the user
|
|
4985
4729
|
"Which AI framework are you using?"
|
|
@@ -4987,9 +4731,6 @@ AI AGENT: Please determine the framework by:
|
|
|
4987
4731
|
- LangGraph
|
|
4988
4732
|
- Vercel AI SDK
|
|
4989
4733
|
- OpenAI SDK
|
|
4990
|
-
- Mastra
|
|
4991
|
-
- Claude Code
|
|
4992
|
-
- Generic (OpenAI-compatible)
|
|
4993
4734
|
|
|
4994
4735
|
### Next Steps
|
|
4995
4736
|
1. Once determined, run: \`mutagent integrate <framework>\`
|
|
@@ -5006,12 +4747,12 @@ Examples:
|
|
|
5006
4747
|
${chalk9.dim("$")} mutagent integrate langchain --output ./INTEGRATION.md
|
|
5007
4748
|
${chalk9.dim("$")} mutagent integrate --list # List available frameworks
|
|
5008
4749
|
|
|
5009
|
-
Frameworks:
|
|
4750
|
+
Frameworks: langchain, langgraph, vercel-ai, openai
|
|
5010
4751
|
|
|
5011
4752
|
This is a SKILL LOADER for AI coding agents (Claude Code, Cursor, etc.).
|
|
5012
4753
|
It returns INSTRUCTIONS that AI agents execute - it does NOT auto-install packages.
|
|
5013
4754
|
`);
|
|
5014
|
-
integrate.argument("[framework]", "Framework name (
|
|
4755
|
+
integrate.argument("[framework]", "Framework name (langchain, langgraph, vercel-ai, openai)").option("-o, --output <path>", "Save instructions to file").option("--raw", "Output raw markdown (no formatting)").option("--verify", "Verify integration after setup").action(async (frameworkArg, options) => {
|
|
5015
4756
|
const isJson = getJsonFlag(integrate);
|
|
5016
4757
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
5017
4758
|
try {
|
|
@@ -5109,7 +4850,7 @@ AI AGENT: Execute these steps using Bash for install, Write/Edit for code change
|
|
|
5109
4850
|
init_sdk_client();
|
|
5110
4851
|
import { Command as Command6 } from "commander";
|
|
5111
4852
|
import chalk10 from "chalk";
|
|
5112
|
-
import { readFileSync as
|
|
4853
|
+
import { readFileSync as readFileSync9 } from "fs";
|
|
5113
4854
|
init_errors();
|
|
5114
4855
|
function createAgentsCommand() {
|
|
5115
4856
|
const agents = new Command6("agents").description("Manage AI agents").addHelpText("after", `
|
|
@@ -5233,7 +4974,7 @@ ${chalk10.dim("Required: --name, --slug, and --system-prompt (or --file).")}
|
|
|
5233
4974
|
try {
|
|
5234
4975
|
let data;
|
|
5235
4976
|
if (options.file) {
|
|
5236
|
-
const content =
|
|
4977
|
+
const content = readFileSync9(options.file, "utf-8");
|
|
5237
4978
|
data = JSON.parse(content);
|
|
5238
4979
|
} else if (options.name && options.slug && options.systemPrompt) {
|
|
5239
4980
|
data = {
|
|
@@ -5267,7 +5008,7 @@ Examples:
|
|
|
5267
5008
|
try {
|
|
5268
5009
|
let data = {};
|
|
5269
5010
|
if (options.file) {
|
|
5270
|
-
const content =
|
|
5011
|
+
const content = readFileSync9(options.file, "utf-8");
|
|
5271
5012
|
data = JSON.parse(content);
|
|
5272
5013
|
} else {
|
|
5273
5014
|
if (options.name)
|
|
@@ -5562,7 +5303,7 @@ ${chalk11.dim("Persists organization ID for org-scoped API keys.")}
|
|
|
5562
5303
|
init_sdk_client();
|
|
5563
5304
|
import { Command as Command8 } from "commander";
|
|
5564
5305
|
import chalk12 from "chalk";
|
|
5565
|
-
import { readFileSync as
|
|
5306
|
+
import { readFileSync as readFileSync10 } from "fs";
|
|
5566
5307
|
init_errors();
|
|
5567
5308
|
function parseSSELine(line) {
|
|
5568
5309
|
if (!line || line.startsWith(":")) {
|
|
@@ -5724,7 +5465,7 @@ function parsePromptStyleInput(options) {
|
|
|
5724
5465
|
function getInputJson(options) {
|
|
5725
5466
|
if (options.file) {
|
|
5726
5467
|
try {
|
|
5727
|
-
return
|
|
5468
|
+
return readFileSync10(options.file, "utf-8");
|
|
5728
5469
|
} catch (err) {
|
|
5729
5470
|
throw new MutagentError("FILE_READ_ERROR", `Failed to read input file: ${options.file}`, err instanceof Error ? err.message : "Check the file path and permissions");
|
|
5730
5471
|
}
|
|
@@ -6077,7 +5818,7 @@ init_config();
|
|
|
6077
5818
|
import { Command as Command11 } from "commander";
|
|
6078
5819
|
import inquirer3 from "inquirer";
|
|
6079
5820
|
import chalk15 from "chalk";
|
|
6080
|
-
import { existsSync as
|
|
5821
|
+
import { existsSync as existsSync10, readFileSync as readFileSync11, writeFileSync as writeFileSync4 } from "fs";
|
|
6081
5822
|
import { execSync as execSync2 } from "child_process";
|
|
6082
5823
|
import { join as join5 } from "path";
|
|
6083
5824
|
init_errors();
|
|
@@ -6130,16 +5871,16 @@ var FRAMEWORK_DETECTION_MAP = {
|
|
|
6130
5871
|
}
|
|
6131
5872
|
};
|
|
6132
5873
|
function detectPackageManager2(cwd = process.cwd()) {
|
|
6133
|
-
if (
|
|
5874
|
+
if (existsSync10(join5(cwd, "bun.lockb")) || existsSync10(join5(cwd, "bun.lock"))) {
|
|
6134
5875
|
return "bun";
|
|
6135
5876
|
}
|
|
6136
|
-
if (
|
|
5877
|
+
if (existsSync10(join5(cwd, "pnpm-lock.yaml"))) {
|
|
6137
5878
|
return "pnpm";
|
|
6138
5879
|
}
|
|
6139
|
-
if (
|
|
5880
|
+
if (existsSync10(join5(cwd, "yarn.lock"))) {
|
|
6140
5881
|
return "yarn";
|
|
6141
5882
|
}
|
|
6142
|
-
if (
|
|
5883
|
+
if (existsSync10(join5(cwd, "package-lock.json"))) {
|
|
6143
5884
|
return "npm";
|
|
6144
5885
|
}
|
|
6145
5886
|
try {
|
|
@@ -6161,12 +5902,12 @@ function getInstallCommand2(pm, packages) {
|
|
|
6161
5902
|
}
|
|
6162
5903
|
function detectFrameworkFromPackageJson(cwd = process.cwd()) {
|
|
6163
5904
|
const pkgPath = join5(cwd, "package.json");
|
|
6164
|
-
if (!
|
|
5905
|
+
if (!existsSync10(pkgPath)) {
|
|
6165
5906
|
return null;
|
|
6166
5907
|
}
|
|
6167
5908
|
let pkg;
|
|
6168
5909
|
try {
|
|
6169
|
-
pkg = JSON.parse(
|
|
5910
|
+
pkg = JSON.parse(readFileSync11(pkgPath, "utf-8"));
|
|
6170
5911
|
} catch {
|
|
6171
5912
|
return null;
|
|
6172
5913
|
}
|
|
@@ -6182,7 +5923,7 @@ function detectFrameworkFromPackageJson(cwd = process.cwd()) {
|
|
|
6182
5923
|
return null;
|
|
6183
5924
|
}
|
|
6184
5925
|
function hasRcConfig(cwd = process.cwd()) {
|
|
6185
|
-
return
|
|
5926
|
+
return existsSync10(join5(cwd, ".mutagentrc.json"));
|
|
6186
5927
|
}
|
|
6187
5928
|
function writeRcConfig(config, cwd = process.cwd()) {
|
|
6188
5929
|
const rcPath = join5(cwd, ".mutagentrc.json");
|
|
@@ -6478,7 +6219,7 @@ Scanning ${scanPath}...
|
|
|
6478
6219
|
// src/commands/skills.ts
|
|
6479
6220
|
import { Command as Command13 } from "commander";
|
|
6480
6221
|
import chalk17 from "chalk";
|
|
6481
|
-
import { existsSync as
|
|
6222
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync3, writeFileSync as writeFileSync5 } from "fs";
|
|
6482
6223
|
import { join as join6 } from "path";
|
|
6483
6224
|
var SKILL_FRONTMATTER = `---
|
|
6484
6225
|
name: mutagent-cli
|
|
@@ -6585,7 +6326,7 @@ that teaches coding agents how to use the MutagenT CLI effectively.
|
|
|
6585
6326
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
6586
6327
|
const skillDir = join6(process.cwd(), SKILL_DIR);
|
|
6587
6328
|
const skillPath = join6(skillDir, SKILL_FILE);
|
|
6588
|
-
if (!
|
|
6329
|
+
if (!existsSync11(skillDir)) {
|
|
6589
6330
|
mkdirSync3(skillDir, { recursive: true });
|
|
6590
6331
|
}
|
|
6591
6332
|
const content = `${SKILL_FRONTMATTER}
|
|
@@ -6613,12 +6354,16 @@ ${SKILL_BODY}
|
|
|
6613
6354
|
// src/bin/cli.ts
|
|
6614
6355
|
init_config();
|
|
6615
6356
|
var cliVersion = "0.1.1";
|
|
6616
|
-
|
|
6617
|
-
|
|
6618
|
-
|
|
6619
|
-
|
|
6620
|
-
|
|
6621
|
-
|
|
6357
|
+
if (process.env.CLI_VERSION) {
|
|
6358
|
+
cliVersion = process.env.CLI_VERSION;
|
|
6359
|
+
} else {
|
|
6360
|
+
try {
|
|
6361
|
+
const __dirname2 = dirname(fileURLToPath(import.meta.url));
|
|
6362
|
+
const pkgPath = join7(__dirname2, "..", "..", "package.json");
|
|
6363
|
+
const pkg = JSON.parse(readFileSync12(pkgPath, "utf-8"));
|
|
6364
|
+
cliVersion = pkg.version ?? cliVersion;
|
|
6365
|
+
} catch {}
|
|
6366
|
+
}
|
|
6622
6367
|
var program = new Command14;
|
|
6623
6368
|
program.name("mutagent").description(`MutagenT CLI - AI-native prompt optimization platform
|
|
6624
6369
|
|
|
@@ -6656,7 +6401,7 @@ ${chalk18.yellow("Workflows:")}
|
|
|
6656
6401
|
program.addHelpText("after", `
|
|
6657
6402
|
${chalk18.cyan("┌─ AI AGENT INTEGRATION HINT ────────────────────────────────────────────────┐")}
|
|
6658
6403
|
${chalk18.cyan("│")} ${chalk18.cyan("│")}
|
|
6659
|
-
${chalk18.cyan("│")} Frameworks:
|
|
6404
|
+
${chalk18.cyan("│")} Frameworks: langchain, langgraph, vercel-ai, openai ${chalk18.cyan("│")}
|
|
6660
6405
|
${chalk18.cyan("│")} ${chalk18.cyan("│")}
|
|
6661
6406
|
${chalk18.cyan("│")} Get integration guide: mutagent integrate <framework> ${chalk18.cyan("│")}
|
|
6662
6407
|
${chalk18.cyan("│")} Verify setup: mutagent integrate <framework> --verify ${chalk18.cyan("│")}
|
|
@@ -6695,5 +6440,5 @@ program.addCommand(createExploreCommand());
|
|
|
6695
6440
|
program.addCommand(createSkillsCommand());
|
|
6696
6441
|
program.parse();
|
|
6697
6442
|
|
|
6698
|
-
//# debugId=
|
|
6443
|
+
//# debugId=8F5D422F7273E03E64756E2164756E21
|
|
6699
6444
|
//# sourceMappingURL=cli.js.map
|