@mutagent/cli 0.1.37 → 0.1.38
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 +270 -10
- package/dist/bin/cli.js.map +8 -7
- package/dist/index.js +7 -2
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
package/dist/bin/cli.js
CHANGED
|
@@ -797,7 +797,12 @@ class SDKClientWrapper {
|
|
|
797
797
|
}
|
|
798
798
|
}
|
|
799
799
|
async listTraces(filters) {
|
|
800
|
-
const
|
|
800
|
+
const filterRecord = {};
|
|
801
|
+
if (filters?.promptId)
|
|
802
|
+
filterRecord.promptId = filters.promptId;
|
|
803
|
+
if (filters?.source)
|
|
804
|
+
filterRecord.source = filters.source;
|
|
805
|
+
const params = Object.keys(filterRecord).length > 0 ? new URLSearchParams(filterRecord).toString() : "";
|
|
801
806
|
const response = await this.request(`/api/traces${params ? `?${params}` : ""}`);
|
|
802
807
|
return response.data ?? [];
|
|
803
808
|
}
|
|
@@ -1056,10 +1061,10 @@ var init_sdk_client = __esm(() => {
|
|
|
1056
1061
|
});
|
|
1057
1062
|
|
|
1058
1063
|
// src/bin/cli.ts
|
|
1059
|
-
import { Command as
|
|
1064
|
+
import { Command as Command19 } from "commander";
|
|
1060
1065
|
import chalk24 from "chalk";
|
|
1061
|
-
import { readFileSync as
|
|
1062
|
-
import { join as
|
|
1066
|
+
import { readFileSync as readFileSync12 } from "fs";
|
|
1067
|
+
import { join as join9, dirname } from "path";
|
|
1063
1068
|
import { fileURLToPath } from "url";
|
|
1064
1069
|
|
|
1065
1070
|
// src/commands/auth.ts
|
|
@@ -4959,10 +4964,11 @@ Examples:
|
|
|
4959
4964
|
|
|
4960
4965
|
Note: MutagenT traces replace Langfuse for observability.
|
|
4961
4966
|
`);
|
|
4962
|
-
traces.command("list").description("List traces").option("-p, --prompt <id>", "Filter by prompt ID").option("-l, --limit <n>", "Limit results", "50").addHelpText("after", `
|
|
4967
|
+
traces.command("list").description("List traces").option("-p, --prompt <id>", "Filter by prompt ID").option("-s, --source <source>", "Filter by trace source (e.g., claude-code, sdk, langchain)").option("-l, --limit <n>", "Limit results", "50").addHelpText("after", `
|
|
4963
4968
|
Examples:
|
|
4964
4969
|
${chalk12.dim("$")} mutagent traces list
|
|
4965
4970
|
${chalk12.dim("$")} mutagent traces list --prompt <prompt-id>
|
|
4971
|
+
${chalk12.dim("$")} mutagent traces list --source claude-code --json
|
|
4966
4972
|
${chalk12.dim("$")} mutagent traces list --limit 10 --json
|
|
4967
4973
|
|
|
4968
4974
|
${chalk12.dim("Tip: Filter by prompt to see traces for a specific prompt version.")}
|
|
@@ -4972,7 +4978,8 @@ ${chalk12.dim("Tip: Filter by prompt to see traces for a specific prompt version
|
|
|
4972
4978
|
try {
|
|
4973
4979
|
const client = getSDKClient();
|
|
4974
4980
|
const tracesList = await client.listTraces({
|
|
4975
|
-
promptId: options.prompt
|
|
4981
|
+
promptId: options.prompt,
|
|
4982
|
+
source: options.source
|
|
4976
4983
|
});
|
|
4977
4984
|
const limit = parseInt(options.limit, 10) || 50;
|
|
4978
4985
|
const limited = tracesList.slice(0, limit);
|
|
@@ -7478,6 +7485,257 @@ Examples:
|
|
|
7478
7485
|
return usage;
|
|
7479
7486
|
}
|
|
7480
7487
|
|
|
7488
|
+
// src/commands/hooks.ts
|
|
7489
|
+
init_config();
|
|
7490
|
+
import { Command as Command18 } from "commander";
|
|
7491
|
+
import { randomUUID } from "crypto";
|
|
7492
|
+
import { join as join8 } from "path";
|
|
7493
|
+
import { tmpdir } from "os";
|
|
7494
|
+
import { readFileSync as readFileSync11, writeFileSync as writeFileSync6, unlinkSync, existsSync as existsSync14 } from "fs";
|
|
7495
|
+
async function safeExecute(fn) {
|
|
7496
|
+
try {
|
|
7497
|
+
await fn();
|
|
7498
|
+
} catch (err) {
|
|
7499
|
+
process.stderr.write(`[mutagent hooks] Warning: ${err instanceof Error ? err.message : String(err)}
|
|
7500
|
+
`);
|
|
7501
|
+
}
|
|
7502
|
+
}
|
|
7503
|
+
async function readStdin() {
|
|
7504
|
+
const chunks = [];
|
|
7505
|
+
for await (const chunk of process.stdin) {
|
|
7506
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
7507
|
+
}
|
|
7508
|
+
return JSON.parse(Buffer.concat(chunks).toString("utf-8"));
|
|
7509
|
+
}
|
|
7510
|
+
function stateFilePath(sessionId) {
|
|
7511
|
+
return join8(tmpdir(), `mutagent-hook-${sessionId}.json`);
|
|
7512
|
+
}
|
|
7513
|
+
function readState(sessionId) {
|
|
7514
|
+
const path = stateFilePath(sessionId);
|
|
7515
|
+
if (!existsSync14(path))
|
|
7516
|
+
return null;
|
|
7517
|
+
try {
|
|
7518
|
+
return JSON.parse(readFileSync11(path, "utf-8"));
|
|
7519
|
+
} catch {
|
|
7520
|
+
return null;
|
|
7521
|
+
}
|
|
7522
|
+
}
|
|
7523
|
+
function writeState(sessionId, state) {
|
|
7524
|
+
writeFileSync6(stateFilePath(sessionId), JSON.stringify(state), "utf-8");
|
|
7525
|
+
}
|
|
7526
|
+
function deleteState(sessionId) {
|
|
7527
|
+
const path = stateFilePath(sessionId);
|
|
7528
|
+
if (existsSync14(path)) {
|
|
7529
|
+
try {
|
|
7530
|
+
unlinkSync(path);
|
|
7531
|
+
} catch {}
|
|
7532
|
+
}
|
|
7533
|
+
}
|
|
7534
|
+
var API_TIMEOUT_MS = 5000;
|
|
7535
|
+
async function sendBatchTrace(traces) {
|
|
7536
|
+
const apiKey = getApiKey();
|
|
7537
|
+
if (!apiKey) {
|
|
7538
|
+
process.stderr.write(`[mutagent hooks] Warning: Not authenticated. Run: mutagent auth login
|
|
7539
|
+
`);
|
|
7540
|
+
return;
|
|
7541
|
+
}
|
|
7542
|
+
const config = loadConfig();
|
|
7543
|
+
const endpoint = config.endpoint ?? "http://localhost:3003";
|
|
7544
|
+
const headers = {
|
|
7545
|
+
"x-api-key": apiKey,
|
|
7546
|
+
"Content-Type": "application/json"
|
|
7547
|
+
};
|
|
7548
|
+
if (config.defaultWorkspace) {
|
|
7549
|
+
headers["x-workspace-id"] = config.defaultWorkspace;
|
|
7550
|
+
}
|
|
7551
|
+
if (config.defaultOrganization) {
|
|
7552
|
+
headers["x-organization-id"] = config.defaultOrganization;
|
|
7553
|
+
}
|
|
7554
|
+
const controller = new AbortController;
|
|
7555
|
+
const timeout = setTimeout(() => {
|
|
7556
|
+
controller.abort();
|
|
7557
|
+
}, API_TIMEOUT_MS);
|
|
7558
|
+
try {
|
|
7559
|
+
const response = await fetch(`${endpoint}/api/traces/batch`, {
|
|
7560
|
+
method: "POST",
|
|
7561
|
+
headers,
|
|
7562
|
+
body: JSON.stringify({ traces }),
|
|
7563
|
+
signal: controller.signal
|
|
7564
|
+
});
|
|
7565
|
+
if (!response.ok) {
|
|
7566
|
+
const body = await response.text().catch(() => "");
|
|
7567
|
+
process.stderr.write(`[mutagent hooks] Warning: API returned ${String(response.status)}: ${body.slice(0, 200)}
|
|
7568
|
+
`);
|
|
7569
|
+
}
|
|
7570
|
+
} finally {
|
|
7571
|
+
clearTimeout(timeout);
|
|
7572
|
+
}
|
|
7573
|
+
}
|
|
7574
|
+
function getString(input, ...keys) {
|
|
7575
|
+
for (const key of keys) {
|
|
7576
|
+
const val = input[key];
|
|
7577
|
+
if (typeof val === "string" && val.length > 0)
|
|
7578
|
+
return val;
|
|
7579
|
+
}
|
|
7580
|
+
return "";
|
|
7581
|
+
}
|
|
7582
|
+
async function handleSessionStart() {
|
|
7583
|
+
const input = await readStdin();
|
|
7584
|
+
const sessionId = getString(input, "session_id", "sessionId");
|
|
7585
|
+
if (!sessionId)
|
|
7586
|
+
throw new Error("Missing session_id in stdin");
|
|
7587
|
+
const now = new Date().toISOString();
|
|
7588
|
+
const traceId = `cc-${sessionId}`;
|
|
7589
|
+
const state = {
|
|
7590
|
+
traceId,
|
|
7591
|
+
sessionId,
|
|
7592
|
+
startTime: now,
|
|
7593
|
+
openSpans: {}
|
|
7594
|
+
};
|
|
7595
|
+
writeState(sessionId, state);
|
|
7596
|
+
await sendBatchTrace([
|
|
7597
|
+
{
|
|
7598
|
+
traceId,
|
|
7599
|
+
sessionId,
|
|
7600
|
+
name: "Claude Code Session",
|
|
7601
|
+
source: "claude-code",
|
|
7602
|
+
startTime: now,
|
|
7603
|
+
status: "running",
|
|
7604
|
+
spans: []
|
|
7605
|
+
}
|
|
7606
|
+
]);
|
|
7607
|
+
}
|
|
7608
|
+
async function handleSessionEnd() {
|
|
7609
|
+
const input = await readStdin();
|
|
7610
|
+
const sessionId = getString(input, "session_id", "sessionId");
|
|
7611
|
+
if (!sessionId)
|
|
7612
|
+
throw new Error("Missing session_id in stdin");
|
|
7613
|
+
const now = new Date().toISOString();
|
|
7614
|
+
const state = readState(sessionId);
|
|
7615
|
+
const traceId = state?.traceId ?? `cc-${sessionId}`;
|
|
7616
|
+
const startTime = state?.startTime ?? now;
|
|
7617
|
+
await sendBatchTrace([
|
|
7618
|
+
{
|
|
7619
|
+
traceId,
|
|
7620
|
+
sessionId,
|
|
7621
|
+
name: "Claude Code Session",
|
|
7622
|
+
source: "claude-code",
|
|
7623
|
+
startTime,
|
|
7624
|
+
endTime: now,
|
|
7625
|
+
status: "completed",
|
|
7626
|
+
spans: []
|
|
7627
|
+
}
|
|
7628
|
+
]);
|
|
7629
|
+
deleteState(sessionId);
|
|
7630
|
+
}
|
|
7631
|
+
async function handlePreToolUse() {
|
|
7632
|
+
const input = await readStdin();
|
|
7633
|
+
const sessionId = getString(input, "session_id", "sessionId");
|
|
7634
|
+
const toolName = getString(input, "tool_name", "toolName") || "unknown";
|
|
7635
|
+
if (!sessionId)
|
|
7636
|
+
throw new Error("Missing session_id in stdin");
|
|
7637
|
+
const now = new Date().toISOString();
|
|
7638
|
+
const state = readState(sessionId) ?? {
|
|
7639
|
+
traceId: `cc-${sessionId}`,
|
|
7640
|
+
sessionId,
|
|
7641
|
+
startTime: now,
|
|
7642
|
+
openSpans: {}
|
|
7643
|
+
};
|
|
7644
|
+
const spanId = randomUUID();
|
|
7645
|
+
state.openSpans[spanId] = {
|
|
7646
|
+
spanId,
|
|
7647
|
+
startTime: now,
|
|
7648
|
+
toolName
|
|
7649
|
+
};
|
|
7650
|
+
writeState(sessionId, state);
|
|
7651
|
+
await sendBatchTrace([
|
|
7652
|
+
{
|
|
7653
|
+
traceId: state.traceId,
|
|
7654
|
+
sessionId,
|
|
7655
|
+
name: "Claude Code Session",
|
|
7656
|
+
source: "claude-code",
|
|
7657
|
+
startTime: state.startTime,
|
|
7658
|
+
status: "running",
|
|
7659
|
+
spans: [
|
|
7660
|
+
{
|
|
7661
|
+
spanId,
|
|
7662
|
+
name: toolName,
|
|
7663
|
+
kind: "tool",
|
|
7664
|
+
startTime: now,
|
|
7665
|
+
status: "running"
|
|
7666
|
+
}
|
|
7667
|
+
]
|
|
7668
|
+
}
|
|
7669
|
+
]);
|
|
7670
|
+
}
|
|
7671
|
+
async function handlePostToolUse() {
|
|
7672
|
+
const input = await readStdin();
|
|
7673
|
+
const sessionId = getString(input, "session_id", "sessionId");
|
|
7674
|
+
const toolName = getString(input, "tool_name", "toolName") || "unknown";
|
|
7675
|
+
if (!sessionId)
|
|
7676
|
+
throw new Error("Missing session_id in stdin");
|
|
7677
|
+
const now = new Date().toISOString();
|
|
7678
|
+
const state = readState(sessionId);
|
|
7679
|
+
const traceId = state?.traceId ?? `cc-${sessionId}`;
|
|
7680
|
+
const startTime = state?.startTime ?? now;
|
|
7681
|
+
let matchedSpan = null;
|
|
7682
|
+
let matchedKey = null;
|
|
7683
|
+
if (state?.openSpans) {
|
|
7684
|
+
const entries = Object.entries(state.openSpans);
|
|
7685
|
+
for (let i = entries.length - 1;i >= 0; i--) {
|
|
7686
|
+
const entry = entries[i];
|
|
7687
|
+
if (entry && entry[1].toolName === toolName) {
|
|
7688
|
+
matchedSpan = entry[1];
|
|
7689
|
+
matchedKey = entry[0];
|
|
7690
|
+
break;
|
|
7691
|
+
}
|
|
7692
|
+
}
|
|
7693
|
+
}
|
|
7694
|
+
const spanId = matchedSpan?.spanId ?? randomUUID();
|
|
7695
|
+
const spanStartTime = matchedSpan?.startTime ?? now;
|
|
7696
|
+
if (state && matchedKey) {
|
|
7697
|
+
state.openSpans = Object.fromEntries(Object.entries(state.openSpans).filter(([k]) => k !== matchedKey));
|
|
7698
|
+
writeState(sessionId, state);
|
|
7699
|
+
}
|
|
7700
|
+
await sendBatchTrace([
|
|
7701
|
+
{
|
|
7702
|
+
traceId,
|
|
7703
|
+
sessionId,
|
|
7704
|
+
name: "Claude Code Session",
|
|
7705
|
+
source: "claude-code",
|
|
7706
|
+
startTime,
|
|
7707
|
+
status: "running",
|
|
7708
|
+
spans: [
|
|
7709
|
+
{
|
|
7710
|
+
spanId,
|
|
7711
|
+
name: toolName,
|
|
7712
|
+
kind: "tool",
|
|
7713
|
+
startTime: spanStartTime,
|
|
7714
|
+
endTime: now,
|
|
7715
|
+
status: "completed"
|
|
7716
|
+
}
|
|
7717
|
+
]
|
|
7718
|
+
}
|
|
7719
|
+
]);
|
|
7720
|
+
}
|
|
7721
|
+
function createHooksCommand() {
|
|
7722
|
+
const hooks = new Command18("hooks").description("Hook handlers for AI coding assistants");
|
|
7723
|
+
const claudeCode = hooks.command("claude-code").description("Claude Code session telemetry");
|
|
7724
|
+
claudeCode.command("session-start").description("Handle session start event").action(async () => {
|
|
7725
|
+
await safeExecute(handleSessionStart);
|
|
7726
|
+
});
|
|
7727
|
+
claudeCode.command("session-end").description("Handle session end event").action(async () => {
|
|
7728
|
+
await safeExecute(handleSessionEnd);
|
|
7729
|
+
});
|
|
7730
|
+
claudeCode.command("pre-tool-use").description("Handle pre-tool-use event").action(async () => {
|
|
7731
|
+
await safeExecute(handlePreToolUse);
|
|
7732
|
+
});
|
|
7733
|
+
claudeCode.command("post-tool-use").description("Handle post-tool-use event").action(async () => {
|
|
7734
|
+
await safeExecute(handlePostToolUse);
|
|
7735
|
+
});
|
|
7736
|
+
return hooks;
|
|
7737
|
+
}
|
|
7738
|
+
|
|
7481
7739
|
// src/bin/cli.ts
|
|
7482
7740
|
init_config();
|
|
7483
7741
|
var cliVersion = "0.1.1";
|
|
@@ -7486,12 +7744,12 @@ if (process.env.CLI_VERSION) {
|
|
|
7486
7744
|
} else {
|
|
7487
7745
|
try {
|
|
7488
7746
|
const __dirname2 = dirname(fileURLToPath(import.meta.url));
|
|
7489
|
-
const pkgPath =
|
|
7490
|
-
const pkg = JSON.parse(
|
|
7747
|
+
const pkgPath = join9(__dirname2, "..", "..", "package.json");
|
|
7748
|
+
const pkg = JSON.parse(readFileSync12(pkgPath, "utf-8"));
|
|
7491
7749
|
cliVersion = pkg.version ?? cliVersion;
|
|
7492
7750
|
} catch {}
|
|
7493
7751
|
}
|
|
7494
|
-
var program = new
|
|
7752
|
+
var program = new Command19;
|
|
7495
7753
|
program.name("mutagent").description(`MutagenT CLI - AI-native prompt optimization platform
|
|
7496
7754
|
|
|
7497
7755
|
Documentation: https://docs.mutagent.io/cli
|
|
@@ -7529,6 +7787,7 @@ ${chalk24.yellow("Command Navigation:")}
|
|
|
7529
7787
|
mutagent prompts optimize results <job-id> ${chalk24.dim("View scorecard")}
|
|
7530
7788
|
|
|
7531
7789
|
mutagent integrate <framework> ${chalk24.dim("Framework integration guide")}
|
|
7790
|
+
mutagent hooks claude-code <event> ${chalk24.dim("Hook handler for Claude Code telemetry")}
|
|
7532
7791
|
mutagent playground run <id> --input '{...}' ${chalk24.dim("Quick test")}
|
|
7533
7792
|
|
|
7534
7793
|
${chalk24.yellow("Workflow: Evaluate → Optimize:")}
|
|
@@ -7578,7 +7837,8 @@ program.addCommand(createProvidersCommand());
|
|
|
7578
7837
|
program.addCommand(createExploreCommand());
|
|
7579
7838
|
program.addCommand(createSkillsCommand());
|
|
7580
7839
|
program.addCommand(createUsageCommand());
|
|
7840
|
+
program.addCommand(createHooksCommand());
|
|
7581
7841
|
program.parse();
|
|
7582
7842
|
|
|
7583
|
-
//# debugId=
|
|
7843
|
+
//# debugId=CF947D7B55AD31C164756E2164756E21
|
|
7584
7844
|
//# sourceMappingURL=cli.js.map
|