@mutagent/cli 0.1.397 → 0.1.398
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 +832 -738
- package/dist/index.js +16 -13
- package/package.json +1 -1
package/dist/bin/cli.js
CHANGED
|
@@ -454,7 +454,7 @@ ${String(data.length)} result(s)`));
|
|
|
454
454
|
}
|
|
455
455
|
}
|
|
456
456
|
function createSpinner(text, isJson) {
|
|
457
|
-
if (isJson) {
|
|
457
|
+
if (isJson || !process.stderr.isTTY || process.env.CI === "true") {
|
|
458
458
|
const noop = () => {
|
|
459
459
|
return;
|
|
460
460
|
};
|
|
@@ -583,7 +583,7 @@ var init_errors = __esm(() => {
|
|
|
583
583
|
notSignedInOrNoWorkspace: 3
|
|
584
584
|
};
|
|
585
585
|
KEY_REJECTED_CODES = new Set(["AUTH_EXPIRED", "INVALID_API_KEY", "FOREIGN_API_KEY", "API_401", "SANDBOX_TOKEN_REFUSED"]);
|
|
586
|
-
NOT_SIGNED_IN_CODES = new Set(["AUTH_REQUIRED", "WORKSPACE_REQUIRED"
|
|
586
|
+
NOT_SIGNED_IN_CODES = new Set(["AUTH_REQUIRED", "WORKSPACE_REQUIRED"]);
|
|
587
587
|
MutagentError = class MutagentError extends Error {
|
|
588
588
|
code;
|
|
589
589
|
suggestion;
|
|
@@ -673,8 +673,8 @@ var init_errors = __esm(() => {
|
|
|
673
673
|
}
|
|
674
674
|
};
|
|
675
675
|
NotFoundError = class NotFoundError extends MutagentError {
|
|
676
|
-
constructor(resource, id) {
|
|
677
|
-
super("NOT_FOUND", `${resource} not found: ${id}`, `Check the ID and try again. List available ${resource.toLowerCase()}s with the appropriate list command.`);
|
|
676
|
+
constructor(resource, id, listCommand) {
|
|
677
|
+
super("NOT_FOUND", `${resource} not found: ${id}`, listCommand === undefined ? `Check the ID and try again. List available ${resource.toLowerCase()}s with the appropriate list command.` : `Run: ${listCommand}`);
|
|
678
678
|
}
|
|
679
679
|
};
|
|
680
680
|
});
|
|
@@ -909,6 +909,7 @@ var init_config = __esm(() => {
|
|
|
909
909
|
// src/lib/organization-scope.ts
|
|
910
910
|
var exports_organization_scope = {};
|
|
911
911
|
__export(exports_organization_scope, {
|
|
912
|
+
workspaceDenied: () => workspaceDenied,
|
|
912
913
|
unreachableServerError: () => unreachableServerError,
|
|
913
914
|
tenancyHeaders: () => tenancyHeaders,
|
|
914
915
|
tenancyFailure: () => tenancyFailure,
|
|
@@ -968,18 +969,20 @@ function parseBody(body) {
|
|
|
968
969
|
function deadKeyError() {
|
|
969
970
|
return new TenancyError("AUTH_EXPIRED", "Your CLI key expired or was revoked.", "Run: mutagent login");
|
|
970
971
|
}
|
|
972
|
+
function workspaceDenied(ctx) {
|
|
973
|
+
const shown = ctx.workspaceName ?? ctx.workspaceId ?? "workspace";
|
|
974
|
+
if (ctx.workspaceOrigin === "selection") {
|
|
975
|
+
return new TenancyError(TENANCY_DENIED, `Your saved workspace ${shown} is no longer available to you.`, "Run: mutagent workspaces use <name>");
|
|
976
|
+
}
|
|
977
|
+
const where = ctx.organizationName ? ` in ${ctx.organizationName}` : "";
|
|
978
|
+
return new TenancyError(TENANCY_DENIED, `No workspace "${shown}" among your workspaces${where}.`, "See: mutagent workspaces list");
|
|
979
|
+
}
|
|
971
980
|
function tenancyFailure(status, body, ctx) {
|
|
972
981
|
const parsed = parseBody(body);
|
|
973
982
|
if (status === 401)
|
|
974
983
|
return deadKeyError();
|
|
975
|
-
if (status === 403 && parsed.code === TENANCY_DENIED)
|
|
976
|
-
|
|
977
|
-
if (ctx.workspaceOrigin === "selection") {
|
|
978
|
-
return new TenancyError(TENANCY_DENIED, `Your saved workspace ${shown} is no longer available to you.`, "Run: mutagent workspaces use <name>");
|
|
979
|
-
}
|
|
980
|
-
const where = ctx.organizationName ? ` in ${ctx.organizationName}` : "";
|
|
981
|
-
return new TenancyError(TENANCY_DENIED, `No workspace "${shown}" among your workspaces${where}.`, "See: mutagent workspaces list");
|
|
982
|
-
}
|
|
984
|
+
if (status === 403 && parsed.code === TENANCY_DENIED)
|
|
985
|
+
return workspaceDenied(ctx);
|
|
983
986
|
if (status === 403 && ctx.keyScope === "workspace" && ctx.workspaceOrigin === "override") {
|
|
984
987
|
return new TenancyError("WORKSPACE_KEY_MISMATCH", "This API key only works in its own workspace.", "Run: mutagent login (for a key that can switch workspaces)");
|
|
985
988
|
}
|
|
@@ -18095,6 +18098,15 @@ async function deployFrozenAgent(api, source2, built, options) {
|
|
|
18095
18098
|
};
|
|
18096
18099
|
}, recovery);
|
|
18097
18100
|
}
|
|
18101
|
+
function listStatus(agent, slots) {
|
|
18102
|
+
if (agent.status === "archived" || agent.archivedAt !== null)
|
|
18103
|
+
return "archived";
|
|
18104
|
+
if (slots.some((slot) => slot.enabled && slot.activeRevision !== null))
|
|
18105
|
+
return "active";
|
|
18106
|
+
if (slots.length > 0 && slots.every((slot) => !slot.enabled))
|
|
18107
|
+
return "retired";
|
|
18108
|
+
return "stored";
|
|
18109
|
+
}
|
|
18098
18110
|
async function listRemoteAgents(api, options) {
|
|
18099
18111
|
const page = await api.listAgents({
|
|
18100
18112
|
limit: Number(options.limit ?? 20),
|
|
@@ -18105,7 +18117,7 @@ async function listRemoteAgents(api, options) {
|
|
|
18105
18117
|
agents: page.data.map((agent) => ({
|
|
18106
18118
|
slug: agent.slug,
|
|
18107
18119
|
model: agent.model,
|
|
18108
|
-
status: agent.
|
|
18120
|
+
status: listStatus(agent, agent.deployments),
|
|
18109
18121
|
slots: agent.deployments.map((slot) => `${slot.environment ?? "(default)"}=${slot.enabled ? slot.activeRevision === null ? "none" : `v${String(slot.activeRevision)}` : "retired"}`).join(", ")
|
|
18110
18122
|
})),
|
|
18111
18123
|
data: page.data,
|
|
@@ -18284,6 +18296,8 @@ this is the only way back from retire. An archived managed agent is refused
|
|
|
18284
18296
|
(409 MANAGED_AGENT_ARCHIVED): deploy its agent.md again to bring it back.
|
|
18285
18297
|
Example: mutagent agent activate invoice-pricing --revision v2 --env prod --json`,
|
|
18286
18298
|
list: `Lists the workspace's managed agents with each slot's active revision.
|
|
18299
|
+
STATUS is what the slots say: active (a slot runs a revision), retired (every
|
|
18300
|
+
slot retired), stored (nothing active yet) or archived.
|
|
18287
18301
|
Archived agents are left out unless --include-archived.
|
|
18288
18302
|
Example: mutagent agent list --json`,
|
|
18289
18303
|
inspect: `Shows a managed agent's revisions (newest first), its slots and the sessions
|
|
@@ -18316,7 +18330,9 @@ var DIRECTIVES = {
|
|
|
18316
18330
|
--idempotency-key; a new key is a new request. A 409 on generation means the slot
|
|
18317
18331
|
changed: inspect it before retrying.`,
|
|
18318
18332
|
list: ` Read-only. --json prints { agents, data, nextCursor }; pass nextCursor as --cursor for
|
|
18319
|
-
the next page.
|
|
18333
|
+
the next page. agents[].status is derived from the slots (active | retired | stored |
|
|
18334
|
+
archived); data[].status is the agent record's own lifecycle field. Archived agents
|
|
18335
|
+
appear only with --include-archived.`,
|
|
18320
18336
|
inspect: ` Read-only. --json prints the agent, its revisions (nextCursor for --cursor), its
|
|
18321
18337
|
slots and the sessions launched from it with their references. --operation <id>
|
|
18322
18338
|
prints the recorded outcome of one deploy or activate instead.`,
|
|
@@ -19255,6 +19271,32 @@ function registerAgentHistoryCommands(group) {
|
|
|
19255
19271
|
});
|
|
19256
19272
|
}
|
|
19257
19273
|
|
|
19274
|
+
// src/lib/agent/list-table.ts
|
|
19275
|
+
init_output();
|
|
19276
|
+
import chalk4 from "chalk";
|
|
19277
|
+
function activeRevision(slot) {
|
|
19278
|
+
if (!slot.enabled)
|
|
19279
|
+
return "retired";
|
|
19280
|
+
return slot.activeRevision === null ? "none" : `v${String(slot.activeRevision)}`;
|
|
19281
|
+
}
|
|
19282
|
+
function printAgentList(response) {
|
|
19283
|
+
const agents = Array.isArray(response.data) ? response.data : [];
|
|
19284
|
+
if (agents.length === 0) {
|
|
19285
|
+
console.log(chalk4.gray("No managed agents in this workspace. Deploy one: mutagent agent deploy <agent.md>"));
|
|
19286
|
+
return;
|
|
19287
|
+
}
|
|
19288
|
+
const rows = agents.flatMap((agent) => agent.deployments.length === 0 ? [{ slug: agent.slug, status: agent.status, slot: "-", "active revision": "-" }] : agent.deployments.map((slot) => ({
|
|
19289
|
+
slug: agent.slug,
|
|
19290
|
+
status: agent.status,
|
|
19291
|
+
slot: slot.environment ?? "default",
|
|
19292
|
+
"active revision": activeRevision(slot)
|
|
19293
|
+
})));
|
|
19294
|
+
new OutputFormatter("table").output(rows);
|
|
19295
|
+
if (typeof response.nextCursor === "string" && response.nextCursor !== "") {
|
|
19296
|
+
console.log(`More: mutagent agent list --cursor ${response.nextCursor}`);
|
|
19297
|
+
}
|
|
19298
|
+
}
|
|
19299
|
+
|
|
19258
19300
|
// src/commands/agent/index.ts
|
|
19259
19301
|
var RUN_TAKES_A_FILE_MESSAGE = "mutagent agent run takes a local agent.md; a managed agent runs with mutagent helix agent @slug";
|
|
19260
19302
|
function looksLikeSlug(source2) {
|
|
@@ -19302,7 +19344,7 @@ function createAgentCommand(injected) {
|
|
|
19302
19344
|
await performAgentAction("list", cmd, false, async () => {
|
|
19303
19345
|
validateLimit(opts.limit, "list");
|
|
19304
19346
|
return (await services()).list(opts);
|
|
19305
|
-
});
|
|
19347
|
+
}, printAgentList);
|
|
19306
19348
|
});
|
|
19307
19349
|
leaf("inspect", "Show a managed agent's revisions, slots and sessions, or one operation").argument("[slug]", "Managed agent slug").option("--env <name>", "Show only the deployment slot of this Environment").option("--operation <id>", "Show the recorded outcome of one deploy or activate instead").option("--limit <count>", "Revisions per page from 1 to 100", "20").option("--cursor <cursor>", "Revision nextCursor from the previous inspect").action(async (slug, opts, cmd) => {
|
|
19308
19350
|
await performAgentAction("inspect", cmd, false, async () => {
|
|
@@ -19335,12 +19377,12 @@ init_key_check();
|
|
|
19335
19377
|
init_output();
|
|
19336
19378
|
init_errors();
|
|
19337
19379
|
import { Command as Command2 } from "commander";
|
|
19338
|
-
import
|
|
19380
|
+
import chalk7 from "chalk";
|
|
19339
19381
|
import { existsSync as existsSync8 } from "fs";
|
|
19340
19382
|
import { join as join13 } from "path";
|
|
19341
19383
|
|
|
19342
19384
|
// src/commands/onboarding.ts
|
|
19343
|
-
import
|
|
19385
|
+
import chalk5 from "chalk";
|
|
19344
19386
|
|
|
19345
19387
|
// src/lib/rc-config.ts
|
|
19346
19388
|
init_config();
|
|
@@ -19686,46 +19728,46 @@ async function runPostOnboarding(deps = {}) {
|
|
|
19686
19728
|
const select = deps.selectAction ?? defaultSelectAction;
|
|
19687
19729
|
const install = deps.installPackage ?? installPackage;
|
|
19688
19730
|
console.log("");
|
|
19689
|
-
console.log(
|
|
19731
|
+
console.log(chalk5.bold.cyan(" You are authenticated."));
|
|
19690
19732
|
console.log("");
|
|
19691
19733
|
const rc = scaffold(cwd);
|
|
19692
19734
|
if (rc.alreadyPresent) {
|
|
19693
|
-
console.log(` ${
|
|
19735
|
+
console.log(` ${chalk5.green("✓")} .mutagentrc.json already present`);
|
|
19694
19736
|
} else {
|
|
19695
|
-
console.log(` ${
|
|
19737
|
+
console.log(` ${chalk5.green("✓")} Created .mutagentrc.json`);
|
|
19696
19738
|
}
|
|
19697
19739
|
console.log("");
|
|
19698
19740
|
const action = await select(ONBOARDING_CHOICES);
|
|
19699
19741
|
console.log("");
|
|
19700
19742
|
if (action === "helix") {
|
|
19701
|
-
console.log(
|
|
19702
|
-
console.log(
|
|
19743
|
+
console.log(chalk5.bold(" Installing Helix…"));
|
|
19744
|
+
console.log(chalk5.dim(" Downloading the helix binary and verifying its checksum"));
|
|
19703
19745
|
console.log("");
|
|
19704
19746
|
try {
|
|
19705
19747
|
const result = await install("helix", {});
|
|
19706
|
-
console.log(` ${
|
|
19748
|
+
console.log(` ${chalk5.green("✓")} Helix ${result.version} installed at ${result.binaryPath}`);
|
|
19707
19749
|
if (result.pathLine !== undefined) {
|
|
19708
|
-
console.log(` ${
|
|
19709
|
-
console.log(` ${
|
|
19750
|
+
console.log(` ${chalk5.yellow("⚠")} Not on your PATH yet. Add this line to your shell profile:`);
|
|
19751
|
+
console.log(` ${chalk5.cyan(result.pathLine)}`);
|
|
19710
19752
|
}
|
|
19711
|
-
console.log(` ${
|
|
19753
|
+
console.log(` ${chalk5.blue("→")} Next: ${result.nextStep}`);
|
|
19712
19754
|
console.log("");
|
|
19713
19755
|
} catch (error3) {
|
|
19714
19756
|
console.log("");
|
|
19715
19757
|
if (error3 instanceof MutagentError) {
|
|
19716
|
-
console.error(` ${
|
|
19758
|
+
console.error(` ${chalk5.red("✗")} Helix install failed: ${scrubKnown(error3.message)}`);
|
|
19717
19759
|
if (error3.suggestion)
|
|
19718
|
-
console.error(` ${
|
|
19760
|
+
console.error(` ${chalk5.yellow("→")} ${scrubKnown(error3.suggestion)}`);
|
|
19719
19761
|
} else {
|
|
19720
19762
|
const message = error3 instanceof Error ? error3.message : String(error3);
|
|
19721
|
-
console.error(` ${
|
|
19763
|
+
console.error(` ${chalk5.red("✗")} Helix install failed: ${scrubKnown(message)}`);
|
|
19722
19764
|
}
|
|
19723
19765
|
console.error("");
|
|
19724
19766
|
process.exitCode = 1;
|
|
19725
19767
|
}
|
|
19726
19768
|
} else {
|
|
19727
|
-
console.log(
|
|
19728
|
-
console.log(
|
|
19769
|
+
console.log(chalk5.dim(` Run ${chalk5.cyan("mutagent --help")} to explore the CLI.`));
|
|
19770
|
+
console.log(chalk5.dim(' Hit a snag? Send feedback: mutagent feedback send "what happened"'));
|
|
19729
19771
|
console.log("");
|
|
19730
19772
|
}
|
|
19731
19773
|
}
|
|
@@ -19737,7 +19779,7 @@ init_organization_scope();
|
|
|
19737
19779
|
init_output();
|
|
19738
19780
|
init_errors();
|
|
19739
19781
|
import { input, password, select } from "@inquirer/prompts";
|
|
19740
|
-
import
|
|
19782
|
+
import chalk6 from "chalk";
|
|
19741
19783
|
import ora2 from "ora";
|
|
19742
19784
|
|
|
19743
19785
|
// src/lib/browser-auth.ts
|
|
@@ -19910,7 +19952,7 @@ async function performLoginAction(opts) {
|
|
|
19910
19952
|
}
|
|
19911
19953
|
if (!isNonInteractive && wasFirstLogin) {
|
|
19912
19954
|
console.log(`
|
|
19913
|
-
` +
|
|
19955
|
+
` + chalk6.bold.cyan(" Welcome to Mutagent CLI!") + `
|
|
19914
19956
|
`);
|
|
19915
19957
|
console.log(` No credentials found. Please authenticate to continue.
|
|
19916
19958
|
`);
|
|
@@ -20085,18 +20127,18 @@ async function loginWithPastedKey(initialEndpoint, output, wasFirstLogin) {
|
|
|
20085
20127
|
function createAuthCommand() {
|
|
20086
20128
|
const auth = new Command2("auth").description("Sign in, show the sign-in state, or sign out on this machine").addHelpText("after", `
|
|
20087
20129
|
Examples:
|
|
20088
|
-
${
|
|
20089
|
-
${
|
|
20090
|
-
${
|
|
20091
|
-
${
|
|
20130
|
+
${chalk7.dim("$")} mutagent login
|
|
20131
|
+
${chalk7.dim("$")} mutagent login --browser
|
|
20132
|
+
${chalk7.dim("$")} mutagent auth status
|
|
20133
|
+
${chalk7.dim("$")} mutagent auth logout
|
|
20092
20134
|
|
|
20093
|
-
${
|
|
20135
|
+
${chalk7.dim("mutagent auth login is the same command as mutagent login.")}
|
|
20094
20136
|
`);
|
|
20095
20137
|
auth.command("login").description("Same as mutagent login: sign in and store the API key on this machine").option("--browser", "Sign in with the browser (skip the method prompt)").option("--non-interactive", "Skip the method prompt and use browser sign-in (with --json it also needs --browser)").option("--endpoint <url>", "API endpoint", "https://api.mutagent.io").addHelpText("after", `
|
|
20096
20138
|
Examples:
|
|
20097
|
-
${
|
|
20098
|
-
${
|
|
20099
|
-
${
|
|
20139
|
+
${chalk7.dim("$")} mutagent login ${chalk7.dim("# In a terminal, choose browser or API key")}
|
|
20140
|
+
${chalk7.dim("$")} mutagent login --browser ${chalk7.dim("# Sign in with the browser")}
|
|
20141
|
+
${chalk7.dim("$")} mutagent login --non-interactive ${chalk7.dim("# Browser sign-in without the method prompt (a person approves in the browser)")}
|
|
20100
20142
|
|
|
20101
20143
|
This runs the same sign-in as mutagent login, with the same options and --json output.
|
|
20102
20144
|
See mutagent login --help for the full description.
|
|
@@ -20132,8 +20174,8 @@ See mutagent login --help for the full description.
|
|
|
20132
20174
|
});
|
|
20133
20175
|
auth.command("status").description("Show the sign-in state, endpoint and active workspace").addHelpText("after", `
|
|
20134
20176
|
Examples:
|
|
20135
|
-
${
|
|
20136
|
-
${
|
|
20177
|
+
${chalk7.dim("$")} mutagent auth status
|
|
20178
|
+
${chalk7.dim("$")} mutagent auth status --json
|
|
20137
20179
|
|
|
20138
20180
|
${EXIT_CODES_LINE}
|
|
20139
20181
|
`).action(async () => {
|
|
@@ -20179,7 +20221,7 @@ ${EXIT_CODES_LINE}
|
|
|
20179
20221
|
});
|
|
20180
20222
|
auth.command("logout").description("Clear stored credentials").addHelpText("after", `
|
|
20181
20223
|
Examples:
|
|
20182
|
-
${
|
|
20224
|
+
${chalk7.dim("$")} mutagent auth logout
|
|
20183
20225
|
`).action(() => {
|
|
20184
20226
|
const isJson = getJsonFlag(auth);
|
|
20185
20227
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -20193,16 +20235,16 @@ Examples:
|
|
|
20193
20235
|
init_output();
|
|
20194
20236
|
init_errors();
|
|
20195
20237
|
import { Command as Command3 } from "commander";
|
|
20196
|
-
import
|
|
20238
|
+
import chalk8 from "chalk";
|
|
20197
20239
|
function createLoginCommand() {
|
|
20198
20240
|
const login = new Command3("login").description("Sign in to Mutagent and store the API key on this machine").option("--browser", "Sign in with the browser (skip the method prompt)").option("--non-interactive", "Skip the method prompt and use browser sign-in (with --json it also needs --browser)").option("--endpoint <url>", "API endpoint", "https://api.mutagent.io").addHelpText("after", `
|
|
20199
20241
|
Examples:
|
|
20200
|
-
${
|
|
20201
|
-
${
|
|
20202
|
-
${
|
|
20203
|
-
${
|
|
20204
|
-
${
|
|
20205
|
-
${
|
|
20242
|
+
${chalk8.dim("$")} mutagent login ${chalk8.dim("# In a terminal, choose browser or API key")}
|
|
20243
|
+
${chalk8.dim("$")} mutagent login --browser ${chalk8.dim("# Opens a real browser here; sign in or sign up")}
|
|
20244
|
+
${chalk8.dim("$")} mutagent login --non-interactive ${chalk8.dim("# Browser sign-in without the method prompt (a person approves in the browser)")}
|
|
20245
|
+
${chalk8.dim("$")} mutagent login --browser --non-interactive --json ${chalk8.dim("# Agent path: no browser opens here — see below")}
|
|
20246
|
+
${chalk8.dim("$")} mutagent login --org <slug> ${chalk8.dim("# Sign in for another organization (preselected on the approval page)")}
|
|
20247
|
+
${chalk8.dim("$")} MUTAGENT_API_KEY=mg_live_... mutagent login --json ${chalk8.dim("# Sign in with a key (CI)")}
|
|
20206
20248
|
|
|
20207
20249
|
Browser sign-in: app.mutagent.io is where you sign in or sign up, finish onboarding
|
|
20208
20250
|
and approve this CLI. The CLI waits up to 5 minutes and saves the credentials.
|
|
@@ -20225,8 +20267,8 @@ Environment:
|
|
|
20225
20267
|
CI=true Same as --non-interactive
|
|
20226
20268
|
|
|
20227
20269
|
Then:
|
|
20228
|
-
${
|
|
20229
|
-
${
|
|
20270
|
+
${chalk8.dim("$")} mutagent workspaces current
|
|
20271
|
+
${chalk8.dim("$")} mutagent workspaces use <name>
|
|
20230
20272
|
|
|
20231
20273
|
mutagent auth login runs the same sign-in.
|
|
20232
20274
|
`).action(async (options) => {
|
|
@@ -20268,7 +20310,7 @@ init_output();
|
|
|
20268
20310
|
init_errors();
|
|
20269
20311
|
init_organization_scope();
|
|
20270
20312
|
import { Command as Command5 } from "commander";
|
|
20271
|
-
import
|
|
20313
|
+
import chalk10 from "chalk";
|
|
20272
20314
|
|
|
20273
20315
|
// src/commands/workspaces.ts
|
|
20274
20316
|
init_sdk_client();
|
|
@@ -20277,7 +20319,7 @@ init_errors();
|
|
|
20277
20319
|
init_config();
|
|
20278
20320
|
init_organization_scope();
|
|
20279
20321
|
import { Command as Command4 } from "commander";
|
|
20280
|
-
import
|
|
20322
|
+
import chalk9 from "chalk";
|
|
20281
20323
|
async function useWorkspace(value2) {
|
|
20282
20324
|
const apiKey = getApiKey();
|
|
20283
20325
|
if (!apiKey)
|
|
@@ -20302,10 +20344,10 @@ async function useWorkspace(value2) {
|
|
|
20302
20344
|
function createWorkspacesCommand() {
|
|
20303
20345
|
const workspaces = new Command4("workspaces").alias("workspace").description("List, select and inspect workspaces").addHelpText("after", `
|
|
20304
20346
|
Examples:
|
|
20305
|
-
${
|
|
20306
|
-
${
|
|
20307
|
-
${
|
|
20308
|
-
${
|
|
20347
|
+
${chalk9.dim("$")} mutagent workspaces list
|
|
20348
|
+
${chalk9.dim("$")} mutagent workspaces use <name|id> ${chalk9.dim("# Every later command works in this workspace")}
|
|
20349
|
+
${chalk9.dim("$")} mutagent workspaces current --json
|
|
20350
|
+
${chalk9.dim("$")} mutagent providers list --workspace <name|id> ${chalk9.dim("# One command in another workspace")}
|
|
20309
20351
|
|
|
20310
20352
|
The CLI key from \`mutagent login\` works in every workspace you are a member of in its
|
|
20311
20353
|
organization. Workspace precedence: --workspace, then MUTAGENT_WORKSPACE_ID, then the
|
|
@@ -20315,8 +20357,8 @@ Create or change workspaces in the dashboard: ${getAppBaseUrl()}
|
|
|
20315
20357
|
`);
|
|
20316
20358
|
workspaces.command("list").alias("ls").description("List your workspaces in the key's organization (* = selected)").option("-l, --limit <n>", "Limit results", "50").option("-o, --offset <n>", "Offset for pagination").addHelpText("after", `
|
|
20317
20359
|
Examples:
|
|
20318
|
-
${
|
|
20319
|
-
${
|
|
20360
|
+
${chalk9.dim("$")} mutagent workspaces list
|
|
20361
|
+
${chalk9.dim("$")} mutagent workspaces list --limit 10 --json
|
|
20320
20362
|
|
|
20321
20363
|
Lists only workspaces you are a member of. Works even when the selected workspace is no
|
|
20322
20364
|
longer available, so you can pick another with: mutagent workspaces use <name>
|
|
@@ -20360,8 +20402,8 @@ longer available, so you can pick another with: mutagent workspaces use <name>
|
|
|
20360
20402
|
});
|
|
20361
20403
|
workspaces.command("use").description("Select the workspace every later command works in").argument("<name|id>", "Workspace name or id").addHelpText("after", `
|
|
20362
20404
|
Examples:
|
|
20363
|
-
${
|
|
20364
|
-
${
|
|
20405
|
+
${chalk9.dim("$")} mutagent workspaces use staging
|
|
20406
|
+
${chalk9.dim("$")} mutagent workspaces use <workspace-id> --json
|
|
20365
20407
|
|
|
20366
20408
|
Resolves against your workspaces in the key's organization and saves the choice. No
|
|
20367
20409
|
browser and no prompt. A workspace in another organization needs a key for that
|
|
@@ -20382,8 +20424,8 @@ organization: mutagent login --org <slug>. Two workspaces with the same name: pa
|
|
|
20382
20424
|
});
|
|
20383
20425
|
workspaces.command("current").description("Show the key's scope, organization and the verified workspace").addHelpText("after", `
|
|
20384
20426
|
Examples:
|
|
20385
|
-
${
|
|
20386
|
-
${
|
|
20427
|
+
${chalk9.dim("$")} mutagent workspaces current
|
|
20428
|
+
${chalk9.dim("$")} mutagent workspaces current --json
|
|
20387
20429
|
|
|
20388
20430
|
Asks the server (GET /api/api-keys/self) with the workspace this command would use, so
|
|
20389
20431
|
the answer is verified, not read from local config.
|
|
@@ -20430,8 +20472,8 @@ the answer is verified, not read from local config.
|
|
|
20430
20472
|
});
|
|
20431
20473
|
workspaces.command("get").description("Get workspace details").argument("<id>", "Workspace ID").addHelpText("after", `
|
|
20432
20474
|
Examples:
|
|
20433
|
-
${
|
|
20434
|
-
${
|
|
20475
|
+
${chalk9.dim("$")} mutagent workspaces get <workspace-id>
|
|
20476
|
+
${chalk9.dim("$")} mutagent workspaces get <workspace-id> --json
|
|
20435
20477
|
`).action(async (id) => {
|
|
20436
20478
|
const isJson = getJsonFlag(workspaces);
|
|
20437
20479
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -20466,14 +20508,14 @@ var VALID_CONFIG_KEYS = ["apiKey", "endpoint", "format", "timeout", "defaultWork
|
|
|
20466
20508
|
function createConfigCommand() {
|
|
20467
20509
|
const config = new Command5("config").description("Manage CLI configuration").addHelpText("after", `
|
|
20468
20510
|
Examples:
|
|
20469
|
-
${
|
|
20470
|
-
${
|
|
20471
|
-
${
|
|
20511
|
+
${chalk10.dim("$")} mutagent config list
|
|
20512
|
+
${chalk10.dim("$")} mutagent config get endpoint
|
|
20513
|
+
${chalk10.dim("$")} mutagent config set workspace <name|id> ${chalk10.dim("# Same as: mutagent workspaces use")}
|
|
20472
20514
|
`);
|
|
20473
20515
|
config.command("list").alias("ls").description("List all configuration").addHelpText("after", `
|
|
20474
20516
|
Examples:
|
|
20475
|
-
${
|
|
20476
|
-
${
|
|
20517
|
+
${chalk10.dim("$")} mutagent config list
|
|
20518
|
+
${chalk10.dim("$")} mutagent config list --json
|
|
20477
20519
|
`).action(() => {
|
|
20478
20520
|
const isJson = getJsonFlag(config);
|
|
20479
20521
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -20486,12 +20528,12 @@ Examples:
|
|
|
20486
20528
|
});
|
|
20487
20529
|
config.command("get").description("Get configuration value").argument("<key>", `Configuration key (${VALID_CONFIG_KEYS.join(", ")})`).addHelpText("after", `
|
|
20488
20530
|
Examples:
|
|
20489
|
-
${
|
|
20490
|
-
${
|
|
20491
|
-
${
|
|
20531
|
+
${chalk10.dim("$")} mutagent config get endpoint
|
|
20532
|
+
${chalk10.dim("$")} mutagent config get defaultWorkspace
|
|
20533
|
+
${chalk10.dim("$")} mutagent config get apiKey --json
|
|
20492
20534
|
|
|
20493
|
-
${
|
|
20494
|
-
${
|
|
20535
|
+
${chalk10.dim(`Keys: ${VALID_CONFIG_KEYS.join(", ")}`)}
|
|
20536
|
+
${chalk10.dim("A key with no value set is reported as unknown.")}
|
|
20495
20537
|
`).action((key) => {
|
|
20496
20538
|
const isJson = getJsonFlag(config);
|
|
20497
20539
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -20516,10 +20558,10 @@ ${chalk9.dim("A key with no value set is reported as unknown.")}
|
|
|
20516
20558
|
const set2 = new Command5("set").description("Set configuration value");
|
|
20517
20559
|
set2.command("workspace").description("Select the workspace every later command works in (same as: workspaces use)").argument("<name|id>", "Workspace name or id").addHelpText("after", `
|
|
20518
20560
|
Examples:
|
|
20519
|
-
${
|
|
20520
|
-
${
|
|
20561
|
+
${chalk10.dim("$")} mutagent config set workspace staging
|
|
20562
|
+
${chalk10.dim("$")} mutagent config set workspace <workspace-id>
|
|
20521
20563
|
|
|
20522
|
-
${
|
|
20564
|
+
${chalk10.dim("Runs mutagent workspaces use: resolves the name among your workspaces and saves it.")}
|
|
20523
20565
|
`).action(async (value2) => {
|
|
20524
20566
|
const isJson = getJsonFlag(config);
|
|
20525
20567
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -20536,10 +20578,10 @@ ${chalk9.dim("Runs mutagent workspaces use: resolves the name among your workspa
|
|
|
20536
20578
|
});
|
|
20537
20579
|
set2.command("org").description("Confirm the key's organization (it comes from the key; nothing is stored)").argument("<id|slug>", "Organization id or slug").addHelpText("after", `
|
|
20538
20580
|
Examples:
|
|
20539
|
-
${
|
|
20581
|
+
${chalk10.dim("$")} mutagent config set org <org-id|slug>
|
|
20540
20582
|
|
|
20541
|
-
${
|
|
20542
|
-
${
|
|
20583
|
+
${chalk10.dim("The CLI key belongs to one organization. The same organization: nothing to do.")}
|
|
20584
|
+
${chalk10.dim("Another organization: sign in for it with mutagent login --org <id|slug>.")}
|
|
20543
20585
|
`).action(async (value2) => {
|
|
20544
20586
|
const isJson = getJsonFlag(config);
|
|
20545
20587
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -20573,14 +20615,14 @@ init_sdk_client();
|
|
|
20573
20615
|
init_output();
|
|
20574
20616
|
init_errors();
|
|
20575
20617
|
import { Command as Command6 } from "commander";
|
|
20576
|
-
import
|
|
20618
|
+
import chalk15 from "chalk";
|
|
20577
20619
|
import { LlmProviderType as ProviderCatalogId } from "@mutagent/sdk/models";
|
|
20578
20620
|
|
|
20579
20621
|
// src/commands/providers/add.ts
|
|
20580
20622
|
init_sdk_client();
|
|
20581
20623
|
init_output();
|
|
20582
20624
|
init_errors();
|
|
20583
|
-
import
|
|
20625
|
+
import chalk11 from "chalk";
|
|
20584
20626
|
|
|
20585
20627
|
// ../mutagent/src/modules/tenancy/providers/catalog.ts
|
|
20586
20628
|
var apiKeyField = (description) => ({
|
|
@@ -21097,15 +21139,15 @@ function collectCredentialFields(options) {
|
|
|
21097
21139
|
function registerAddCommand(parent) {
|
|
21098
21140
|
parent.command("add").description("Add an LLM provider to the workspace").requiredOption("-p, --provider <type>", "LLM provider type (openai, anthropic, azure, ...)").requiredOption("-n, --name <name>", "Display name").option("--api-key-stdin", "Read the LLM provider API key from stdin, keeping it out of shell history (every type except vertex)").option("-k, --api-key <key>", "LLM provider API key (not your Mutagent key); every type except vertex").option("--service-account-key <json>", "Google Vertex service-account credential JSON").option("--hosted-family <family>", `Model family a gateway (azure, vertex, bedrock) serves: ${HOSTED_FAMILIES.join(", ")}`).option("--base-url <url>", "Base URL of the API").option("--api-format <format>", apiFormatHelpText()).option("--resource-endpoint <url>", "Azure resource endpoint").option("--deployment-name <name>", "Azure deployment name").option("--api-version <version>", "Azure API version (e.g. 2024-08-01-preview)").option("--project-id <id>", "Google Vertex project ID").option("--region <region>", "Region (Vertex location, or AWS Bedrock region)").option("--set-default", "Make it the workspace's default LLM provider of its type").addHelpText("after", `
|
|
21099
21141
|
Examples:
|
|
21100
|
-
${
|
|
21101
|
-
${
|
|
21102
|
-
${
|
|
21103
|
-
${
|
|
21142
|
+
${chalk11.dim("$")} mutagent providers add --provider openai --name "My OpenAI" --api-key-stdin < openai-key.txt
|
|
21143
|
+
${chalk11.dim("$")} printf %s "$OPENAI_API_KEY" | mutagent providers add --provider openai --name "My OpenAI" --api-key-stdin
|
|
21144
|
+
${chalk11.dim("$")} mutagent providers add --provider openai --name "My OpenAI" --api-key $OPENAI_API_KEY
|
|
21145
|
+
${chalk11.dim("$")} mutagent providers add --provider azure --name "Azure GPT" --api-key $KEY \\
|
|
21104
21146
|
--hosted-family openai --resource-endpoint https://my.openai.azure.com --deployment-name gpt-5
|
|
21105
|
-
${
|
|
21106
|
-
${
|
|
21147
|
+
${chalk11.dim("$")} mutagent providers add --provider bedrock --name "Bedrock Claude" --api-key $KEY --region us-east-1
|
|
21148
|
+
${chalk11.dim("$")} mutagent providers add --provider custom --name "My gateway" --api-key $KEY \\
|
|
21107
21149
|
--base-url https://llm.example.com/v1 --api-format anthropic
|
|
21108
|
-
${
|
|
21150
|
+
${chalk11.dim("$")} mutagent providers add --provider zai-coding-plan --name "Z.AI" --api-key $ZAI_API_KEY
|
|
21109
21151
|
|
|
21110
21152
|
azure and vertex serve another vendor's models and need --hosted-family; bedrock serves
|
|
21111
21153
|
anthropic and needs none. Other LLM provider types must not set it.
|
|
@@ -21199,10 +21241,10 @@ AI Agent Directive:
|
|
|
21199
21241
|
console.log(` Workspace: ${workspaceId}`);
|
|
21200
21242
|
console.log(` URL: ${providerLink(created.id)}`);
|
|
21201
21243
|
if (options.setDefault) {
|
|
21202
|
-
console.log(
|
|
21244
|
+
console.log(chalk11.green(" Set as the default LLM provider"));
|
|
21203
21245
|
}
|
|
21204
21246
|
console.log("");
|
|
21205
|
-
console.log(
|
|
21247
|
+
console.log(chalk11.dim("API key is encrypted server-side. Use `providers get` to see masked key."));
|
|
21206
21248
|
}
|
|
21207
21249
|
} catch (error3) {
|
|
21208
21250
|
handleError(error3, isJson);
|
|
@@ -21242,15 +21284,15 @@ function buildProviderCreatedDirective(provider, workspaceId) {
|
|
|
21242
21284
|
init_sdk_client();
|
|
21243
21285
|
init_output();
|
|
21244
21286
|
init_errors();
|
|
21245
|
-
import
|
|
21287
|
+
import chalk12 from "chalk";
|
|
21246
21288
|
function registerUpdateCommand(parent) {
|
|
21247
21289
|
parent.command("update").description("Update an LLM provider").argument("<id>", "LLM provider ID (from: mutagent providers list)").option("-n, --name <name>", "Updated display name").option("--api-key-stdin", "Read the new LLM provider API key from stdin, keeping it out of shell history").option("-k, --api-key <key>", "New LLM provider API key (not your Mutagent key); stored encrypted").option("--active <bool>", "Activate or deactivate (true|false)").option("--set-default", "Make it the workspace's default LLM provider of its type").option("--base-url <url>", 'Updated base URL (use "" to clear)').addHelpText("after", `
|
|
21248
21290
|
Examples:
|
|
21249
|
-
${
|
|
21250
|
-
${
|
|
21251
|
-
${
|
|
21252
|
-
${
|
|
21253
|
-
${
|
|
21291
|
+
${chalk12.dim("$")} mutagent providers update <provider-id> --api-key-stdin --json < new-key.txt
|
|
21292
|
+
${chalk12.dim("$")} mutagent providers update <provider-id> --name "New Name"
|
|
21293
|
+
${chalk12.dim("$")} mutagent providers update <provider-id> --api-key $NEW_KEY --json
|
|
21294
|
+
${chalk12.dim("$")} mutagent providers update <provider-id> --active false
|
|
21295
|
+
${chalk12.dim("$")} mutagent providers update <provider-id> --set-default --json
|
|
21254
21296
|
|
|
21255
21297
|
Only the fields you pass change. An update never sets the workspace default model.
|
|
21256
21298
|
--api-key-stdin reads the key from stdin and drops one trailing newline; give it or
|
|
@@ -21312,7 +21354,7 @@ AI Agent Directive:
|
|
|
21312
21354
|
}
|
|
21313
21355
|
console.log(` URL: ${providerLink(updated.id)}`);
|
|
21314
21356
|
if (apiKey !== undefined) {
|
|
21315
|
-
console.log(
|
|
21357
|
+
console.log(chalk12.dim(" API key re-encrypted server-side."));
|
|
21316
21358
|
}
|
|
21317
21359
|
}
|
|
21318
21360
|
} catch (error3) {
|
|
@@ -21353,12 +21395,12 @@ function buildProviderUpdatedDirective(provider, requestId) {
|
|
|
21353
21395
|
init_sdk_client();
|
|
21354
21396
|
init_output();
|
|
21355
21397
|
init_errors();
|
|
21356
|
-
import
|
|
21398
|
+
import chalk13 from "chalk";
|
|
21357
21399
|
function registerDeleteCommand(parent) {
|
|
21358
21400
|
parent.command("delete").alias("rm").description("Delete an LLM provider").argument("<id>", "LLM provider ID (from: mutagent providers list)").option("-f, --force", "Confirm the delete (required in every mode, --json included)").addHelpText("after", `
|
|
21359
21401
|
Examples:
|
|
21360
|
-
${
|
|
21361
|
-
${
|
|
21402
|
+
${chalk13.dim("$")} mutagent providers delete <provider-id> --force
|
|
21403
|
+
${chalk13.dim("$")} mutagent providers delete <provider-id> --force --json
|
|
21362
21404
|
|
|
21363
21405
|
Without --force the command refuses (CONFIRMATION_REQUIRED, exit 1) and sends nothing,
|
|
21364
21406
|
--json included; it never prompts.
|
|
@@ -21441,7 +21483,7 @@ init_sdk_client();
|
|
|
21441
21483
|
init_config();
|
|
21442
21484
|
init_output();
|
|
21443
21485
|
init_errors();
|
|
21444
|
-
import
|
|
21486
|
+
import chalk14 from "chalk";
|
|
21445
21487
|
import { createInterface } from "readline";
|
|
21446
21488
|
init_known_secrets();
|
|
21447
21489
|
init_secret_scrub();
|
|
@@ -22085,13 +22127,13 @@ async function askConsent(question) {
|
|
|
22085
22127
|
function statusGlyph(result) {
|
|
22086
22128
|
switch (result.status) {
|
|
22087
22129
|
case "mirrored":
|
|
22088
|
-
return
|
|
22130
|
+
return chalk14.green("mirrored");
|
|
22089
22131
|
case "updated":
|
|
22090
|
-
return
|
|
22132
|
+
return chalk14.green("updated ");
|
|
22091
22133
|
case "skipped":
|
|
22092
|
-
return
|
|
22134
|
+
return chalk14.yellow("skipped ");
|
|
22093
22135
|
case "failed":
|
|
22094
|
-
return
|
|
22136
|
+
return chalk14.red("failed ");
|
|
22095
22137
|
default:
|
|
22096
22138
|
return result.status;
|
|
22097
22139
|
}
|
|
@@ -22099,12 +22141,12 @@ function statusGlyph(result) {
|
|
|
22099
22141
|
function registerMirrorCommand(parent) {
|
|
22100
22142
|
parent.command("mirror").description("Copy the API keys from your local Helix login store into the workspace as LLM providers").option("-y, --yes", "Consent without prompting (required when non-interactive)").option("--no-overwrite", "Leave LLM providers the workspace already has untouched").option("--channel <channel>", `Helix channel whose store is read: ${HELIX_CHANNELS2.join(" | ")}`, "stable").option("--provider <id>", "Only this local LLM provider id (repeatable)", (value2, prev = []) => [...prev, value2]).addHelpText("after", `
|
|
22101
22143
|
Examples:
|
|
22102
|
-
${
|
|
22103
|
-
${
|
|
22104
|
-
${
|
|
22105
|
-
${
|
|
22106
|
-
${
|
|
22107
|
-
${
|
|
22144
|
+
${chalk14.dim("$")} mutagent providers mirror
|
|
22145
|
+
${chalk14.dim("$")} mutagent providers mirror --json ${chalk14.dim("Show the plan without sending anything")}
|
|
22146
|
+
${chalk14.dim("$")} mutagent providers mirror --yes --json
|
|
22147
|
+
${chalk14.dim("$")} mutagent providers mirror --provider zai --provider openrouter
|
|
22148
|
+
${chalk14.dim("$")} mutagent providers mirror --no-overwrite
|
|
22149
|
+
${chalk14.dim("$")} mutagent providers mirror --channel rc
|
|
22108
22150
|
|
|
22109
22151
|
Reads the API keys in your local Helix login store (~/.mutagent/agent, ~/.mutagent/agent-rc
|
|
22110
22152
|
with --channel rc, or $HELIX_CODING_AGENT_DIR when set) and creates or updates the
|
|
@@ -22185,7 +22227,7 @@ AI Agent Directive:
|
|
|
22185
22227
|
if (plan.length === 0) {
|
|
22186
22228
|
output.info("Nothing to mirror.");
|
|
22187
22229
|
} else {
|
|
22188
|
-
console.log(
|
|
22230
|
+
console.log(chalk14.bold(`
|
|
22189
22231
|
Plan:`));
|
|
22190
22232
|
for (const line of describePlan(plan))
|
|
22191
22233
|
console.log(` ${scrubSecretsSuccess(line, [apiKey, ...knownSecrets()])}`);
|
|
@@ -22235,7 +22277,7 @@ Plan:`));
|
|
|
22235
22277
|
});
|
|
22236
22278
|
} else {
|
|
22237
22279
|
for (const result of results) {
|
|
22238
|
-
const tail = result.status === "failed" ?
|
|
22280
|
+
const tail = result.status === "failed" ? chalk14.red(result.error ?? "") : result.status === "skipped" ? chalk14.dim(result.reason ?? "") : chalk14.dim(`${result.rowId ? `row ${result.rowId}` : ""}${result.workspaceDefaultModelSet ? `${result.rowId ? " · " : ""}default set to ${result.workspaceDefaultModelSet}` : ""}`);
|
|
22239
22281
|
const lands = result.provider ? ` → ${result.provider === "custom" ? `custom (${result.harnessProvider ?? result.id})` : result.provider}` : "";
|
|
22240
22282
|
console.log(scrubSecretsSuccess(` ${statusGlyph(result)} ${result.id}${lands} ${tail}`, [
|
|
22241
22283
|
apiKey,
|
|
@@ -22283,13 +22325,13 @@ function validateProviderType(type4) {
|
|
|
22283
22325
|
function createProvidersCommand() {
|
|
22284
22326
|
const providers = new Command6("providers").description("Manage LLM provider configurations (BYOK)").addHelpText("after", `
|
|
22285
22327
|
Examples:
|
|
22286
|
-
${
|
|
22287
|
-
${
|
|
22288
|
-
${
|
|
22289
|
-
${
|
|
22290
|
-
${
|
|
22291
|
-
${
|
|
22292
|
-
${
|
|
22328
|
+
${chalk15.dim("$")} mutagent providers mirror
|
|
22329
|
+
${chalk15.dim("$")} mutagent providers list
|
|
22330
|
+
${chalk15.dim("$")} mutagent providers get <provider-id>
|
|
22331
|
+
${chalk15.dim("$")} mutagent providers add --provider openai --name "My OpenAI" --api-key $KEY
|
|
22332
|
+
${chalk15.dim("$")} mutagent providers test <provider-id>
|
|
22333
|
+
${chalk15.dim("$")} mutagent providers update <provider-id> --name "New Name"
|
|
22334
|
+
${chalk15.dim("$")} mutagent providers delete <provider-id> --force
|
|
22293
22335
|
|
|
22294
22336
|
LLM providers hold the keys Helix uses to call models in the cloud. See what they
|
|
22295
22337
|
unlock with \`mutagent helix models\`.
|
|
@@ -22298,10 +22340,10 @@ LLM provider types: ${VALID_PROVIDER_TYPES.join(", ")}
|
|
|
22298
22340
|
`);
|
|
22299
22341
|
providers.command("list").alias("ls").description("List the workspace's LLM providers").option("-l, --limit <n>", "Limit results", "50").option("-o, --offset <n>", "Offset for pagination").option("-t, --type <type>", "Filter by LLM provider type").option("-m, --models", "Show catalogue models for each LLM provider type (for Helix cloud models: mutagent helix models)").addHelpText("after", `
|
|
22300
22342
|
Examples:
|
|
22301
|
-
${
|
|
22302
|
-
${
|
|
22303
|
-
${
|
|
22304
|
-
${
|
|
22343
|
+
${chalk15.dim("$")} mutagent providers list
|
|
22344
|
+
${chalk15.dim("$")} mutagent providers list --type openai
|
|
22345
|
+
${chalk15.dim("$")} mutagent providers list --models
|
|
22346
|
+
${chalk15.dim("$")} mutagent providers list --json
|
|
22305
22347
|
`).action(async (options) => {
|
|
22306
22348
|
const isJson = getJsonFlag(providers);
|
|
22307
22349
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -22344,6 +22386,7 @@ Examples:
|
|
|
22344
22386
|
name: p.name,
|
|
22345
22387
|
provider: p.provider,
|
|
22346
22388
|
...harnessProvider ? { harnessProvider } : {},
|
|
22389
|
+
baseUrl: p.baseUrl ?? null,
|
|
22347
22390
|
isActive: p.isActive,
|
|
22348
22391
|
isDefault: p.isDefault ?? false,
|
|
22349
22392
|
updatedAt: p.updatedAt,
|
|
@@ -22377,8 +22420,8 @@ Examples:
|
|
|
22377
22420
|
});
|
|
22378
22421
|
providers.command("get").description("Show one LLM provider").argument("<id>", "LLM provider ID (from: mutagent providers list)").addHelpText("after", `
|
|
22379
22422
|
Examples:
|
|
22380
|
-
${
|
|
22381
|
-
${
|
|
22423
|
+
${chalk15.dim("$")} mutagent providers get <provider-id>
|
|
22424
|
+
${chalk15.dim("$")} mutagent providers get <provider-id> --json
|
|
22382
22425
|
`).action(async (id) => {
|
|
22383
22426
|
const isJson = getJsonFlag(providers);
|
|
22384
22427
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -22407,10 +22450,10 @@ Examples:
|
|
|
22407
22450
|
});
|
|
22408
22451
|
providers.command("test").description("Test an LLM provider's connection").argument("<id>", "LLM provider ID (from: mutagent providers list)").addHelpText("after", `
|
|
22409
22452
|
Examples:
|
|
22410
|
-
${
|
|
22411
|
-
${
|
|
22453
|
+
${chalk15.dim("$")} mutagent providers test <provider-id>
|
|
22454
|
+
${chalk15.dim("$")} mutagent providers test <provider-id> --json
|
|
22412
22455
|
|
|
22413
|
-
${
|
|
22456
|
+
${chalk15.dim("Tests the connection and lists the models the LLM provider reports.")}
|
|
22414
22457
|
`).action(async (id) => {
|
|
22415
22458
|
const isJson = getJsonFlag(providers);
|
|
22416
22459
|
const output = new OutputFormatter(isJson ? "json" : "table");
|
|
@@ -22427,9 +22470,9 @@ ${chalk14.dim("Tests the connection and lists the models the LLM provider report
|
|
|
22427
22470
|
} else {
|
|
22428
22471
|
const latency = typeof result.latencyMs === "number" ? ` (${String(result.latencyMs)}ms)` : "";
|
|
22429
22472
|
output.success(`LLM provider test passed${latency}`);
|
|
22430
|
-
console.log(
|
|
22473
|
+
console.log(chalk15.green(`Message: ${result.message}`));
|
|
22431
22474
|
if (result.models && result.models.length > 0) {
|
|
22432
|
-
console.log(
|
|
22475
|
+
console.log(chalk15.bold(`
|
|
22433
22476
|
Available Models:`));
|
|
22434
22477
|
result.models.forEach((model2) => {
|
|
22435
22478
|
console.log(` - ${model2}`);
|
|
@@ -22452,14 +22495,14 @@ init_config();
|
|
|
22452
22495
|
init_output();
|
|
22453
22496
|
init_errors();
|
|
22454
22497
|
import { Command as Command8 } from "commander";
|
|
22455
|
-
import
|
|
22498
|
+
import chalk17 from "chalk";
|
|
22456
22499
|
import { readFileSync as readFileSync7 } from "fs";
|
|
22457
22500
|
import { join as join16 } from "path";
|
|
22458
22501
|
|
|
22459
22502
|
// src/commands/skills.ts
|
|
22460
22503
|
init_output();
|
|
22461
22504
|
import { Command as Command7 } from "commander";
|
|
22462
|
-
import
|
|
22505
|
+
import chalk16 from "chalk";
|
|
22463
22506
|
import { existsSync as existsSync10, mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
22464
22507
|
import { dirname as dirname5, join as join15 } from "path";
|
|
22465
22508
|
import { execSync } from "child_process";
|
|
@@ -23267,7 +23310,7 @@ function createSkillsCommand() {
|
|
|
23267
23310
|
const skills = new Command7("skills").description("Manage Mutagent CLI skills for coding agents");
|
|
23268
23311
|
skills.command("install").description("Install Mutagent CLI skill for Claude Code").addHelpText("after", `
|
|
23269
23312
|
Examples:
|
|
23270
|
-
${
|
|
23313
|
+
${chalk16.dim("$")} mutagent skills install
|
|
23271
23314
|
|
|
23272
23315
|
This creates a Claude Code skill at .claude/skills/mutagent-cli/SKILL.md
|
|
23273
23316
|
that teaches coding agents how to use the Mutagent CLI effectively.
|
|
@@ -23287,7 +23330,7 @@ that teaches coding agents how to use the Mutagent CLI effectively.
|
|
|
23287
23330
|
});
|
|
23288
23331
|
} else {
|
|
23289
23332
|
output.success(`Installed Mutagent CLI skill`);
|
|
23290
|
-
console.log(` ${
|
|
23333
|
+
console.log(` ${chalk16.dim("Dir:")} ${result.skillDir}`);
|
|
23291
23334
|
console.log("");
|
|
23292
23335
|
for (let i = 0;i < result.files.length; i++) {
|
|
23293
23336
|
const entry = result.files[i];
|
|
@@ -23295,12 +23338,12 @@ that teaches coding agents how to use the Mutagent CLI effectively.
|
|
|
23295
23338
|
continue;
|
|
23296
23339
|
const isLast = i === result.files.length - 1;
|
|
23297
23340
|
const prefix = isLast ? "└─" : "├─";
|
|
23298
|
-
console.log(` ${
|
|
23341
|
+
console.log(` ${chalk16.dim(prefix)} ${entry.relPath} ${chalk16.dim(`(${String(entry.bytes)} bytes)`)}`);
|
|
23299
23342
|
}
|
|
23300
23343
|
console.log("");
|
|
23301
|
-
console.log(` ${
|
|
23302
|
-
console.log(` ${
|
|
23303
|
-
console.log(` ${
|
|
23344
|
+
console.log(` ${chalk16.dim(`${String(result.files.length)} file(s), ${String(result.totalBytes)} bytes total.`)}`);
|
|
23345
|
+
console.log(` ${chalk16.dim("This skill teaches coding agents how to use the Mutagent CLI.")}`);
|
|
23346
|
+
console.log(` ${chalk16.dim("It will be automatically loaded by Claude Code when relevant triggers match.")}`);
|
|
23304
23347
|
}
|
|
23305
23348
|
});
|
|
23306
23349
|
return skills;
|
|
@@ -23311,7 +23354,7 @@ var LOGIN_GUIDANCE = "Run: mutagent login — sign-up happens in the browser. Th
|
|
|
23311
23354
|
function createInitCommand(deps = {}) {
|
|
23312
23355
|
const init = new Command8("init").description("Initialize Mutagent in your project").addHelpText("after", `
|
|
23313
23356
|
Examples:
|
|
23314
|
-
${
|
|
23357
|
+
${chalk17.dim("$")} mutagent init # Write .mutagentrc.json + install the CLI skill
|
|
23315
23358
|
|
|
23316
23359
|
What it does:
|
|
23317
23360
|
1. Writes .mutagentrc.json (endpoint / workspace / org) — skipped if present
|
|
@@ -23384,11 +23427,11 @@ It never prompts. Without a sign-in it exits 3 (AUTH_REQUIRED) and names the sig
|
|
|
23384
23427
|
});
|
|
23385
23428
|
} else {
|
|
23386
23429
|
console.log("");
|
|
23387
|
-
console.log(
|
|
23388
|
-
console.log(` ${
|
|
23430
|
+
console.log(chalk17.bold(` What's next:`));
|
|
23431
|
+
console.log(` ${chalk17.cyan("mutagent install helix".padEnd(30))}${chalk17.dim("# the standalone Helix binary")}`);
|
|
23389
23432
|
console.log("");
|
|
23390
|
-
console.log(
|
|
23391
|
-
console.log(
|
|
23433
|
+
console.log(chalk17.dim(" Your coding agent now knows these workflows — restart it to pick up"));
|
|
23434
|
+
console.log(chalk17.dim(' the skill, then just say "set up Mutagent on this project".'));
|
|
23392
23435
|
}
|
|
23393
23436
|
} catch (error3) {
|
|
23394
23437
|
handleError(error3, isJson);
|
|
@@ -23403,13 +23446,12 @@ init_output();
|
|
|
23403
23446
|
init_errors();
|
|
23404
23447
|
init_sdk_client();
|
|
23405
23448
|
import { Command as Command9 } from "commander";
|
|
23406
|
-
import
|
|
23407
|
-
var PROVIDERS_URL = "https://app.mutagent.io/settings/providers";
|
|
23449
|
+
import chalk18 from "chalk";
|
|
23408
23450
|
function createUsageCommand() {
|
|
23409
23451
|
const usage2 = new Command9("usage").description("Count the workspace's LLM providers and the workspaces you can see").addHelpText("after", `
|
|
23410
23452
|
Examples:
|
|
23411
|
-
${
|
|
23412
|
-
${
|
|
23453
|
+
${chalk18.dim("$")} mutagent usage
|
|
23454
|
+
${chalk18.dim("$")} mutagent usage --json
|
|
23413
23455
|
`);
|
|
23414
23456
|
usage2.action(async () => {
|
|
23415
23457
|
const isJson = getJsonFlag(usage2);
|
|
@@ -23437,20 +23479,20 @@ Examples:
|
|
|
23437
23479
|
workspaces: workspaceCount
|
|
23438
23480
|
},
|
|
23439
23481
|
_links: {
|
|
23440
|
-
providers:
|
|
23441
|
-
dashboard:
|
|
23482
|
+
providers: providerSettingsLink(),
|
|
23483
|
+
dashboard: getAppBaseUrl()
|
|
23442
23484
|
}
|
|
23443
23485
|
});
|
|
23444
23486
|
} else {
|
|
23445
23487
|
console.log("");
|
|
23446
|
-
console.log(
|
|
23447
|
-
console.log(
|
|
23488
|
+
console.log(chalk18.bold("\uD83D\uDCCA Mutagent Usage"));
|
|
23489
|
+
console.log(chalk18.dim("─".repeat(45)));
|
|
23448
23490
|
console.log("");
|
|
23449
|
-
console.log(
|
|
23450
|
-
console.log(` Providers: ${
|
|
23451
|
-
console.log(` Workspaces: ${
|
|
23491
|
+
console.log(chalk18.bold("Resources:"));
|
|
23492
|
+
console.log(` Providers: ${chalk18.cyan(String(providerCount))}`);
|
|
23493
|
+
console.log(` Workspaces: ${chalk18.cyan(String(workspaceCount))}`);
|
|
23452
23494
|
console.log("");
|
|
23453
|
-
console.log(` Manage providers: ${
|
|
23495
|
+
console.log(` Manage providers: ${chalk18.underline(providerSettingsLink())}`);
|
|
23454
23496
|
console.log("");
|
|
23455
23497
|
}
|
|
23456
23498
|
} catch (error3) {
|
|
@@ -23464,7 +23506,7 @@ Examples:
|
|
|
23464
23506
|
import { readFileSync as readFileSync11 } from "node:fs";
|
|
23465
23507
|
import { basename as basename4 } from "node:path";
|
|
23466
23508
|
import { Command as Command10 } from "commander";
|
|
23467
|
-
import
|
|
23509
|
+
import chalk19 from "chalk";
|
|
23468
23510
|
|
|
23469
23511
|
// src/commands/hooks/import-transcript.ts
|
|
23470
23512
|
var MAX_SPAN_TEXT = 4000;
|
|
@@ -24368,7 +24410,7 @@ Claude Code session telemetry:
|
|
|
24368
24410
|
Sends session activity (turns, tool calls, subagents, compactions) to the Mutagent
|
|
24369
24411
|
traces API.
|
|
24370
24412
|
|
|
24371
|
-
${
|
|
24413
|
+
${chalk19.dim("$")} mutagent hooks install ${chalk19.dim("Add the Mutagent hooks to .claude/settings.local.json (11 events)")}
|
|
24372
24414
|
|
|
24373
24415
|
The claude-code subcommands are what those hooks run; Claude Code calls them.
|
|
24374
24416
|
`);
|
|
@@ -24460,8 +24502,8 @@ unparseable lines without sending anything.
|
|
|
24460
24502
|
});
|
|
24461
24503
|
hooks.command("install").description("Add the Mutagent hooks to .claude/settings.local.json (merges; existing hooks stay)").option("--cwd <dir>", "Target directory", process.cwd()).addHelpText("after", `
|
|
24462
24504
|
Examples:
|
|
24463
|
-
${
|
|
24464
|
-
${
|
|
24505
|
+
${chalk19.dim("$")} mutagent hooks install
|
|
24506
|
+
${chalk19.dim("$")} mutagent hooks install --cwd ../other-project
|
|
24465
24507
|
|
|
24466
24508
|
Merges the Mutagent hooks into all 11 Claude Code events of
|
|
24467
24509
|
.claude/settings.local.json (created if missing). Hooks already present are left
|
|
@@ -24558,7 +24600,7 @@ init_errors();
|
|
|
24558
24600
|
init_config();
|
|
24559
24601
|
init_organization_scope();
|
|
24560
24602
|
import { Command as Command11 } from "commander";
|
|
24561
|
-
import
|
|
24603
|
+
import chalk22 from "chalk";
|
|
24562
24604
|
import { type as osType, release as osRelease } from "os";
|
|
24563
24605
|
import { readFileSync as readFileSync13 } from "fs";
|
|
24564
24606
|
import { join as join20, dirname as dirname6 } from "path";
|
|
@@ -24577,7 +24619,7 @@ import {
|
|
|
24577
24619
|
readSync,
|
|
24578
24620
|
closeSync
|
|
24579
24621
|
} from "fs";
|
|
24580
|
-
import
|
|
24622
|
+
import chalk20 from "chalk";
|
|
24581
24623
|
var TAIL_BYTES = 200000;
|
|
24582
24624
|
function defaultReadTail(path, tailBytes) {
|
|
24583
24625
|
const { size } = fsStatSync(path);
|
|
@@ -24653,7 +24695,7 @@ Or omit the path to auto-detect the newest coding-agent session.`);
|
|
|
24653
24695
|
}
|
|
24654
24696
|
}
|
|
24655
24697
|
if (!newest) {
|
|
24656
|
-
warn(
|
|
24698
|
+
warn(chalk20.yellow("⚠ No coding-agent transcript found; sending feedback without one."));
|
|
24657
24699
|
return null;
|
|
24658
24700
|
}
|
|
24659
24701
|
const { content, truncated } = readTail(newest.path, TAIL_BYTES);
|
|
@@ -24668,7 +24710,7 @@ Or omit the path to auto-detect the newest coding-agent session.`);
|
|
|
24668
24710
|
|
|
24669
24711
|
// src/lib/feedback-safety.ts
|
|
24670
24712
|
init_secret_scan();
|
|
24671
|
-
import
|
|
24713
|
+
import chalk21 from "chalk";
|
|
24672
24714
|
|
|
24673
24715
|
// src/lib/by-design.ts
|
|
24674
24716
|
var NOT_FOUND = String.raw`404|not\s+found|missing|unavailable|unpublished|doesn'?t\s+exist|does\s+not\s+exist|no\s+such\s+package|cannot\s+install|can'?t\s+install|fails?\s+to\s+install`;
|
|
@@ -24739,9 +24781,9 @@ function buildPreview(transcript) {
|
|
|
24739
24781
|
function buildTranscriptWarning(preview) {
|
|
24740
24782
|
const kb = (preview.bytes / 1024).toFixed(1);
|
|
24741
24783
|
return [
|
|
24742
|
-
|
|
24743
|
-
` ${
|
|
24744
|
-
` ${
|
|
24784
|
+
chalk21.yellow("⚠ About to upload your coding-agent session transcript."),
|
|
24785
|
+
` ${chalk21.bold("Source:")} ${preview.sourcePath}`,
|
|
24786
|
+
` ${chalk21.bold("Sending:")} ${String(preview.fileCount)} file, ${kb} KB${preview.truncated ? " (tail only)" : ""}`,
|
|
24745
24787
|
"",
|
|
24746
24788
|
" A session transcript typically contains:",
|
|
24747
24789
|
" • source code and file contents you or the agent opened",
|
|
@@ -24750,9 +24792,9 @@ function buildTranscriptWarning(preview) {
|
|
|
24750
24792
|
" • internal hostnames, service names, and URLs",
|
|
24751
24793
|
" • business context from your prompts and the agent replies",
|
|
24752
24794
|
"",
|
|
24753
|
-
` ${
|
|
24754
|
-
` ${
|
|
24755
|
-
` ${
|
|
24795
|
+
` ${chalk21.dim("Credentials are scanned for and redacted automatically, but detection")}`,
|
|
24796
|
+
` ${chalk21.dim("is best-effort — review the source file if the session touched secrets.")}`,
|
|
24797
|
+
` ${chalk21.dim("Omit --attach-transcript to send feedback without it.")}`
|
|
24756
24798
|
].join(`
|
|
24757
24799
|
`);
|
|
24758
24800
|
}
|
|
@@ -24764,12 +24806,12 @@ function buildRedactionReport(redactions) {
|
|
|
24764
24806
|
byKind.set(match.label, (byKind.get(match.label) ?? 0) + 1);
|
|
24765
24807
|
}
|
|
24766
24808
|
const lines = [
|
|
24767
|
-
|
|
24809
|
+
chalk21.green(`✓ Redacted ${String(redactions.length)} credential${redactions.length === 1 ? "" : "s"} from the transcript before upload:`)
|
|
24768
24810
|
];
|
|
24769
24811
|
for (const [label, count] of byKind) {
|
|
24770
24812
|
lines.push(` • ${label} ×${String(count)}`);
|
|
24771
24813
|
}
|
|
24772
|
-
lines.push(
|
|
24814
|
+
lines.push(chalk21.dim(" These were replaced with [REDACTED:…] markers and never left your machine."));
|
|
24773
24815
|
return lines.join(`
|
|
24774
24816
|
`);
|
|
24775
24817
|
}
|
|
@@ -24777,17 +24819,17 @@ function buildByDesignNotice(entries) {
|
|
|
24777
24819
|
if (entries.length === 0)
|
|
24778
24820
|
return "";
|
|
24779
24821
|
const lines = [
|
|
24780
|
-
|
|
24822
|
+
chalk21.cyan("ℹ Heads up — this may describe intended behaviour:"),
|
|
24781
24823
|
""
|
|
24782
24824
|
];
|
|
24783
24825
|
for (const entry of entries) {
|
|
24784
|
-
lines.push(` ${
|
|
24826
|
+
lines.push(` ${chalk21.bold(entry.title)}`);
|
|
24785
24827
|
for (const line of wrap(entry.reality, 76)) {
|
|
24786
24828
|
lines.push(` ${line}`);
|
|
24787
24829
|
}
|
|
24788
24830
|
lines.push("");
|
|
24789
24831
|
}
|
|
24790
|
-
lines.push(
|
|
24832
|
+
lines.push(chalk21.dim(" Sending anyway — if this is a regression rather than the design,"), chalk21.dim(" your report is exactly what we need. Nothing was withheld."));
|
|
24791
24833
|
return lines.join(`
|
|
24792
24834
|
`);
|
|
24793
24835
|
}
|
|
@@ -24895,44 +24937,44 @@ function buildPayload(feedback, category, title, session, transcript) {
|
|
|
24895
24937
|
}
|
|
24896
24938
|
function createFeedbackCommand() {
|
|
24897
24939
|
const feedback = new Command11("feedback").description("Send product feedback to Mutagent").addHelpText("after", `
|
|
24898
|
-
${
|
|
24899
|
-
${
|
|
24900
|
-
${
|
|
24901
|
-
${
|
|
24940
|
+
${chalk22.bold("Examples:")}
|
|
24941
|
+
${chalk22.cyan('mutagent feedback send "helix session attach was easy to follow"')}
|
|
24942
|
+
${chalk22.cyan('mutagent feedback send "Eval gate was confusing" --category stage:evaluate')}
|
|
24943
|
+
${chalk22.cyan('mutagent feedback send "CLI crashed on export" --category cli --json')}
|
|
24902
24944
|
|
|
24903
24945
|
AI Agent Directive:
|
|
24904
24946
|
ALWAYS use --json: mutagent feedback send "..." --category cli --json
|
|
24905
|
-
${
|
|
24947
|
+
${chalk22.yellow("Do NOT attach a transcript by default.")} --attach-transcript uploads the
|
|
24906
24948
|
coding-agent SESSION JSONL — source code, absolute paths, branch and repository
|
|
24907
24949
|
names, internal hostnames, and the business context of the operator's prompts.
|
|
24908
24950
|
Use it only when the operator explicitly asks for it. See:
|
|
24909
|
-
${
|
|
24951
|
+
${chalk22.dim("mutagent feedback send --help")}
|
|
24910
24952
|
`);
|
|
24911
24953
|
registerFeedbackSend(feedback);
|
|
24912
24954
|
return feedback;
|
|
24913
24955
|
}
|
|
24914
24956
|
function registerFeedbackSend(feedback) {
|
|
24915
24957
|
feedback.command("send").description("Send product feedback about the Mutagent platform or CLI").argument("<feedback>", "The feedback body (content), max 10000 characters").option("--title <string>", "Short title").option("--category <value>", `Feedback category: 'cli', 'helix', or 'stage:<${VALID_STAGES.join("|")}>'`, "cli").option("--session <id>", "Link the feedback to a session").option("--attach-transcript [path]", "Attach the coding-agent session JSONL. Bare = auto-detect newest; or pass an explicit path.").addHelpText("after", `
|
|
24916
|
-
${
|
|
24917
|
-
${
|
|
24918
|
-
${
|
|
24919
|
-
${
|
|
24920
|
-
${
|
|
24921
|
-
${
|
|
24922
|
-
|
|
24923
|
-
${
|
|
24924
|
-
${
|
|
24925
|
-
${
|
|
24926
|
-
${
|
|
24927
|
-
|
|
24928
|
-
${
|
|
24958
|
+
${chalk22.bold("Examples:")}
|
|
24959
|
+
${chalk22.dim("$")} mutagent feedback send "The setup flow could show progress better"
|
|
24960
|
+
${chalk22.dim("$")} mutagent feedback send "Eval gate was confusing" --category stage:evaluate --title "eval gate unclear"
|
|
24961
|
+
${chalk22.dim("$")} mutagent feedback send "Diagnose loop stalled" --category stage:diagnose --session sess_abc123 --json
|
|
24962
|
+
${chalk22.dim("$")} mutagent feedback send "CLI crashed mid-run" --category cli --attach-transcript --json
|
|
24963
|
+
${chalk22.dim("$")} mutagent feedback send "Repro attached" --category cli --attach-transcript /tmp/session.jsonl
|
|
24964
|
+
|
|
24965
|
+
${chalk22.bold("Category:")}
|
|
24966
|
+
${chalk22.bold("cli")} Feedback about the CLI itself (default)
|
|
24967
|
+
${chalk22.bold("helix")} Feedback about Helix
|
|
24968
|
+
${chalk22.bold("stage:<x>")} Feedback about a lifecycle stage: ${VALID_STAGES.join(", ")}
|
|
24969
|
+
|
|
24970
|
+
${chalk22.bold("Transcript (--attach-transcript):")}
|
|
24929
24971
|
Uploads the last 200 KB of a coding-agent session transcript, separately from the
|
|
24930
24972
|
feedback text. Without a path it picks the newest session from Claude Code, Codex
|
|
24931
24973
|
or omp; a path picks that file.
|
|
24932
24974
|
|
|
24933
|
-
${
|
|
24934
|
-
${
|
|
24935
|
-
${
|
|
24975
|
+
${chalk22.yellow("A session transcript contains source code, absolute paths (including your")}
|
|
24976
|
+
${chalk22.yellow("username), branch and repository names, internal hostnames, and the business")}
|
|
24977
|
+
${chalk22.yellow("context of your prompts.")} Credentials are scanned for and redacted before
|
|
24936
24978
|
upload, and the exact size and source path are printed before anything is sent.
|
|
24937
24979
|
Detection is best-effort: omit the flag if the session handled secrets.
|
|
24938
24980
|
|
|
@@ -25015,15 +25057,15 @@ Or with a key: export MUTAGENT_API_KEY=<key>, then: mutagent login --json`);
|
|
|
25015
25057
|
init_output();
|
|
25016
25058
|
init_errors();
|
|
25017
25059
|
import { Command as Command12 } from "commander";
|
|
25018
|
-
import
|
|
25060
|
+
import chalk23 from "chalk";
|
|
25019
25061
|
function createInstallCommand(deps) {
|
|
25020
25062
|
const install = new Command12("install").description("Install the standalone Helix binary on this machine").argument("<package>", `Package to install: ${VALID_PACKAGES.join(", ")}`).option("--channel <channel>", `Release channel: ${HELIX_CHANNELS.join(" or ")} (default: latest)`).addHelpText("after", `
|
|
25021
|
-
${
|
|
25022
|
-
${
|
|
25023
|
-
${
|
|
25024
|
-
${
|
|
25063
|
+
${chalk23.bold("Examples:")}
|
|
25064
|
+
${chalk23.dim("$")} mutagent install helix
|
|
25065
|
+
${chalk23.dim("$")} mutagent install helix --channel candidate
|
|
25066
|
+
${chalk23.dim("$")} mutagent install helix --json
|
|
25025
25067
|
|
|
25026
|
-
${
|
|
25068
|
+
${chalk23.bold("helix")}: the standalone Helix binary, the same one
|
|
25027
25069
|
\`curl -fsSL https://install.mutagent.io/helix | bash\` installs. It downloads
|
|
25028
25070
|
helix-<os>-<arch> for macOS or Linux (x64, arm64), verifies it against
|
|
25029
25071
|
checksums.txt from the same origin, writes ~/.mutagent/bin/helix and points the
|
|
@@ -25034,7 +25076,7 @@ Shell rc files are never changed: when the directory is not on PATH, the line to
|
|
|
25034
25076
|
add is printed. This installs Helix on this machine; mutagent helix runs it in
|
|
25035
25077
|
the cloud.
|
|
25036
25078
|
|
|
25037
|
-
${
|
|
25079
|
+
${chalk23.bold("Environment:")}
|
|
25038
25080
|
MUTAGENT_HELIX_CHANNEL latest or candidate; --channel wins
|
|
25039
25081
|
MUTAGENT_INSTALL_HOST install host (default: https://install.mutagent.io)
|
|
25040
25082
|
MUTAGENT_INSTALL_DIR install directory (default: ~/.mutagent/bin)
|
|
@@ -25052,7 +25094,7 @@ AI Agent Directive:
|
|
|
25052
25094
|
try {
|
|
25053
25095
|
assertInstallTarget(pkg);
|
|
25054
25096
|
if (!isJson)
|
|
25055
|
-
console.log(
|
|
25097
|
+
console.log(chalk23.dim(`Downloading and verifying ${pkg}…`));
|
|
25056
25098
|
const result = await installPackage(pkg, { channel: options.channel }, deps);
|
|
25057
25099
|
if (isJson) {
|
|
25058
25100
|
output.output({
|
|
@@ -25075,15 +25117,15 @@ AI Agent Directive:
|
|
|
25075
25117
|
return;
|
|
25076
25118
|
}
|
|
25077
25119
|
output.success(`Installed helix ${result.version} (${result.channel}) → ${result.binaryPath}`);
|
|
25078
|
-
console.log(
|
|
25120
|
+
console.log(chalk23.dim(` sha256 ${result.sha256}`));
|
|
25079
25121
|
if (result.aliasPath !== undefined) {
|
|
25080
|
-
console.log(
|
|
25122
|
+
console.log(chalk23.dim(` alias ${result.aliasPath}`));
|
|
25081
25123
|
}
|
|
25082
25124
|
if (result.pathLine !== undefined) {
|
|
25083
|
-
console.log(`${
|
|
25084
|
-
console.log(` ${
|
|
25125
|
+
console.log(`${chalk23.yellow("⚠")} The install directory is not on your PATH. Add this line to your shell profile:`);
|
|
25126
|
+
console.log(` ${chalk23.cyan(result.pathLine)}`);
|
|
25085
25127
|
}
|
|
25086
|
-
console.log(`${
|
|
25128
|
+
console.log(`${chalk23.blue("→")} Next: ${result.nextStep}`);
|
|
25087
25129
|
} catch (error3) {
|
|
25088
25130
|
handleError(error3, isJson);
|
|
25089
25131
|
}
|
|
@@ -26412,8 +26454,9 @@ async function exchangeToken(input2, deps = {}) {
|
|
|
26412
26454
|
if (response.status === 401)
|
|
26413
26455
|
throw deadKeyError();
|
|
26414
26456
|
if (response.status === 403) {
|
|
26415
|
-
const
|
|
26416
|
-
|
|
26457
|
+
const context = { ...input2.tenancy, workspaceId: input2.workspaceId };
|
|
26458
|
+
const body = await response.text().catch(() => "");
|
|
26459
|
+
throw tenancyFailure(403, body, context) ?? workspaceDenied(context);
|
|
26417
26460
|
}
|
|
26418
26461
|
if (!response.ok) {
|
|
26419
26462
|
const detail = scrubKnown(messageFrom(await response.text().catch(() => "")));
|
|
@@ -26500,7 +26543,18 @@ async function resolveConnection() {
|
|
|
26500
26543
|
workspaceOrigin: tenancy.workspaceOrigin,
|
|
26501
26544
|
organizationId: tenancy.organization?.id
|
|
26502
26545
|
});
|
|
26503
|
-
return {
|
|
26546
|
+
return {
|
|
26547
|
+
endpoint: tenancy.endpoint,
|
|
26548
|
+
apiKey,
|
|
26549
|
+
workspaceId,
|
|
26550
|
+
headers,
|
|
26551
|
+
tenancy: {
|
|
26552
|
+
keyScope: tenancy.keyScope,
|
|
26553
|
+
workspaceName: tenancy.workspaceName,
|
|
26554
|
+
workspaceOrigin: tenancy.workspaceOrigin,
|
|
26555
|
+
organizationName: tenancy.organization?.name
|
|
26556
|
+
}
|
|
26557
|
+
};
|
|
26504
26558
|
}
|
|
26505
26559
|
function requireWorkspace(workspaceId) {
|
|
26506
26560
|
if (workspaceId === undefined || workspaceId.trim() === "") {
|
|
@@ -26525,7 +26579,12 @@ async function sandboxFetch(path, init, deps = {}) {
|
|
|
26525
26579
|
try {
|
|
26526
26580
|
const response = await fetchWithTokenRetry(`${endpoint}${path}`, init, { ...connection.headers, ...toHeaderRecord(init.headers) }, {
|
|
26527
26581
|
doFetch: fetch,
|
|
26528
|
-
authorization: async (forceRefresh) => `Bearer ${await getOperatorToken({
|
|
26582
|
+
authorization: async (forceRefresh) => `Bearer ${await getOperatorToken({
|
|
26583
|
+
endpoint,
|
|
26584
|
+
apiKey: connection.apiKey,
|
|
26585
|
+
workspaceId: connection.workspaceId,
|
|
26586
|
+
...connection.tenancy === undefined ? {} : { tenancy: connection.tenancy }
|
|
26587
|
+
}, { forceRefresh }, deps)}`,
|
|
26529
26588
|
onTokenRejected: () => {
|
|
26530
26589
|
clearCachedToken(deps);
|
|
26531
26590
|
}
|
|
@@ -27896,7 +27955,7 @@ function planLauncherArgv(argv, deps = defaultPlanDeps()) {
|
|
|
27896
27955
|
init_output();
|
|
27897
27956
|
init_errors();
|
|
27898
27957
|
import { Command as Command14, Option as Option4 } from "commander";
|
|
27899
|
-
import
|
|
27958
|
+
import chalk30 from "chalk";
|
|
27900
27959
|
|
|
27901
27960
|
// src/lib/sandbox-checkpoints.ts
|
|
27902
27961
|
async function captureCheckpoint(id, sessionId) {
|
|
@@ -27908,7 +27967,7 @@ async function captureCheckpoint(id, sessionId) {
|
|
|
27908
27967
|
}
|
|
27909
27968
|
|
|
27910
27969
|
// src/lib/sandbox-session.ts
|
|
27911
|
-
import
|
|
27970
|
+
import chalk25 from "chalk";
|
|
27912
27971
|
|
|
27913
27972
|
// src/lib/tty.ts
|
|
27914
27973
|
function isPlainOutput() {
|
|
@@ -27929,7 +27988,7 @@ init_errors();
|
|
|
27929
27988
|
init_known_secrets();
|
|
27930
27989
|
|
|
27931
27990
|
// src/lib/sandbox-frames.ts
|
|
27932
|
-
import
|
|
27991
|
+
import chalk24 from "chalk";
|
|
27933
27992
|
var SILENT2 = new Set([
|
|
27934
27993
|
"message_start",
|
|
27935
27994
|
"message_update",
|
|
@@ -28021,7 +28080,7 @@ class FrameFeed {
|
|
|
28021
28080
|
const arg = started?.arg ?? identifyingArg(frame.toolName, frame.args);
|
|
28022
28081
|
const failed = isFailure(frame.result);
|
|
28023
28082
|
const elapsed = started === undefined ? "" : formatDuration(this.#now() - started.startedAt);
|
|
28024
|
-
const name = this.#plain ? toolName : failed ?
|
|
28083
|
+
const name = this.#plain ? toolName : failed ? chalk24.red(toolName) : chalk24.cyan(toolName);
|
|
28025
28084
|
const visible = arg === "" ? toolName.padEnd(TOOL_COL) : `${toolName.padEnd(TOOL_COL)} ${arg}`;
|
|
28026
28085
|
const head = arg === "" ? pad(name, toolName, TOOL_COL) : `${pad(name, toolName, TOOL_COL)} ${arg}`;
|
|
28027
28086
|
const gap = " ".repeat(Math.max(2, DURATION_COL - visible.length));
|
|
@@ -28038,7 +28097,7 @@ class FrameFeed {
|
|
|
28038
28097
|
const method = typeof frame.method === "string" ? frame.method : "request";
|
|
28039
28098
|
const key = typeof frame.statusKey === "string" ? ` ${frame.statusKey}` : "";
|
|
28040
28099
|
const body = `hitl ${method}${key}`;
|
|
28041
|
-
return this.#line(this.#sym("◆", "?"), this.#plain ? body :
|
|
28100
|
+
return this.#line(this.#sym("◆", "?"), this.#plain ? body : chalk24.yellow(body));
|
|
28042
28101
|
}
|
|
28043
28102
|
#response(frame) {
|
|
28044
28103
|
const command = typeof frame.command === "string" ? frame.command : "command";
|
|
@@ -28047,7 +28106,7 @@ class FrameFeed {
|
|
|
28047
28106
|
const body = `${command}${id} ${ok ? "accepted" : "rejected"}`;
|
|
28048
28107
|
if (this.#plain)
|
|
28049
28108
|
return this.#line(ok ? "+" : "x", body);
|
|
28050
|
-
return this.#line(ok ? "✓" : "✗", ok ?
|
|
28109
|
+
return this.#line(ok ? "✓" : "✗", ok ? chalk24.green(body) : chalk24.red(body));
|
|
28051
28110
|
}
|
|
28052
28111
|
#line(symbol3, body) {
|
|
28053
28112
|
return ` ${symbol3} ${body}`;
|
|
@@ -28056,7 +28115,7 @@ class FrameFeed {
|
|
|
28056
28115
|
return this.#plain ? plain : styled;
|
|
28057
28116
|
}
|
|
28058
28117
|
#dim(text) {
|
|
28059
|
-
return this.#plain ? text :
|
|
28118
|
+
return this.#plain ? text : chalk24.dim(text);
|
|
28060
28119
|
}
|
|
28061
28120
|
#rule(label) {
|
|
28062
28121
|
const dash = this.#plain ? "-" : "─";
|
|
@@ -28146,7 +28205,7 @@ function formatDuration(ms) {
|
|
|
28146
28205
|
|
|
28147
28206
|
// src/lib/sandbox-session.ts
|
|
28148
28207
|
function dim(text) {
|
|
28149
|
-
return isPlainOutput() ? text :
|
|
28208
|
+
return isPlainOutput() ? text : chalk25.dim(text);
|
|
28150
28209
|
}
|
|
28151
28210
|
function reattachHint(id, lastSeq) {
|
|
28152
28211
|
const since = lastSeq > 0 ? ` --since ${String(lastSeq)}` : "";
|
|
@@ -28310,17 +28369,48 @@ function parseSince(raw) {
|
|
|
28310
28369
|
return value2;
|
|
28311
28370
|
}
|
|
28312
28371
|
|
|
28372
|
+
// src/lib/helix-session-gone.ts
|
|
28373
|
+
init_errors();
|
|
28374
|
+
var GONE_STATUSES = new Set([404, 410]);
|
|
28375
|
+
var CONSEQUENCE = {
|
|
28376
|
+
checkpoints: "its checkpoints can't be listed or restored from here",
|
|
28377
|
+
restore: "it can't be restored from here",
|
|
28378
|
+
stream: "it can't be attached to",
|
|
28379
|
+
input: "it can't take input"
|
|
28380
|
+
};
|
|
28381
|
+
var NEW_SESSION_COMMANDS = ['mutagent helix -p "<task>"', "mutagent helix --mode rpc"];
|
|
28382
|
+
|
|
28383
|
+
class SessionSandboxGoneError extends MutagentError {
|
|
28384
|
+
serverMessage;
|
|
28385
|
+
constructor(code, reference, route, serverMessage) {
|
|
28386
|
+
super(code, `The sandbox of session ${reference} was deleted, so ${CONSEQUENCE[route]}.`, `Start a new session: ${NEW_SESSION_COMMANDS[0]} or ${NEW_SESSION_COMMANDS[1]}`);
|
|
28387
|
+
this.serverMessage = serverMessage;
|
|
28388
|
+
this.name = "SessionSandboxGoneError";
|
|
28389
|
+
}
|
|
28390
|
+
toJSON() {
|
|
28391
|
+
return {
|
|
28392
|
+
...super.toJSON(),
|
|
28393
|
+
_agentGuidance: { fix: [...NEW_SESSION_COMMANDS], notes: [`The server answered: ${this.serverMessage}`] }
|
|
28394
|
+
};
|
|
28395
|
+
}
|
|
28396
|
+
}
|
|
28397
|
+
function sessionGoneGuidance(error3, route, reference) {
|
|
28398
|
+
if (!(error3 instanceof ApiError) || !GONE_STATUSES.has(error3.statusCode))
|
|
28399
|
+
return error3;
|
|
28400
|
+
return new SessionSandboxGoneError(error3.code, reference, route, error3.message);
|
|
28401
|
+
}
|
|
28402
|
+
|
|
28313
28403
|
// src/commands/helix/restore-command.ts
|
|
28314
28404
|
init_output();
|
|
28315
28405
|
init_errors();
|
|
28316
|
-
import
|
|
28406
|
+
import chalk26 from "chalk";
|
|
28317
28407
|
var DRIFT_MODES = ["warn", "refuse", "skip"];
|
|
28318
28408
|
function registerRestore(session, root) {
|
|
28319
28409
|
session.command("restore").description("Continue a session from a checkpoint in a rebuilt sandbox").argument("<reference>", "Session reference (hs1_...) from 'mutagent helix' or 'session list'; the session may be stopped").option("--snapshot <id>", "Checkpoint to use, from 'session checkpoints' (default: the newest complete one from this session's sandbox)").option("--on-drift <mode>", `If files the conversation names are missing: ${DRIFT_MODES.join(" | ")} (default: warn)`).option("--partial", "Also restore turns saved after the checkpoint (may end mid tool call)").addHelpText("after", `
|
|
28320
28410
|
Examples:
|
|
28321
|
-
${
|
|
28322
|
-
${
|
|
28323
|
-
${
|
|
28411
|
+
${chalk26.dim("$")} mutagent helix session restore <reference>
|
|
28412
|
+
${chalk26.dim("$")} mutagent helix session restore <reference> --snapshot snap_1
|
|
28413
|
+
${chalk26.dim("$")} mutagent helix session restore <reference> --on-drift refuse --json
|
|
28324
28414
|
|
|
28325
28415
|
Rebuilds the sandbox (the old one may be stopped or gone), restores the workspace
|
|
28326
28416
|
and settings where the checkpoint has them, and starts a new session that
|
|
@@ -28372,23 +28462,24 @@ AI Agent Directive:
|
|
|
28372
28462
|
return;
|
|
28373
28463
|
}
|
|
28374
28464
|
output.success(`Sandbox ${result.sandboxId} rebuilt at generation ${String(result.generation)} from snapshot ${result.snapshotId}`);
|
|
28375
|
-
console.error(
|
|
28465
|
+
console.error(chalk26.dim(` New session ${result.reference} · stream continues at seq ${String(result.seq)}`));
|
|
28376
28466
|
if (result.workspace !== null) {
|
|
28377
|
-
console.error(
|
|
28467
|
+
console.error(chalk26.dim(` Workspace: ${String(result.workspace.files)} files into ${result.cwd ?? "the default cwd"}`));
|
|
28378
28468
|
}
|
|
28379
28469
|
if (result.settingsReplayed.length > 0) {
|
|
28380
|
-
console.error(
|
|
28470
|
+
console.error(chalk26.dim(` Replayed: ${result.settingsReplayed.join(", ")}`));
|
|
28381
28471
|
}
|
|
28382
28472
|
if (result.partial) {
|
|
28383
|
-
console.error(
|
|
28473
|
+
console.error(chalk26.dim(` Partial: ${String(result.partialBytes)} bytes beyond the checkpoint`));
|
|
28384
28474
|
}
|
|
28385
28475
|
for (const skipped of result.skippedSnapshots) {
|
|
28386
|
-
console.error(
|
|
28476
|
+
console.error(chalk26.dim(` skipped ${skipped.id}: ${skipped.reason}`));
|
|
28387
28477
|
}
|
|
28388
28478
|
for (const gap of result.notRestored)
|
|
28389
|
-
console.error(
|
|
28479
|
+
console.error(chalk26.yellow(` ! ${gap}`));
|
|
28390
28480
|
} catch (error3) {
|
|
28391
|
-
|
|
28481
|
+
const named = (options.snapshot?.trim() ?? "") !== "";
|
|
28482
|
+
handleError(named ? error3 : sessionGoneGuidance(error3, "restore", reference), isJson);
|
|
28392
28483
|
}
|
|
28393
28484
|
});
|
|
28394
28485
|
}
|
|
@@ -28403,12 +28494,12 @@ function parseDriftMode(raw) {
|
|
|
28403
28494
|
// src/commands/helix/reference-commands.ts
|
|
28404
28495
|
init_output();
|
|
28405
28496
|
init_errors();
|
|
28406
|
-
import
|
|
28497
|
+
import chalk27 from "chalk";
|
|
28407
28498
|
function registerCheckpoints(session, root) {
|
|
28408
28499
|
session.command("checkpoints").description("List the checkpoints of the sandbox a session runs in").argument("<reference>", "Session reference (hs1_...) from 'mutagent helix' or 'session list'").addHelpText("after", `
|
|
28409
28500
|
Examples:
|
|
28410
|
-
${
|
|
28411
|
-
${
|
|
28501
|
+
${chalk27.dim("$")} mutagent helix session checkpoints <reference>
|
|
28502
|
+
${chalk27.dim("$")} mutagent helix session checkpoints <reference> --json
|
|
28412
28503
|
|
|
28413
28504
|
Newest first, without the stored bytes. The list covers every session the
|
|
28414
28505
|
sandbox has run, so SESSION names each checkpoint's session. MESSAGES is how
|
|
@@ -28428,7 +28519,7 @@ AI Agent Directive:
|
|
|
28428
28519
|
return;
|
|
28429
28520
|
}
|
|
28430
28521
|
if (snapshots.length === 0) {
|
|
28431
|
-
console.log(
|
|
28522
|
+
console.log(chalk27.gray("No checkpoints captured from this session's sandbox."));
|
|
28432
28523
|
console.log("");
|
|
28433
28524
|
console.log(` Capture one: mutagent helix session checkpoint ${reference}`);
|
|
28434
28525
|
return;
|
|
@@ -28441,15 +28532,15 @@ AI Agent Directive:
|
|
|
28441
28532
|
captured: new Date(snapshot.capturedAt).toLocaleString()
|
|
28442
28533
|
})));
|
|
28443
28534
|
} catch (error3) {
|
|
28444
|
-
handleError(error3, isJson);
|
|
28535
|
+
handleError(sessionGoneGuidance(error3, "checkpoints", reference), isJson);
|
|
28445
28536
|
}
|
|
28446
28537
|
});
|
|
28447
28538
|
}
|
|
28448
28539
|
function registerCloseInput(session, root) {
|
|
28449
28540
|
session.command("close-input").description("Close a session's input (end of stdin)").argument("<reference>", "Session reference (hs1_...) from 'mutagent helix' or 'session list'").addHelpText("after", `
|
|
28450
28541
|
Examples:
|
|
28451
|
-
${
|
|
28452
|
-
${
|
|
28542
|
+
${chalk27.dim("$")} mutagent helix session close-input <reference>
|
|
28543
|
+
${chalk27.dim("$")} mutagent helix session close-input <reference> --json
|
|
28453
28544
|
|
|
28454
28545
|
Sends end-of-input to the session, as closing stdin does on 'mutagent helix --mode rpc'.
|
|
28455
28546
|
An interactive session finishes its current work and ends; later 'session send' is
|
|
@@ -28492,7 +28583,7 @@ function planSessionStartArgs(argv, deps) {
|
|
|
28492
28583
|
init_output();
|
|
28493
28584
|
init_errors();
|
|
28494
28585
|
import { Option as Option2 } from "commander";
|
|
28495
|
-
import
|
|
28586
|
+
import chalk28 from "chalk";
|
|
28496
28587
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
28497
28588
|
var COMMAND_TYPES = ["prompt", "steer", "follow_up", "abort"];
|
|
28498
28589
|
var NEEDS_MESSAGE = new Set(["prompt", "steer", "follow_up"]);
|
|
@@ -28500,11 +28591,11 @@ function registerSendCommand(parent, registration) {
|
|
|
28500
28591
|
const jsonSource = registration?.jsonSource ?? parent;
|
|
28501
28592
|
parent.command("send").description("Send a prompt or command to a session").argument("<reference>", "Session reference (hs1_...)").argument("[message...]", "What to say to the agent").addOption(new Option2("--session <id>", "The session id, when the first argument is a sandbox id").hideHelp()).option("--type <type>", `${COMMAND_TYPES.join(" | ")} (default: prompt)`).option("--line <json>", "Send this exact JSON command instead of building one").option("--message-id <id>", "Use this command id instead of a generated one").addHelpText("after", `
|
|
28502
28593
|
Examples:
|
|
28503
|
-
${
|
|
28504
|
-
${
|
|
28505
|
-
${
|
|
28506
|
-
${
|
|
28507
|
-
${
|
|
28594
|
+
${chalk28.dim("$")} mutagent helix session send <reference> "also check the refresh path"
|
|
28595
|
+
${chalk28.dim("$")} mutagent helix session send <reference> --type steer "stop and re-read the spec"
|
|
28596
|
+
${chalk28.dim("$")} mutagent helix session send <reference> --type abort
|
|
28597
|
+
${chalk28.dim("$")} mutagent helix session send <reference> --line '{"type":"prompt","id":"p7","message":"go"}'
|
|
28598
|
+
${chalk28.dim("$")} mutagent helix session send <reference> "run the tests" --json
|
|
28508
28599
|
|
|
28509
28600
|
Types:
|
|
28510
28601
|
prompt A new instruction to an agent that has finished its turn
|
|
@@ -28523,7 +28614,7 @@ reference reach the woken session. 'mutagent helix session restore <reference>'
|
|
|
28523
28614
|
manual option; it continues the session in a new sandbox and prints the new reference.
|
|
28524
28615
|
Send does not wait for the reply. The reply arrives on the session's stream as a
|
|
28525
28616
|
'response' event carrying the command id (in --json output). Watch it with:
|
|
28526
|
-
${
|
|
28617
|
+
${chalk28.dim("$")} mutagent helix session attach <reference>
|
|
28527
28618
|
|
|
28528
28619
|
AI Agent Directive:
|
|
28529
28620
|
--json returns ONE object: { success, reference, type, id, line, accepted,
|
|
@@ -28571,10 +28662,10 @@ AI Agent Directive:
|
|
|
28571
28662
|
return;
|
|
28572
28663
|
}
|
|
28573
28664
|
output.success(`Sent ${built.type} to session ${sessionId}`);
|
|
28574
|
-
console.error(
|
|
28575
|
-
console.error(
|
|
28665
|
+
console.error(chalk28.dim(` ${built.line}`));
|
|
28666
|
+
console.error(chalk28.dim(` The reply arrives on the stream, not here: mutagent sandbox attach ${id}`));
|
|
28576
28667
|
} catch (error3) {
|
|
28577
|
-
handleError(error3, isJson);
|
|
28668
|
+
handleError(options.session === undefined ? sessionGoneGuidance(error3, "input", id) : error3, isJson);
|
|
28578
28669
|
}
|
|
28579
28670
|
});
|
|
28580
28671
|
}
|
|
@@ -28637,16 +28728,16 @@ function readType(raw) {
|
|
|
28637
28728
|
init_output();
|
|
28638
28729
|
init_errors();
|
|
28639
28730
|
import { Option as Option3 } from "commander";
|
|
28640
|
-
import
|
|
28731
|
+
import chalk29 from "chalk";
|
|
28641
28732
|
var SIGNAL_TYPES = ["SIGINT", "SIGTERM"];
|
|
28642
28733
|
var DEFAULT_SIGNAL = "SIGINT";
|
|
28643
28734
|
function registerSignalCommand(parent, registration) {
|
|
28644
28735
|
const jsonSource = registration?.jsonSource ?? parent;
|
|
28645
28736
|
parent.command("signal").description("Stop a session with SIGINT or SIGTERM; its sandbox stays up").argument("<reference>", "Session reference (hs1_...)").addOption(new Option3("--session <id>", "The session id, when the argument is a sandbox id").hideHelp()).option("--type <signal>", `${SIGNAL_TYPES.join(" | ")} (default: ${DEFAULT_SIGNAL})`).option("-f, --force", "Confirm the stop (required in every mode, --json included)").addHelpText("after", `
|
|
28646
28737
|
Examples:
|
|
28647
|
-
${
|
|
28648
|
-
${
|
|
28649
|
-
${
|
|
28738
|
+
${chalk29.dim("$")} mutagent helix session signal <reference> --force
|
|
28739
|
+
${chalk29.dim("$")} mutagent helix session signal <reference> --type SIGTERM --force
|
|
28740
|
+
${chalk29.dim("$")} mutagent helix session signal <reference> --force --json
|
|
28650
28741
|
|
|
28651
28742
|
SIGINT (the signal Ctrl-C sends) and SIGTERM both stop the session's Helix process.
|
|
28652
28743
|
SIGKILL is not supported.
|
|
@@ -28715,8 +28806,8 @@ AI Agent Directive:
|
|
|
28715
28806
|
return;
|
|
28716
28807
|
}
|
|
28717
28808
|
output.success(`Sent ${signal} to session ${sessionId}`);
|
|
28718
|
-
console.error(
|
|
28719
|
-
console.error(
|
|
28809
|
+
console.error(chalk29.dim(` The sandbox is still up: mutagent sandbox attach ${id}`));
|
|
28810
|
+
console.error(chalk29.dim(` Destroy it with: mutagent sandbox delete ${id} --force`));
|
|
28720
28811
|
} catch (error3) {
|
|
28721
28812
|
handleError(error3, isJson);
|
|
28722
28813
|
}
|
|
@@ -28736,11 +28827,11 @@ function resolveSignal(raw) {
|
|
|
28736
28827
|
function registerSessionCommand(parent) {
|
|
28737
28828
|
const session = new Command14("session").description("List, watch and control Helix sessions").addHelpText("after", `
|
|
28738
28829
|
Examples:
|
|
28739
|
-
${
|
|
28740
|
-
${
|
|
28741
|
-
${
|
|
28742
|
-
${
|
|
28743
|
-
${
|
|
28830
|
+
${chalk30.dim("$")} mutagent helix session list
|
|
28831
|
+
${chalk30.dim("$")} mutagent helix session attach <reference>
|
|
28832
|
+
${chalk30.dim("$")} mutagent helix session send <reference> "and now the tests"
|
|
28833
|
+
${chalk30.dim("$")} mutagent helix session signal <reference> --force
|
|
28834
|
+
${chalk30.dim("$")} mutagent helix session checkpoint <reference>
|
|
28744
28835
|
|
|
28745
28836
|
A session reference (hs1_...) is printed when a run starts and listed by 'session list'.
|
|
28746
28837
|
attach, send, signal, close-input, checkpoint, checkpoints and restore take it.
|
|
@@ -28779,10 +28870,10 @@ function withSessionFlags(options, own) {
|
|
|
28779
28870
|
function registerStart(session, root) {
|
|
28780
28871
|
session.command("start", { hidden: true }).description("Start a Helix session in an existing sandbox, by sandbox id").argument("<sandbox-id>", "Sandbox to start the session in").argument("[args...]", "Helix flags (put -- before them)").allowUnknownOption(true).allowExcessArguments(true).option("--rpc", "Start an interactive session that accepts 'session send' (default: headless, runs once and ends)").option("--cwd <path>", "Working directory (default: $HOME for an interactive session)").option("--env <name>", "Workspace Environment to load (see mutagent env list)").addHelpText("after", `
|
|
28781
28872
|
Examples:
|
|
28782
|
-
${
|
|
28783
|
-
${
|
|
28784
|
-
${
|
|
28785
|
-
${
|
|
28873
|
+
${chalk30.dim("$")} mutagent helix session start sbx_123 --rpc
|
|
28874
|
+
${chalk30.dim("$")} mutagent helix session start sbx_123 --rpc --env staging
|
|
28875
|
+
${chalk30.dim("$")} mutagent helix session start sbx_123 --rpc --json
|
|
28876
|
+
${chalk30.dim("$")} mutagent helix session start sbx_123 -- --model <provider/model> --thinking high
|
|
28786
28877
|
|
|
28787
28878
|
Prints the session id. Address the session as <sandbox-id> --session <session-id>
|
|
28788
28879
|
for send, signal and checkpoint, and watch it with 'mutagent sandbox attach <sandbox-id>'.
|
|
@@ -28835,9 +28926,9 @@ AI Agent Directive:
|
|
|
28835
28926
|
return;
|
|
28836
28927
|
}
|
|
28837
28928
|
output.success(`Session ${sessionId} started in ${id} (${mode})`);
|
|
28838
|
-
console.error(
|
|
28929
|
+
console.error(chalk30.dim(` Watch it: mutagent sandbox attach ${id}`));
|
|
28839
28930
|
if (mode === "interactive") {
|
|
28840
|
-
console.error(
|
|
28931
|
+
console.error(chalk30.dim(` Talk to it: mutagent helix session send ${id} --session ${sessionId} "<message>"`));
|
|
28841
28932
|
}
|
|
28842
28933
|
} catch (error3) {
|
|
28843
28934
|
handleError(error3, isJson);
|
|
@@ -28852,8 +28943,8 @@ function requireSessionId(result, sandboxId) {
|
|
|
28852
28943
|
function registerSessionList(session, root) {
|
|
28853
28944
|
session.command("list").alias("ls").description("List this workspace's Helix sessions").argument("[sandbox-id]", "List only the session ids in this sandbox").addHelpText("after", `
|
|
28854
28945
|
Examples:
|
|
28855
|
-
${
|
|
28856
|
-
${
|
|
28946
|
+
${chalk30.dim("$")} mutagent helix session list
|
|
28947
|
+
${chalk30.dim("$")} mutagent helix session list --json
|
|
28857
28948
|
|
|
28858
28949
|
Every session in the workspace, live and ended, newest activity first.
|
|
28859
28950
|
STATUS is live (running now), ended (finished; exitCode in --json), stopped-for-idling
|
|
@@ -28879,7 +28970,7 @@ AI Agent Directive:
|
|
|
28879
28970
|
return;
|
|
28880
28971
|
}
|
|
28881
28972
|
if (sessions2.length === 0) {
|
|
28882
|
-
console.log(
|
|
28973
|
+
console.log(chalk30.gray(`No sessions running in ${id}.`));
|
|
28883
28974
|
console.log("");
|
|
28884
28975
|
console.log(` Start one: mutagent helix session start ${id} --rpc`);
|
|
28885
28976
|
return;
|
|
@@ -28898,7 +28989,7 @@ AI Agent Directive:
|
|
|
28898
28989
|
return;
|
|
28899
28990
|
}
|
|
28900
28991
|
if (sessions.length === 0) {
|
|
28901
|
-
console.log(
|
|
28992
|
+
console.log(chalk30.gray("No Helix sessions in this workspace yet."));
|
|
28902
28993
|
console.log("");
|
|
28903
28994
|
console.log(' Start one: mutagent helix -p "<task>" or mutagent helix --rpc');
|
|
28904
28995
|
return;
|
|
@@ -28913,7 +29004,7 @@ AI Agent Directive:
|
|
|
28913
29004
|
"LAST ACTIVITY": s.lastActivityAt
|
|
28914
29005
|
})));
|
|
28915
29006
|
if (nextCursor !== undefined) {
|
|
28916
|
-
console.log(
|
|
29007
|
+
console.log(chalk30.gray("\nMore sessions — re-run with the cursor from --json `nextCursor`."));
|
|
28917
29008
|
}
|
|
28918
29009
|
} catch (error3) {
|
|
28919
29010
|
handleError(error3, isJson);
|
|
@@ -28943,15 +29034,15 @@ function registerSessionAttach(session) {
|
|
|
28943
29034
|
send: (line, signal) => sendHelixInput(reference, line, signal)
|
|
28944
29035
|
});
|
|
28945
29036
|
} catch (error3) {
|
|
28946
|
-
handleError(error3, false);
|
|
29037
|
+
handleError(sessionGoneGuidance(error3, "stream", reference), false);
|
|
28947
29038
|
}
|
|
28948
29039
|
});
|
|
28949
29040
|
}
|
|
28950
29041
|
function registerCheckpoint(session, root) {
|
|
28951
29042
|
session.command("checkpoint").description("Save a session's conversation as a checkpoint").argument("<reference>", "Session reference (hs1_...)").addOption(new Option4("--session <id>", "The session id, when the argument is a sandbox id").hideHelp()).addHelpText("after", `
|
|
28952
29043
|
Examples:
|
|
28953
|
-
${
|
|
28954
|
-
${
|
|
29044
|
+
${chalk30.dim("$")} mutagent helix session checkpoint <reference>
|
|
29045
|
+
${chalk30.dim("$")} mutagent helix session checkpoint <reference> --json
|
|
28955
29046
|
|
|
28956
29047
|
Saves Helix's own session file, and the workspace and settings where the
|
|
28957
29048
|
deployment supports it. notCaptured lists anything left out.
|
|
@@ -29000,7 +29091,7 @@ AI Agent Directive:
|
|
|
29000
29091
|
if (Array.isArray(result.notCaptured))
|
|
29001
29092
|
for (const reason of result.notCaptured)
|
|
29002
29093
|
output.warn("Not captured: " + reason);
|
|
29003
|
-
console.error(
|
|
29094
|
+
console.error(chalk30.dim(` ${String(result.messageCount)} messages, ${String(result.bytes)} bytes, from ${result.sourcePath}`));
|
|
29004
29095
|
} catch (error3) {
|
|
29005
29096
|
handleError(error3, isJson);
|
|
29006
29097
|
}
|
|
@@ -29016,10 +29107,10 @@ function requireSession(raw, example) {
|
|
|
29016
29107
|
// src/commands/helix/models.ts
|
|
29017
29108
|
init_output();
|
|
29018
29109
|
init_errors();
|
|
29019
|
-
import
|
|
29110
|
+
import chalk31 from "chalk";
|
|
29020
29111
|
function printView(view, output) {
|
|
29021
29112
|
if (view.models.length === 0) {
|
|
29022
|
-
console.log(
|
|
29113
|
+
console.log(chalk31.gray("No Helix Cloud models: this workspace has no active LLM provider that Helix can use."));
|
|
29023
29114
|
console.log("");
|
|
29024
29115
|
console.log(" Add one: mutagent providers add --provider <id> --name <name> --api-key <key>");
|
|
29025
29116
|
} else {
|
|
@@ -29029,19 +29120,19 @@ function printView(view, output) {
|
|
|
29029
29120
|
name: m.displayName
|
|
29030
29121
|
})));
|
|
29031
29122
|
console.log("");
|
|
29032
|
-
console.log(view.default === null ?
|
|
29123
|
+
console.log(view.default === null ? chalk31.yellow("No default set — a run without --model answers 428. Set one: mutagent helix models default <provider/model>") : `Default: ${view.default}`);
|
|
29033
29124
|
}
|
|
29034
29125
|
if (view.unmapped.length > 0) {
|
|
29035
|
-
console.log(
|
|
29126
|
+
console.log(chalk31.yellow(`Not usable by Helix Cloud (Helix cannot load this LLM provider's key): ${view.unmapped.join(", ")}`));
|
|
29036
29127
|
}
|
|
29037
29128
|
}
|
|
29038
29129
|
function registerModelsCommand(helix) {
|
|
29039
29130
|
const models = helix.command("models").description("List the models Helix can use in the cloud, and the workspace default model").addHelpText("after", `
|
|
29040
29131
|
Examples:
|
|
29041
|
-
${
|
|
29042
|
-
${
|
|
29043
|
-
${
|
|
29044
|
-
${
|
|
29132
|
+
${chalk31.dim("$")} mutagent helix models
|
|
29133
|
+
${chalk31.dim("$")} mutagent helix models --json
|
|
29134
|
+
${chalk31.dim("$")} mutagent helix models default zai-coding-cn/glm-5.2
|
|
29135
|
+
${chalk31.dim("$")} mutagent helix models default zai-coding-cn/glm-5.2 openai/gpt-5
|
|
29045
29136
|
|
|
29046
29137
|
Lists the models your workspace's active LLM providers ('mutagent providers') give
|
|
29047
29138
|
Helix in the cloud. Each id is provider/model: pass it as --model to 'mutagent helix'
|
|
@@ -29070,9 +29161,9 @@ AI Agent Directive:
|
|
|
29070
29161
|
});
|
|
29071
29162
|
models.command("default").description("Set the workspace default model for Helix in the cloud, and its fallbacks").argument("[models...]", "Model ids from 'mutagent helix models'; the first is the default").option("--clear", "Remove the default model and every fallback").addHelpText("after", `
|
|
29072
29163
|
Examples:
|
|
29073
|
-
${
|
|
29074
|
-
${
|
|
29075
|
-
${
|
|
29164
|
+
${chalk31.dim("$")} mutagent helix models default zai-coding-cn/glm-5.2
|
|
29165
|
+
${chalk31.dim("$")} mutagent helix models default zai-coding-cn/glm-5.2 openai/gpt-5
|
|
29166
|
+
${chalk31.dim("$")} mutagent helix models default --clear
|
|
29076
29167
|
|
|
29077
29168
|
Replaces the list. The first id is the default; later ids are used in order when
|
|
29078
29169
|
an earlier model's LLM provider has been turned off. Every id must appear in
|
|
@@ -29107,7 +29198,7 @@ AI Agent Directive:
|
|
|
29107
29198
|
init_output();
|
|
29108
29199
|
init_errors();
|
|
29109
29200
|
import { Option as Option5 } from "commander";
|
|
29110
|
-
import
|
|
29201
|
+
import chalk32 from "chalk";
|
|
29111
29202
|
|
|
29112
29203
|
// src/lib/sandbox-catalog.ts
|
|
29113
29204
|
async function listPresets() {
|
|
@@ -29143,8 +29234,8 @@ function registerDoctorCommand(parent, registration) {
|
|
|
29143
29234
|
const jsonSource = registration?.jsonSource ?? parent;
|
|
29144
29235
|
parent.command("doctor").description("Check the Helix build in the cloud image").addOption(new Option5("--sandbox <id>", "Run in an existing sandbox, by sandbox id").hideHelp()).option("--preset <name>", "Sandbox preset (not with --sandbox)").option("--strict", "Also launch Helix's embedded harness with --version and fail if it fails").option("--welcome", "Print the Helix welcome screen instead of the report").option("--refresh-runtime", "Refused: the cloud image has no Helix runtime to refresh").allowUnknownOption(true).addHelpText("after", `
|
|
29145
29236
|
Examples:
|
|
29146
|
-
${
|
|
29147
|
-
${
|
|
29237
|
+
${chalk32.dim("$")} mutagent helix doctor
|
|
29238
|
+
${chalk32.dim("$")} mutagent helix doctor --strict --json
|
|
29148
29239
|
|
|
29149
29240
|
Runs Helix's own diagnostics in a temporary sandbox that is removed afterwards,
|
|
29150
29241
|
and exits with Helix's exit code. It checks the cloud image, not your machine:
|
|
@@ -29180,8 +29271,8 @@ function registerSmokeCommand(parent, registration) {
|
|
|
29180
29271
|
const jsonSource = registration?.jsonSource ?? parent;
|
|
29181
29272
|
parent.command("smoke").description("Run Helix's smoke test in the cloud").addOption(new Option5("--sandbox <id>", "Run in an existing sandbox, by sandbox id").hideHelp()).option("--preset <name>", "Sandbox preset (not with --sandbox)").allowUnknownOption(true).addHelpText("after", `
|
|
29182
29273
|
Examples:
|
|
29183
|
-
${
|
|
29184
|
-
${
|
|
29274
|
+
${chalk32.dim("$")} mutagent helix smoke
|
|
29275
|
+
${chalk32.dim("$")} mutagent helix smoke --json
|
|
29185
29276
|
|
|
29186
29277
|
Runs one real model turn in a temporary sandbox that is removed afterwards, and
|
|
29187
29278
|
exits with Helix's exit code.
|
|
@@ -29225,8 +29316,8 @@ function registerVersionCommand(parent, registration) {
|
|
|
29225
29316
|
const jsonSource = registration?.jsonSource ?? parent;
|
|
29226
29317
|
parent.command("version").description("Show this CLI's version and the Helix version the cloud uses").addHelpText("after", `
|
|
29227
29318
|
Examples:
|
|
29228
|
-
${
|
|
29229
|
-
${
|
|
29319
|
+
${chalk32.dim("$")} mutagent helix version
|
|
29320
|
+
${chalk32.dim("$")} mutagent helix version --json
|
|
29230
29321
|
|
|
29231
29322
|
cli the mutagent CLI you are running
|
|
29232
29323
|
helix the Helix version the cloud image is released with, as the server reports it
|
|
@@ -29252,7 +29343,7 @@ async function reportVersions(isJson) {
|
|
|
29252
29343
|
return;
|
|
29253
29344
|
}
|
|
29254
29345
|
console.log(`cli ${cli}`);
|
|
29255
|
-
console.log(`helix ${helix ?? "unknown"} ${
|
|
29346
|
+
console.log(`helix ${helix ?? "unknown"} ${chalk32.dim("(pinned by the image, per the backend’s presets)")}`);
|
|
29256
29347
|
}
|
|
29257
29348
|
async function pinnedHelixVersion() {
|
|
29258
29349
|
const { presets, default: fallback } = await listPresets();
|
|
@@ -29364,12 +29455,12 @@ function createHelixCommand() {
|
|
|
29364
29455
|
|
|
29365
29456
|
// src/commands/sandbox/index.ts
|
|
29366
29457
|
import { Command as Command16 } from "commander";
|
|
29367
|
-
import
|
|
29458
|
+
import chalk39 from "chalk";
|
|
29368
29459
|
|
|
29369
29460
|
// src/commands/sandbox/spawn.ts
|
|
29370
29461
|
init_output();
|
|
29371
29462
|
init_errors();
|
|
29372
|
-
import
|
|
29463
|
+
import chalk33 from "chalk";
|
|
29373
29464
|
var ARCHES = ["x86_64", "arm64"];
|
|
29374
29465
|
var EGRESS_POLICIES = ["deny", "allowlist", "allow"];
|
|
29375
29466
|
var EGRESS_KINDS = ["port", "cidr", "domain"];
|
|
@@ -29377,10 +29468,10 @@ function registerSpawnCommand(parent, registration) {
|
|
|
29377
29468
|
const jsonSource = registration?.jsonSource ?? parent;
|
|
29378
29469
|
parent.command("spawn").description("Spawn a persistent sandbox from an image and attach to it").requiredOption("--image <ref>", "Image reference (repository:tag or @digest)").option("--arch <arch>", `Image architecture: ${ARCHES.join(" | ")} (default: this host's)`).option("--name <name>", "Definition name (default: derived from the image reference)").option("--provider <name>", "Sandbox provider (default: the server's; see sandbox providers)").option("--env <name>", "Workspace Environment to load (see mutagent env list)").option("--egress <policy>", `Outbound network: ${EGRESS_POLICIES.join(" | ")} (default: deny)`).option("--egress-allow <rule>", "domain:, port: or cidr: rule for --egress allowlist (repeatable)", collectRule, []).option("--detach", "Print the sandbox ID and return").addHelpText("after", `
|
|
29379
29470
|
Examples:
|
|
29380
|
-
${
|
|
29381
|
-
${
|
|
29382
|
-
${
|
|
29383
|
-
${
|
|
29471
|
+
${chalk33.dim("$")} mutagent sandbox spawn --image alpine:3.20
|
|
29472
|
+
${chalk33.dim("$")} mutagent sandbox spawn --image alpine:3.20 --detach --json
|
|
29473
|
+
${chalk33.dim("$")} mutagent sandbox spawn --image <helix-image> --egress allow
|
|
29474
|
+
${chalk33.dim("$")} mutagent sandbox spawn --image <ref> --egress allowlist --egress-allow domain:api.anthropic.com
|
|
29384
29475
|
|
|
29385
29476
|
--arch defaults to this machine's architecture; set it for an image built elsewhere.
|
|
29386
29477
|
Egress defaults to deny. On Docker the sandbox then runs with --network none, so a Helix
|
|
@@ -29517,10 +29608,10 @@ async function createSandbox(definition, isJson) {
|
|
|
29517
29608
|
const spinner = ora3(`Spawning ${definition.image} (${definition.arch})...`).start();
|
|
29518
29609
|
try {
|
|
29519
29610
|
const sandbox = await spawnSandbox(definition);
|
|
29520
|
-
spinner.succeed(
|
|
29611
|
+
spinner.succeed(chalk33.green(`Sandbox ${sandbox.id} spawned`));
|
|
29521
29612
|
return sandbox;
|
|
29522
29613
|
} catch (error3) {
|
|
29523
|
-
spinner.fail(
|
|
29614
|
+
spinner.fail(chalk33.red("Spawn failed"));
|
|
29524
29615
|
throw error3;
|
|
29525
29616
|
}
|
|
29526
29617
|
}
|
|
@@ -29557,18 +29648,18 @@ function reportDetached(sandbox, id, output, isJson) {
|
|
|
29557
29648
|
// src/commands/sandbox/exec.ts
|
|
29558
29649
|
init_output();
|
|
29559
29650
|
init_errors();
|
|
29560
|
-
import
|
|
29651
|
+
import chalk34 from "chalk";
|
|
29561
29652
|
function registerExecCommand(parent, registration) {
|
|
29562
29653
|
const jsonSource = registration?.jsonSource ?? parent;
|
|
29563
29654
|
parent.command("exec").description("Run a command in a sandbox — an existing one, or a fresh one").argument("<argv...>", "Command and arguments (argv, not a shell string)").option("--sandbox <id>", "Run in this existing sandbox instead of a fresh one").option("--preset <name>", "Preset for a fresh sandbox (not with --sandbox)").option("--keep", "Keep the fresh sandbox after the command (not with --sandbox)").option("--cwd <dir>", "Working directory inside the sandbox").option("--timeout-ms <n>", "Command timeout in milliseconds").option("--no-stream", "With --sandbox, wait for the full result instead of streaming").addHelpText("after", `
|
|
29564
29655
|
Examples:
|
|
29565
|
-
${
|
|
29566
|
-
${
|
|
29567
|
-
${
|
|
29568
|
-
${
|
|
29656
|
+
${chalk34.dim("$")} mutagent sandbox exec -- uname -m
|
|
29657
|
+
${chalk34.dim("$")} mutagent sandbox exec --json --preset <name> -- uname -m
|
|
29658
|
+
${chalk34.dim("$")} mutagent sandbox exec --sandbox sbx_123 --cwd /src -- git status
|
|
29659
|
+
${chalk34.dim("$")} mutagent sandbox exec -- sh -c 'ls | wc -l'
|
|
29569
29660
|
|
|
29570
29661
|
Put this command's flags, and --json, before the sandbox command; everything after it
|
|
29571
|
-
goes to the sandbox unchanged (${
|
|
29662
|
+
goes to the sandbox unchanged (${chalk34.bold("--")} is optional). The command is argv, not a shell
|
|
29572
29663
|
string: name a shell for pipes.
|
|
29573
29664
|
|
|
29574
29665
|
Without --sandbox, a fresh sandbox starts from a preset (see sandbox presets), runs the
|
|
@@ -29700,15 +29791,15 @@ function reportResult(result, output, isJson, context) {
|
|
|
29700
29791
|
// src/commands/sandbox/attach.ts
|
|
29701
29792
|
init_output();
|
|
29702
29793
|
init_errors();
|
|
29703
|
-
import
|
|
29794
|
+
import chalk35 from "chalk";
|
|
29704
29795
|
function registerAttachCommand(parent, registration) {
|
|
29705
29796
|
const jsonSource = registration?.jsonSource ?? parent;
|
|
29706
29797
|
parent.command("attach").description("Stream a running sandbox's output").argument("<id>", "Sandbox ID").option("--since <seq>", "Resume after this sequence number instead of from the start").addHelpText("after", `
|
|
29707
29798
|
Examples:
|
|
29708
|
-
${
|
|
29709
|
-
${
|
|
29710
|
-
${
|
|
29711
|
-
${
|
|
29799
|
+
${chalk35.dim("$")} mutagent sandbox attach sbx_123
|
|
29800
|
+
${chalk35.dim("$")} mutagent sandbox attach sbx_123 --since 412
|
|
29801
|
+
${chalk35.dim("$")} mutagent sandbox attach sbx_123 --json | tail -1
|
|
29802
|
+
${chalk35.dim("$")} mutagent sandbox attach sbx_123 > session.log
|
|
29712
29803
|
|
|
29713
29804
|
Ctrl-C detaches; the sandbox keeps running and the re-attach command, with the resume
|
|
29714
29805
|
point filled in, is printed to stderr. The sandbox runs until it is removed or stopped
|
|
@@ -29753,7 +29844,7 @@ AI Agent Directive:
|
|
|
29753
29844
|
}
|
|
29754
29845
|
|
|
29755
29846
|
// src/commands/sandbox/access.ts
|
|
29756
|
-
import
|
|
29847
|
+
import chalk36 from "chalk";
|
|
29757
29848
|
|
|
29758
29849
|
// src/lib/sandbox-access.ts
|
|
29759
29850
|
init_errors();
|
|
@@ -29783,8 +29874,8 @@ init_output();
|
|
|
29783
29874
|
function registerAccessCommand(parent) {
|
|
29784
29875
|
parent.command("access").description("Check whether this account can create cloud sandboxes").addHelpText("after", `
|
|
29785
29876
|
Examples:
|
|
29786
|
-
${
|
|
29787
|
-
${
|
|
29877
|
+
${chalk36.dim("$")} mutagent sandbox access
|
|
29878
|
+
${chalk36.dim("$")} mutagent sandbox access --json
|
|
29788
29879
|
|
|
29789
29880
|
Asks the server once (GET /api/sandbox/access) for the current workspace and the
|
|
29790
29881
|
signed-in account. It is a diagnostic: a launch needs no check first. Use it when
|
|
@@ -29825,13 +29916,13 @@ Requires a workspace: mutagent workspaces use <name> (or --workspace for one com
|
|
|
29825
29916
|
// src/commands/sandbox/providers.ts
|
|
29826
29917
|
init_output();
|
|
29827
29918
|
init_errors();
|
|
29828
|
-
import
|
|
29919
|
+
import chalk37 from "chalk";
|
|
29829
29920
|
function registerProvidersCommand(parent, registration) {
|
|
29830
29921
|
const jsonSource = registration?.jsonSource ?? parent;
|
|
29831
29922
|
parent.command("providers").description("List sandbox providers for mutagent helix --sandbox-provider (requires sign-in)").addHelpText("after", `
|
|
29832
29923
|
Examples:
|
|
29833
|
-
${
|
|
29834
|
-
${
|
|
29924
|
+
${chalk37.dim("$")} mutagent sandbox providers
|
|
29925
|
+
${chalk37.dim("$")} mutagent sandbox providers --json
|
|
29835
29926
|
|
|
29836
29927
|
A sandbox provider is where a sandbox runs (for example docker or mutagent-cloud). It is not an
|
|
29837
29928
|
LLM provider (\`mutagent providers\`) and not an Environment (\`mutagent env\`).
|
|
@@ -29854,7 +29945,7 @@ AI Agent Directive:
|
|
|
29854
29945
|
return;
|
|
29855
29946
|
}
|
|
29856
29947
|
if (list.names.length === 0) {
|
|
29857
|
-
console.log(
|
|
29948
|
+
console.log(chalk37.gray("No sandbox providers configured on this backend."));
|
|
29858
29949
|
return;
|
|
29859
29950
|
}
|
|
29860
29951
|
output.output(list.names.map((name) => ({ name, default: name === list.default ? "yes" : "" })));
|
|
@@ -29867,9 +29958,9 @@ function registerPreflightCommand(parent, registration) {
|
|
|
29867
29958
|
const jsonSource = registration?.jsonSource ?? parent;
|
|
29868
29959
|
parent.command("preflight").description("Check whether a sandbox provider can run a definition, without creating anything").requiredOption("--image <ref>", "Image reference (repository:tag or @digest)").option("--arch <arch>", "Image architecture: x86_64 | arm64 (default: this host's)").option("--name <name>", "Definition name (default: derived from the image reference)").option("--provider <name>", "Sandbox provider to check against (default: the server's)").option("--env <name>", "Workspace Environment the definition would load").option("--egress <policy>", "Outbound network: deny | allowlist | allow (default: deny)").option("--egress-allow <rule>", "domain:, port: or cidr: rule for --egress allowlist (repeatable)", (value2, previous) => [...previous, value2], []).addHelpText("after", `
|
|
29869
29960
|
Examples:
|
|
29870
|
-
${
|
|
29871
|
-
${
|
|
29872
|
-
${
|
|
29961
|
+
${chalk37.dim("$")} mutagent sandbox preflight --image alpine:3.20
|
|
29962
|
+
${chalk37.dim("$")} mutagent sandbox preflight --image alpine:3.20 --provider mutagent-cloud --json
|
|
29963
|
+
${chalk37.dim("$")} mutagent sandbox preflight --image <ref> --egress allowlist --egress-allow domain:api.anthropic.com
|
|
29873
29964
|
|
|
29874
29965
|
Takes the same flags as spawn and checks the definition spawn would send. Every
|
|
29875
29966
|
violation is listed. An incompatible definition exits 0 with compatible: false;
|
|
@@ -29898,7 +29989,7 @@ AI Agent Directive:
|
|
|
29898
29989
|
output.success(`${definition.name} is compatible with ${verdict.provider}`);
|
|
29899
29990
|
return;
|
|
29900
29991
|
}
|
|
29901
|
-
console.log(
|
|
29992
|
+
console.log(chalk37.yellow(`${definition.name} is NOT compatible with ${verdict.provider}:`));
|
|
29902
29993
|
for (const violation of verdict.violations)
|
|
29903
29994
|
console.log(` - ${violation}`);
|
|
29904
29995
|
} catch (error3) {
|
|
@@ -29910,13 +30001,13 @@ AI Agent Directive:
|
|
|
29910
30001
|
// src/commands/sandbox/inventory.ts
|
|
29911
30002
|
init_output();
|
|
29912
30003
|
init_errors();
|
|
29913
|
-
import
|
|
30004
|
+
import chalk38 from "chalk";
|
|
29914
30005
|
function registerListCommand(parent, registration) {
|
|
29915
30006
|
const jsonSource = registration?.jsonSource ?? parent;
|
|
29916
30007
|
parent.command("list").alias("ls").description("List the workspace's live sandboxes").addHelpText("after", `
|
|
29917
30008
|
Examples:
|
|
29918
|
-
${
|
|
29919
|
-
${
|
|
30009
|
+
${chalk38.dim("$")} mutagent sandbox list
|
|
30010
|
+
${chalk38.dim("$")} mutagent sandbox list --json
|
|
29920
30011
|
|
|
29921
30012
|
Lists the sandboxes in the configured workspace
|
|
29922
30013
|
(mutagent workspaces use <name>).
|
|
@@ -29938,7 +30029,7 @@ AI Agent Directive:
|
|
|
29938
30029
|
return;
|
|
29939
30030
|
}
|
|
29940
30031
|
if (sandboxes.length === 0) {
|
|
29941
|
-
console.log(
|
|
30032
|
+
console.log(chalk38.gray("No sandboxes running."));
|
|
29942
30033
|
console.log("");
|
|
29943
30034
|
console.log(" Start one: mutagent sandbox spawn --image <ref>");
|
|
29944
30035
|
return;
|
|
@@ -29963,8 +30054,8 @@ function registerPresetsCommand(parent, registration) {
|
|
|
29963
30054
|
const jsonSource = registration?.jsonSource ?? parent;
|
|
29964
30055
|
parent.command("presets").description("List presets for mutagent helix --preset (requires sign-in)").addHelpText("after", `
|
|
29965
30056
|
Examples:
|
|
29966
|
-
${
|
|
29967
|
-
${
|
|
30057
|
+
${chalk38.dim("$")} mutagent sandbox presets
|
|
30058
|
+
${chalk38.dim("$")} mutagent sandbox presets --json
|
|
29968
30059
|
|
|
29969
30060
|
A preset is a named sandbox definition kept on the server. \`mutagent helix --preset <name>\`
|
|
29970
30061
|
and \`mutagent sandbox exec --preset <name>\` use it. Image references are not shown.
|
|
@@ -29985,7 +30076,7 @@ AI Agent Directive:
|
|
|
29985
30076
|
return;
|
|
29986
30077
|
}
|
|
29987
30078
|
if (presets.length === 0) {
|
|
29988
|
-
console.log(
|
|
30079
|
+
console.log(chalk38.gray("No presets configured on this backend."));
|
|
29989
30080
|
console.log("");
|
|
29990
30081
|
console.log(" Spawn with an explicit image: mutagent sandbox spawn --image <ref>");
|
|
29991
30082
|
return;
|
|
@@ -30006,8 +30097,8 @@ function registerDeleteCommand2(parent, registration) {
|
|
|
30006
30097
|
const jsonSource = registration?.jsonSource ?? parent;
|
|
30007
30098
|
parent.command("delete").alias("rm").description("Destroy a sandbox now").argument("<id>", "Sandbox ID").option("-f, --force", "Confirm (required in every mode, --json included)").addHelpText("after", `
|
|
30008
30099
|
Examples:
|
|
30009
|
-
${
|
|
30010
|
-
${
|
|
30100
|
+
${chalk38.dim("$")} mutagent sandbox delete sbx_123 --force
|
|
30101
|
+
${chalk38.dim("$")} mutagent sandbox delete sbx_123 --force --json
|
|
30011
30102
|
|
|
30012
30103
|
Ends every session in the sandbox. The server first tries to capture a checkpoint,
|
|
30013
30104
|
so a Helix session can be rebuilt with \`mutagent helix session restore <reference>\`.
|
|
@@ -30050,8 +30141,8 @@ function registerTracesCommand(parent, registration) {
|
|
|
30050
30141
|
const jsonSource = registration?.jsonSource ?? parent;
|
|
30051
30142
|
parent.command("traces").description("Show the spans recorded for a sandbox").argument("<id>", "Sandbox ID").addHelpText("after", `
|
|
30052
30143
|
Examples:
|
|
30053
|
-
${
|
|
30054
|
-
${
|
|
30144
|
+
${chalk38.dim("$")} mutagent sandbox traces sbx_123
|
|
30145
|
+
${chalk38.dim("$")} mutagent sandbox traces sbx_123 --json
|
|
30055
30146
|
|
|
30056
30147
|
An empty list means no spans were recorded; telemetry must be configured on the
|
|
30057
30148
|
server for spans to exist.
|
|
@@ -30071,7 +30162,7 @@ AI Agent Directive:
|
|
|
30071
30162
|
return;
|
|
30072
30163
|
}
|
|
30073
30164
|
if (spans.length === 0) {
|
|
30074
|
-
console.log(
|
|
30165
|
+
console.log(chalk38.gray(`No spans captured for sandbox ${id}.`));
|
|
30075
30166
|
return;
|
|
30076
30167
|
}
|
|
30077
30168
|
output.output(spans.map((span) => {
|
|
@@ -30092,8 +30183,8 @@ function registerStatusCommand(parent, registration) {
|
|
|
30092
30183
|
const jsonSource = registration?.jsonSource ?? parent;
|
|
30093
30184
|
parent.command("status").description("Print one sandbox's state").argument("<id>", "Sandbox ID").addHelpText("after", `
|
|
30094
30185
|
Examples:
|
|
30095
|
-
${
|
|
30096
|
-
${
|
|
30186
|
+
${chalk38.dim("$")} mutagent sandbox status sbx_123
|
|
30187
|
+
${chalk38.dim("$")} mutagent sandbox status sbx_123 --json
|
|
30097
30188
|
|
|
30098
30189
|
States: pending, starting, running, paused, stopping, stopped, failed.
|
|
30099
30190
|
For sandbox provider, arch and creation time use \`mutagent sandbox list --json\`.
|
|
@@ -30122,29 +30213,29 @@ AI Agent Directive:
|
|
|
30122
30213
|
function createSandboxCommand() {
|
|
30123
30214
|
const sandbox = new Command16("sandbox").description("Cloud sandboxes (advanced): run a command in a box; agent runs use mutagent helix").addHelpText("after", `
|
|
30124
30215
|
Examples:
|
|
30125
|
-
${
|
|
30126
|
-
${
|
|
30127
|
-
${
|
|
30128
|
-
${
|
|
30129
|
-
${
|
|
30130
|
-
${
|
|
30131
|
-
${
|
|
30132
|
-
${
|
|
30133
|
-
${
|
|
30134
|
-
${
|
|
30135
|
-
${
|
|
30136
|
-
${
|
|
30137
|
-
${
|
|
30216
|
+
${chalk39.dim("$")} mutagent sandbox exec -- uname -m ${chalk39.dim("Run one shell command in a fresh cloud sandbox")}
|
|
30217
|
+
${chalk39.dim("$")} mutagent helix --sandbox-provider mutagent-cloud -p "run the tests" ${chalk39.dim("Run an agent task in a cloud sandbox")}
|
|
30218
|
+
${chalk39.dim("$")} mutagent sandbox list
|
|
30219
|
+
${chalk39.dim("$")} mutagent sandbox status sbx_1
|
|
30220
|
+
${chalk39.dim("$")} mutagent sandbox delete sbx_1 --force
|
|
30221
|
+
${chalk39.dim("$")} mutagent sandbox presets ${chalk39.dim("Presets `mutagent helix --preset` can name")}
|
|
30222
|
+
${chalk39.dim("$")} mutagent sandbox providers ${chalk39.dim("Sandbox providers `mutagent helix --sandbox-provider` can name")}
|
|
30223
|
+
${chalk39.dim("$")} mutagent sandbox preflight --image alpine:3.20 ${chalk39.dim("Would this definition run?")}
|
|
30224
|
+
${chalk39.dim("$")} mutagent sandbox spawn --image alpine:3.20 --detach
|
|
30225
|
+
${chalk39.dim("$")} mutagent sandbox exec --sandbox sbx_1 -- bun test
|
|
30226
|
+
${chalk39.dim("$")} mutagent sandbox attach sbx_1 --since 412
|
|
30227
|
+
${chalk39.dim("$")} mutagent sandbox traces sbx_1
|
|
30228
|
+
${chalk39.dim("$")} mutagent sandbox access --json ${chalk39.dim("Diagnostic: check whether this account can create cloud sandboxes")}
|
|
30138
30229
|
|
|
30139
30230
|
Which command:
|
|
30140
|
-
Use ${
|
|
30231
|
+
Use ${chalk39.bold("sandbox exec -- <cmd>")} for a shell command, ${chalk39.bold("mutagent helix -p")} for an agent task.
|
|
30141
30232
|
Sandbox providers are managed by the platform; pick one per run with
|
|
30142
30233
|
\`mutagent helix --sandbox-provider\` (see \`mutagent sandbox providers\`).
|
|
30143
30234
|
|
|
30144
30235
|
Single command vs kept sandbox:
|
|
30145
|
-
${
|
|
30146
|
-
and removes the sandbox. ${
|
|
30147
|
-
for ${
|
|
30236
|
+
${chalk39.bold("exec")} without --sandbox starts a fresh sandbox from a preset, runs one command
|
|
30237
|
+
and removes the sandbox. ${chalk39.bold("spawn")} starts a sandbox from an image and leaves it running
|
|
30238
|
+
for ${chalk39.bold("attach")} and ${chalk39.bold("exec --sandbox")}.
|
|
30148
30239
|
|
|
30149
30240
|
Lifecycle:
|
|
30150
30241
|
Ctrl-C, a dropped connection or a closed terminal detaches; the sandbox keeps running.
|
|
@@ -30185,7 +30276,7 @@ Requires a workspace: mutagent workspaces use <name> (or --workspace for one com
|
|
|
30185
30276
|
init_output();
|
|
30186
30277
|
init_errors();
|
|
30187
30278
|
import { Command as Command17 } from "commander";
|
|
30188
|
-
import
|
|
30279
|
+
import chalk40 from "chalk";
|
|
30189
30280
|
import { readFileSync as readFileSync16 } from "fs";
|
|
30190
30281
|
|
|
30191
30282
|
// src/lib/environment-api.ts
|
|
@@ -30332,19 +30423,19 @@ function shellWord2(word) {
|
|
|
30332
30423
|
function createEnvCommand() {
|
|
30333
30424
|
const env = new Command17("env").description("Workspace Environments: the variables and secrets an agent’s tools need").addHelpText("after", `
|
|
30334
30425
|
Examples:
|
|
30335
|
-
${
|
|
30336
|
-
${
|
|
30337
|
-
${
|
|
30338
|
-
${
|
|
30339
|
-
${
|
|
30340
|
-
${
|
|
30341
|
-
${
|
|
30426
|
+
${chalk40.dim("$")} mutagent env list
|
|
30427
|
+
${chalk40.dim("$")} mutagent env set demo GREETING=hello --secret GITHUB_TOKEN=ghp_…
|
|
30428
|
+
${chalk40.dim("$")} mutagent env set staging --from-file .env.staging --secrets-from-file .env.staging.secrets
|
|
30429
|
+
${chalk40.dim("$")} mutagent env show demo
|
|
30430
|
+
${chalk40.dim("$")} mutagent env unset demo GREETING
|
|
30431
|
+
${chalk40.dim("$")} mutagent env delete demo --force
|
|
30432
|
+
${chalk40.dim("$")} mutagent helix --env demo -p "check the deploy" ${chalk40.dim("Load it into a Helix cloud run")}
|
|
30342
30433
|
|
|
30343
30434
|
An Environment holds the variables and secrets an agent's tools need: a GitHub token,
|
|
30344
30435
|
a Langfuse key, a database URL. LLM provider keys belong in \`mutagent providers\`; a
|
|
30345
30436
|
variable named like one (ANTHROPIC_API_KEY, …) is refused unless --allow-provider-key.
|
|
30346
30437
|
|
|
30347
|
-
Values are write-only. \`show\` prints each entry's name and a
|
|
30438
|
+
Values are write-only. \`show\` prints each entry's name and a fingerprint of its value.
|
|
30348
30439
|
|
|
30349
30440
|
Names: Environments use letters, digits, '.', '_' and '-' (up to 64); variables use
|
|
30350
30441
|
A-Z, 0-9 and _, not starting with a digit. An Environment holds up to 64 KiB.
|
|
@@ -30356,7 +30447,7 @@ AI Agent Directive:
|
|
|
30356
30447
|
merges into it when present (PATCH). Pass --replace --force to overwrite the whole
|
|
30357
30448
|
Environment (PUT), which REMOVES entries you do not name. set --json returns
|
|
30358
30449
|
{ success, environment: { name, vars: [{name, fingerprint}], secrets: [...] },
|
|
30359
|
-
variables: [names], secrets: [names], replaced }.
|
|
30450
|
+
variables: [names], secrets: [names], replaced, created }.
|
|
30360
30451
|
Never ask the server for a value; there is no route that returns one.
|
|
30361
30452
|
`);
|
|
30362
30453
|
registerList(env);
|
|
@@ -30369,8 +30460,8 @@ AI Agent Directive:
|
|
|
30369
30460
|
function registerList(parent) {
|
|
30370
30461
|
parent.command("list").alias("ls").description("List the workspace’s Environments").addHelpText("after", `
|
|
30371
30462
|
Examples:
|
|
30372
|
-
${
|
|
30373
|
-
${
|
|
30463
|
+
${chalk40.dim("$")} mutagent env list
|
|
30464
|
+
${chalk40.dim("$")} mutagent env list --json
|
|
30374
30465
|
|
|
30375
30466
|
An empty list means the workspace has no Environments yet.
|
|
30376
30467
|
|
|
@@ -30387,7 +30478,7 @@ AI Agent Directive:
|
|
|
30387
30478
|
return;
|
|
30388
30479
|
}
|
|
30389
30480
|
if (environments.length === 0) {
|
|
30390
|
-
console.log(
|
|
30481
|
+
console.log(chalk40.gray("No Environments in this workspace. Create one: mutagent env set <name> KEY=VALUE"));
|
|
30391
30482
|
return;
|
|
30392
30483
|
}
|
|
30393
30484
|
output.output(environments.map((e) => ({
|
|
@@ -30404,12 +30495,13 @@ AI Agent Directive:
|
|
|
30404
30495
|
function registerShow(parent) {
|
|
30405
30496
|
parent.command("show").description("Entry names and fingerprints of one Environment — never a value").argument("<name>", "Environment name").addHelpText("after", `
|
|
30406
30497
|
Examples:
|
|
30407
|
-
${
|
|
30408
|
-
${
|
|
30498
|
+
${chalk40.dim("$")} mutagent env show demo
|
|
30499
|
+
${chalk40.dim("$")} mutagent env show demo --json
|
|
30409
30500
|
|
|
30410
|
-
Each line is NAME KIND FINGERPRINT. The fingerprint is
|
|
30411
|
-
|
|
30412
|
-
|
|
30501
|
+
Each line is NAME KIND FINGERPRINT. The fingerprint is 8 hex characters of an HMAC
|
|
30502
|
+
keyed by a secret only the server holds: it stays the same while the value is unchanged,
|
|
30503
|
+
so comparing two \`show\` runs tells you whether a value changed. It cannot be computed
|
|
30504
|
+
locally. To make sure a value is what you expect, set it again with \`mutagent env set\`.
|
|
30413
30505
|
|
|
30414
30506
|
An unknown name is an error.
|
|
30415
30507
|
|
|
@@ -30430,10 +30522,10 @@ AI Agent Directive:
|
|
|
30430
30522
|
function registerSet(parent) {
|
|
30431
30523
|
parent.command("set").description("Set variables (and --secret secrets) on an Environment; creates it when absent").argument("<name>", "Environment name").argument("[assignments...]", "KEY=VALUE variables (non-secret)").option("-s, --secret <KEY=VALUE...>", "Secret entries, encrypted at rest and never returned; every KEY=VALUE after --secret is a secret, so put variables first").option("--from-file <path>", "Read variables from a .env file (KEY=VALUE lines); argv wins on the same name").option("--secrets-from-file <path>", "Read secrets from a .env file").option("--replace", "Replace the whole Environment instead of merging into it; removes entries you do not name, so it needs --force").option("-f, --force", "Required with --replace, in every mode (--json included); a merge needs none").option("--allow-provider-key", "Permit a variable named like an LLM provider key").addHelpText("after", `
|
|
30432
30524
|
Examples:
|
|
30433
|
-
${
|
|
30434
|
-
${
|
|
30435
|
-
${
|
|
30436
|
-
${
|
|
30525
|
+
${chalk40.dim("$")} mutagent env set demo GREETING=hello
|
|
30526
|
+
${chalk40.dim("$")} mutagent env set demo GREETING=hello --secret TOKEN=abc123
|
|
30527
|
+
${chalk40.dim("$")} mutagent env set staging --from-file .env.staging
|
|
30528
|
+
${chalk40.dim("$")} mutagent env set staging --replace --from-file .env.staging --force ${chalk40.dim("Drop everything not in the file")}
|
|
30437
30529
|
|
|
30438
30530
|
Entries you name are set and the rest stay; the Environment is created if missing.
|
|
30439
30531
|
--replace removes every entry you do not name, secrets included. Without --force it
|
|
@@ -30443,7 +30535,7 @@ Positional KEY=VALUE and --from-file are variables; --secret and --secrets-from-
|
|
|
30443
30535
|
secrets (encrypted at rest, never returned). Both are set as environment variables in
|
|
30444
30536
|
the sandbox. A name cannot be both.
|
|
30445
30537
|
--secret takes every KEY=VALUE after it, so put variables first:
|
|
30446
|
-
${
|
|
30538
|
+
${chalk40.dim("$")} mutagent env set demo A=1 --secret TOKEN=x
|
|
30447
30539
|
The output names what was stored as a variable and what as a secret.
|
|
30448
30540
|
A value may contain '=': TOKEN=a=b stores "a=b".
|
|
30449
30541
|
Names: A-Z, 0-9 and _, not starting with a digit. An invalid name exits 1. A name that
|
|
@@ -30455,7 +30547,7 @@ AI Agent Directive:
|
|
|
30455
30547
|
--replace is destructive: confirm with the user first, then pass --force.
|
|
30456
30548
|
Nothing printed here contains a value. --json returns { success, environment,
|
|
30457
30549
|
variables: [names stored as variables], secrets: [names stored as secrets],
|
|
30458
|
-
replaced: boolean }. Check that each name landed where you meant it to. An invalid name exits 1 and names the KEY, not the value;
|
|
30550
|
+
replaced: boolean, created: boolean (true when this write made the Environment) }. Check that each name landed where you meant it to. An invalid name exits 1 and names the KEY, not the value;
|
|
30459
30551
|
a name that looks like an LLM provider key exits 1 unless --allow-provider-key.
|
|
30460
30552
|
`).action(async (name, assignments, options) => {
|
|
30461
30553
|
const isJson = getJsonFlag(parent);
|
|
@@ -30483,17 +30575,19 @@ AI Agent Directive:
|
|
|
30483
30575
|
}, new Set([...Object.keys(vars), ...Object.keys(secrets)]));
|
|
30484
30576
|
}
|
|
30485
30577
|
const environment = options.replace === true ? await replaceEnvironment(name, body, allow) : await patchEnvironment(name, body, allow);
|
|
30578
|
+
const created = environment.createdAt !== null && environment.createdAt === environment.updatedAt;
|
|
30486
30579
|
if (isJson) {
|
|
30487
30580
|
output.output({
|
|
30488
30581
|
success: true,
|
|
30489
30582
|
environment,
|
|
30490
30583
|
variables: Object.keys(vars),
|
|
30491
30584
|
secrets: Object.keys(secrets),
|
|
30492
|
-
replaced: options.replace === true
|
|
30585
|
+
replaced: options.replace === true,
|
|
30586
|
+
created
|
|
30493
30587
|
});
|
|
30494
30588
|
return;
|
|
30495
30589
|
}
|
|
30496
|
-
output.success(`${options.replace === true ? "Replaced" : "Updated"} Environment ${name}: ${String(environment.vars.length)} variable(s), ${String(environment.secrets.length)} secret(s)`);
|
|
30590
|
+
output.success(`${created ? "Created" : options.replace === true ? "Replaced" : "Updated"} Environment ${name}: ${String(environment.vars.length)} variable(s), ${String(environment.secrets.length)} secret(s)`);
|
|
30497
30591
|
if (Object.keys(vars).length > 0)
|
|
30498
30592
|
console.log(`Stored as variables: ${Object.keys(vars).join(", ")}`);
|
|
30499
30593
|
if (Object.keys(secrets).length > 0)
|
|
@@ -30507,8 +30601,8 @@ AI Agent Directive:
|
|
|
30507
30601
|
function registerUnset(parent) {
|
|
30508
30602
|
parent.command("unset").description("Remove entries from an Environment").argument("<name>", "Environment name").argument("<keys...>", "Entry names to remove").option("-s, --secret", "The names are secrets (default: try both variables and secrets)").option("-f, --force", "Confirm the removal (required in every mode, --json included)").addHelpText("after", `
|
|
30509
30603
|
Examples:
|
|
30510
|
-
${
|
|
30511
|
-
${
|
|
30604
|
+
${chalk40.dim("$")} mutagent env unset demo GREETING --force
|
|
30605
|
+
${chalk40.dim("$")} mutagent env unset demo TOKEN OTHER_TOKEN --force --json
|
|
30512
30606
|
|
|
30513
30607
|
A name is removed wherever it is, variable or secret; a removed secret cannot be read
|
|
30514
30608
|
back. Unsetting a name that is not there succeeds. Without --force the command refuses
|
|
@@ -30545,8 +30639,8 @@ AI Agent Directive:
|
|
|
30545
30639
|
function registerDelete(parent) {
|
|
30546
30640
|
parent.command("delete").alias("rm").description("Delete an Environment and its secrets").argument("<name>", "Environment name").option("-f, --force", "Confirm (required in every mode, --json included)").addHelpText("after", `
|
|
30547
30641
|
Examples:
|
|
30548
|
-
${
|
|
30549
|
-
${
|
|
30642
|
+
${chalk40.dim("$")} mutagent env delete demo --force
|
|
30643
|
+
${chalk40.dim("$")} mutagent env delete demo --force --json
|
|
30550
30644
|
|
|
30551
30645
|
Deletes the Environment and its encrypted secrets. Sandboxes already running keep the
|
|
30552
30646
|
values they were given; the next run naming this Environment fails.
|
|
@@ -30591,7 +30685,7 @@ async function withNotFound(name, call) {
|
|
|
30591
30685
|
return await call();
|
|
30592
30686
|
} catch (error3) {
|
|
30593
30687
|
if (error3 instanceof ApiError && error3.statusCode === 404)
|
|
30594
|
-
throw new NotFoundError("Environment", name);
|
|
30688
|
+
throw new NotFoundError("Environment", name, "mutagent env list");
|
|
30595
30689
|
throw error3;
|
|
30596
30690
|
}
|
|
30597
30691
|
}
|
|
@@ -30600,7 +30694,7 @@ function printEnvironment(environment, output, isJson) {
|
|
|
30600
30694
|
output.output({ success: true, environment });
|
|
30601
30695
|
return;
|
|
30602
30696
|
}
|
|
30603
|
-
console.log(`${
|
|
30697
|
+
console.log(`${chalk40.bold(environment.name)} ${chalk40.dim(environment.updatedAt ?? "")}`);
|
|
30604
30698
|
printEntries(environment);
|
|
30605
30699
|
}
|
|
30606
30700
|
function printEntries(environment) {
|
|
@@ -30609,12 +30703,12 @@ function printEntries(environment) {
|
|
|
30609
30703
|
...environment.secrets.map((s) => ({ name: s.name, kind: "secret", fingerprint: s.fingerprint }))
|
|
30610
30704
|
];
|
|
30611
30705
|
if (rows.length === 0) {
|
|
30612
|
-
console.log(
|
|
30706
|
+
console.log(chalk40.gray(" (no entries)"));
|
|
30613
30707
|
return;
|
|
30614
30708
|
}
|
|
30615
30709
|
const width = Math.max(...rows.map((r) => r.name.length));
|
|
30616
30710
|
for (const row of rows) {
|
|
30617
|
-
console.log(` ${row.name.padEnd(width)} ${row.kind === "secret" ?
|
|
30711
|
+
console.log(` ${row.name.padEnd(width)} ${row.kind === "secret" ? chalk40.yellow("secret") : chalk40.dim("var ")} ${chalk40.dim(row.fingerprint)}`);
|
|
30618
30712
|
}
|
|
30619
30713
|
}
|
|
30620
30714
|
|
|
@@ -30622,10 +30716,10 @@ function printEntries(environment) {
|
|
|
30622
30716
|
init_config();
|
|
30623
30717
|
init_errors();
|
|
30624
30718
|
import { Command as Command23 } from "commander";
|
|
30625
|
-
import
|
|
30719
|
+
import chalk52 from "chalk";
|
|
30626
30720
|
|
|
30627
30721
|
// src/commands/gateway/status.ts
|
|
30628
|
-
import
|
|
30722
|
+
import chalk42 from "chalk";
|
|
30629
30723
|
|
|
30630
30724
|
// src/lib/gateway-api.ts
|
|
30631
30725
|
init_config();
|
|
@@ -30841,7 +30935,7 @@ async function getGrantMoreRepositoriesUrl() {
|
|
|
30841
30935
|
// src/lib/gateway-envelope.ts
|
|
30842
30936
|
init_output();
|
|
30843
30937
|
init_known_secrets();
|
|
30844
|
-
import
|
|
30938
|
+
import chalk41 from "chalk";
|
|
30845
30939
|
init_errors();
|
|
30846
30940
|
|
|
30847
30941
|
// src/lib/gateway-notices.ts
|
|
@@ -31000,9 +31094,9 @@ function printGatewayOk(isJson, data, opts) {
|
|
|
31000
31094
|
opts.human();
|
|
31001
31095
|
if (opts.next && opts.next.length > 0) {
|
|
31002
31096
|
console.log("");
|
|
31003
|
-
console.log(
|
|
31097
|
+
console.log(chalk41.dim("Next:"));
|
|
31004
31098
|
for (const step of opts.next)
|
|
31005
|
-
console.log(
|
|
31099
|
+
console.log(chalk41.dim(` ${step}`));
|
|
31006
31100
|
}
|
|
31007
31101
|
}
|
|
31008
31102
|
function printGatewayFailureWithData(isJson, error3, data, human) {
|
|
@@ -31015,21 +31109,21 @@ function printGatewayFailureWithData(isJson, error3, data, human) {
|
|
|
31015
31109
|
return error3.exitCode;
|
|
31016
31110
|
}
|
|
31017
31111
|
function printHuman2(error3) {
|
|
31018
|
-
console.error(
|
|
31112
|
+
console.error(chalk41.red(`Error: ${scrubKnown(error3.message)}`) + chalk41.dim(` [${error3.code}]`));
|
|
31019
31113
|
if (error3.fix.length > 0) {
|
|
31020
31114
|
console.error("");
|
|
31021
|
-
console.error(
|
|
31115
|
+
console.error(chalk41.yellow("Fix:"));
|
|
31022
31116
|
for (const step of error3.fix)
|
|
31023
|
-
console.error(
|
|
31117
|
+
console.error(chalk41.yellow(` ${scrubKnown(step)}`));
|
|
31024
31118
|
}
|
|
31025
31119
|
if (error3.notes.length > 0) {
|
|
31026
31120
|
console.error("");
|
|
31027
31121
|
for (const note of error3.notes)
|
|
31028
|
-
console.error(
|
|
31122
|
+
console.error(chalk41.dim(` ${scrubKnown(note)}`));
|
|
31029
31123
|
}
|
|
31030
31124
|
if (error3.escalate !== undefined) {
|
|
31031
31125
|
console.error("");
|
|
31032
|
-
console.error(
|
|
31126
|
+
console.error(chalk41.yellow(`Needs a person: ${scrubKnown(error3.escalate)}`));
|
|
31033
31127
|
}
|
|
31034
31128
|
}
|
|
31035
31129
|
function handleGatewayError(error3, isJson, provider, resource) {
|
|
@@ -31087,16 +31181,16 @@ function nextStepFor(status) {
|
|
|
31087
31181
|
return [`mutagent gateway test-run --repo ${first.name} --wait`];
|
|
31088
31182
|
}
|
|
31089
31183
|
function printStatusHuman(status) {
|
|
31090
|
-
console.log(
|
|
31184
|
+
console.log(chalk42.bold("Gateway status") + chalk42.dim(` workspace ${status.workspaceId}`));
|
|
31091
31185
|
for (const provider of ["github", "slack"]) {
|
|
31092
31186
|
const conn = status.connections[provider];
|
|
31093
31187
|
const connected = conn?.state === "connected";
|
|
31094
|
-
const mark = connected ?
|
|
31188
|
+
const mark = connected ? chalk42.green("✓") : chalk42.yellow("·");
|
|
31095
31189
|
const detail = conn === null ? "unknown" : connected ? conn.accountName ?? conn.accountId ?? "connected" : conn.state;
|
|
31096
31190
|
console.log(` ${mark} ${provider.padEnd(6)} ${detail}`);
|
|
31097
31191
|
}
|
|
31098
31192
|
const linked = status.linkedRepositories.map((repo) => repo.name).join(", ");
|
|
31099
|
-
console.log(` ${linked === "" ?
|
|
31193
|
+
console.log(` ${linked === "" ? chalk42.yellow("·") : chalk42.green("✓")} repos ${linked === "" ? "(none linked)" : linked}`);
|
|
31100
31194
|
}
|
|
31101
31195
|
function registerGatewayStatusCommands(gateway) {
|
|
31102
31196
|
gateway.action(async () => {
|
|
@@ -31111,8 +31205,8 @@ function registerGatewayStatusCommands(gateway) {
|
|
|
31111
31205
|
});
|
|
31112
31206
|
gateway.command("status").description("What's connected, what's missing, and the next command to run").addHelpText("after", `
|
|
31113
31207
|
Examples:
|
|
31114
|
-
${
|
|
31115
|
-
${
|
|
31208
|
+
${chalk42.dim("$")} mutagent gateway status
|
|
31209
|
+
${chalk42.dim("$")} mutagent gateway status --json
|
|
31116
31210
|
|
|
31117
31211
|
Same as bare 'mutagent gateway' — the one command that always tells you what's next.
|
|
31118
31212
|
|
|
@@ -31131,8 +31225,8 @@ AI Agent Directive:
|
|
|
31131
31225
|
});
|
|
31132
31226
|
gateway.command("doctor").description("End-to-end check of the gateway setup, with fixes for anything broken").addHelpText("after", `
|
|
31133
31227
|
Examples:
|
|
31134
|
-
${
|
|
31135
|
-
${
|
|
31228
|
+
${chalk42.dim("$")} mutagent gateway doctor
|
|
31229
|
+
${chalk42.dim("$")} mutagent gateway doctor --json
|
|
31136
31230
|
|
|
31137
31231
|
Checks: GitHub/Slack connection state, a repository is linked, and — the one thing
|
|
31138
31232
|
'status' does not check — that every linked repository is still reachable through the
|
|
@@ -31171,9 +31265,9 @@ AI Agent Directive:
|
|
|
31171
31265
|
const printChecks = () => {
|
|
31172
31266
|
printStatusHuman(status);
|
|
31173
31267
|
console.log("");
|
|
31174
|
-
console.log(
|
|
31268
|
+
console.log(chalk42.bold("Checks:"));
|
|
31175
31269
|
for (const check3 of checks) {
|
|
31176
|
-
console.log(` ${check3.pass ?
|
|
31270
|
+
console.log(` ${check3.pass ? chalk42.green("✓") : chalk42.red("✗")} ${check3.name} ${chalk42.dim(check3.detail)}`);
|
|
31177
31271
|
}
|
|
31178
31272
|
};
|
|
31179
31273
|
const failing = checks.filter((c) => !c.pass);
|
|
@@ -31191,7 +31285,7 @@ AI Agent Directive:
|
|
|
31191
31285
|
}
|
|
31192
31286
|
|
|
31193
31287
|
// src/commands/gateway/connect.ts
|
|
31194
|
-
import
|
|
31288
|
+
import chalk43 from "chalk";
|
|
31195
31289
|
|
|
31196
31290
|
// src/lib/gateway-poll.ts
|
|
31197
31291
|
function sleep2(ms) {
|
|
@@ -31259,7 +31353,7 @@ function reportAttempt(provider, state, attempt, isJson) {
|
|
|
31259
31353
|
printGatewayOk(isJson, { provider, status: attempt.status }, {
|
|
31260
31354
|
next: provider === "github" ? ["mutagent gateway repos link <owner/name>"] : [],
|
|
31261
31355
|
human: () => {
|
|
31262
|
-
console.log(
|
|
31356
|
+
console.log(chalk43.green(`✓ ${provider} connected`) + chalk43.dim(` ${attempt.status?.accountName ?? attempt.status?.accountId ?? ""}`));
|
|
31263
31357
|
}
|
|
31264
31358
|
});
|
|
31265
31359
|
return;
|
|
@@ -31278,9 +31372,9 @@ function reportAttempt(provider, state, attempt, isJson) {
|
|
|
31278
31372
|
function registerConnect(gateway) {
|
|
31279
31373
|
gateway.command("connect").description("Connect GitHub or Slack (prints a URL to open, or resumes an attempt)").argument("<gateway-provider>", "github | slack").option("--wait", "Poll until the attempt settles instead of returning immediately").option("--open", "Also open the URL in a local browser (for a human at a desktop)").option("--attempt <id>", "Resume an existing attempt instead of starting a new one").addHelpText("after", `
|
|
31280
31374
|
Examples:
|
|
31281
|
-
${
|
|
31282
|
-
${
|
|
31283
|
-
${
|
|
31375
|
+
${chalk43.dim("$")} mutagent gateway connect github --json
|
|
31376
|
+
${chalk43.dim("$")} mutagent gateway connect github --wait --attempt att_abc123
|
|
31377
|
+
${chalk43.dim("$")} mutagent gateway connect slack --open
|
|
31284
31378
|
|
|
31285
31379
|
Already connected is success, not an error: re-running this once github or slack is
|
|
31286
31380
|
already connected exits 0 and does nothing — safe to retry.
|
|
@@ -31309,7 +31403,7 @@ AI Agent Directive:
|
|
|
31309
31403
|
if (existing?.state === "connected") {
|
|
31310
31404
|
printGatewayOk(isJson, { provider, status: existing, alreadyConnected: true }, {
|
|
31311
31405
|
human: () => {
|
|
31312
|
-
console.log(
|
|
31406
|
+
console.log(chalk43.green(`✓ ${provider} already connected`) + chalk43.dim(` ${existing.accountName ?? existing.accountId ?? ""}`));
|
|
31313
31407
|
}
|
|
31314
31408
|
});
|
|
31315
31409
|
return;
|
|
@@ -31326,9 +31420,9 @@ AI Agent Directive:
|
|
|
31326
31420
|
`mutagent gateway connect ${provider} --wait --attempt ${start.state}`
|
|
31327
31421
|
],
|
|
31328
31422
|
human: () => {
|
|
31329
|
-
console.log(`1. Sign in (in a browser): ${
|
|
31330
|
-
console.log(`2. Then, in that SAME browser, authorize: ${
|
|
31331
|
-
console.log(
|
|
31423
|
+
console.log(`1. Sign in (in a browser): ${chalk43.cyan(signInUrl)}`);
|
|
31424
|
+
console.log(`2. Then, in that SAME browser, authorize: ${chalk43.cyan(start.url)}`);
|
|
31425
|
+
console.log(chalk43.dim(`attempt: ${start.state}`));
|
|
31332
31426
|
}
|
|
31333
31427
|
});
|
|
31334
31428
|
return;
|
|
@@ -31342,7 +31436,7 @@ AI Agent Directive:
|
|
|
31342
31436
|
function registerReconnect(gateway) {
|
|
31343
31437
|
gateway.command("reconnect").description("Re-authorize GitHub or Slack — also recovers RUN_PRINCIPAL_UNAVAILABLE").argument("<gateway-provider>", "github | slack").addHelpText("after", `
|
|
31344
31438
|
Examples:
|
|
31345
|
-
${
|
|
31439
|
+
${chalk43.dim("$")} mutagent gateway reconnect github --json
|
|
31346
31440
|
|
|
31347
31441
|
Starts a re-auth attempt and exits 0. Sign in at signInUrl first, then open url in that
|
|
31348
31442
|
SAME browser, then finish it the same way as 'connect':
|
|
@@ -31365,9 +31459,9 @@ AI Agent Directive:
|
|
|
31365
31459
|
`mutagent gateway connect ${provider} --wait --attempt ${start.state}`
|
|
31366
31460
|
],
|
|
31367
31461
|
human: () => {
|
|
31368
|
-
console.log(`1. Sign in (in a browser): ${
|
|
31369
|
-
console.log(`2. Then, in that SAME browser, authorize: ${
|
|
31370
|
-
console.log(
|
|
31462
|
+
console.log(`1. Sign in (in a browser): ${chalk43.cyan(signInUrl)}`);
|
|
31463
|
+
console.log(`2. Then, in that SAME browser, authorize: ${chalk43.cyan(start.url)}`);
|
|
31464
|
+
console.log(chalk43.dim(`attempt: ${start.state}`));
|
|
31371
31465
|
}
|
|
31372
31466
|
});
|
|
31373
31467
|
return;
|
|
@@ -31377,7 +31471,7 @@ AI Agent Directive:
|
|
|
31377
31471
|
function registerDisconnect(gateway) {
|
|
31378
31472
|
gateway.command("disconnect").description("Disconnect GitHub or Slack from this workspace").argument("<gateway-provider>", "github | slack").option("-f, --force", "Confirm the disconnect (required; never prompted for)").option("--yes", "Same as --force").addHelpText("after", `
|
|
31379
31473
|
Examples:
|
|
31380
|
-
${
|
|
31474
|
+
${chalk43.dim("$")} mutagent gateway disconnect slack --force
|
|
31381
31475
|
|
|
31382
31476
|
Idempotent: disconnecting when github or slack is already disconnected is success, not an error.
|
|
31383
31477
|
Never prompts: without --force (or --yes) the command refuses (CONFIRMATION_REQUIRED,
|
|
@@ -31394,7 +31488,7 @@ AI Agent Directive:
|
|
|
31394
31488
|
const status = await disconnectIntegration(provider);
|
|
31395
31489
|
printGatewayOk(isJson, { provider, status }, {
|
|
31396
31490
|
human: () => {
|
|
31397
|
-
console.log(
|
|
31491
|
+
console.log(chalk43.green(`✓ ${provider} disconnected`));
|
|
31398
31492
|
}
|
|
31399
31493
|
});
|
|
31400
31494
|
return;
|
|
@@ -31408,17 +31502,17 @@ function registerGatewayConnectCommands(gateway) {
|
|
|
31408
31502
|
}
|
|
31409
31503
|
|
|
31410
31504
|
// src/commands/gateway/repos.ts
|
|
31411
|
-
import
|
|
31505
|
+
import chalk44 from "chalk";
|
|
31412
31506
|
function printLinkedRepo(repo) {
|
|
31413
|
-
const mark = repo.state === "linked" ?
|
|
31414
|
-
const dependents = repo.dependents.triggers + repo.dependents.routines > 0 ?
|
|
31507
|
+
const mark = repo.state === "linked" ? chalk44.green("✓") : chalk44.yellow("·");
|
|
31508
|
+
const dependents = repo.dependents.triggers + repo.dependents.routines > 0 ? chalk44.dim(` ${String(repo.dependents.triggers)} trigger(s), ${String(repo.dependents.routines)} routine(s)`) : "";
|
|
31415
31509
|
console.log(` ${mark} ${repo.name}${dependents}`);
|
|
31416
31510
|
}
|
|
31417
31511
|
function registerList2(gateway) {
|
|
31418
31512
|
gateway.command("repos").description("Repositories the workspace's GitHub installation can reach, or has linked").option("--available", "Every reachable repository (same as no flag)").option("--linked", "Repositories this workspace has linked, by repos link or by use, and ones it unlinked").addHelpText("after", `
|
|
31419
31513
|
Examples:
|
|
31420
|
-
${
|
|
31421
|
-
${
|
|
31514
|
+
${chalk44.dim("$")} mutagent gateway repos --json
|
|
31515
|
+
${chalk44.dim("$")} mutagent gateway repos --linked --json
|
|
31422
31516
|
|
|
31423
31517
|
No flag or --available: every repository the GitHub App installation can reach.
|
|
31424
31518
|
Any of them is usable: a repository links itself the first time it is used.
|
|
@@ -31447,7 +31541,7 @@ AI Agent Directive:
|
|
|
31447
31541
|
printGatewayOk(isJson, { items: items2, count: items2.length }, {
|
|
31448
31542
|
human: () => {
|
|
31449
31543
|
if (items2.length === 0) {
|
|
31450
|
-
console.log(
|
|
31544
|
+
console.log(chalk44.gray("No repositories linked. Fix: mutagent gateway repos link owner/name"));
|
|
31451
31545
|
return;
|
|
31452
31546
|
}
|
|
31453
31547
|
for (const repo of items2)
|
|
@@ -31460,11 +31554,11 @@ AI Agent Directive:
|
|
|
31460
31554
|
printGatewayOk(isJson, { items, count: items.length }, {
|
|
31461
31555
|
human: () => {
|
|
31462
31556
|
if (items.length === 0) {
|
|
31463
|
-
console.log(
|
|
31557
|
+
console.log(chalk44.gray("No repositories reachable. Fix: mutagent gateway repos grant-more"));
|
|
31464
31558
|
return;
|
|
31465
31559
|
}
|
|
31466
31560
|
for (const repo of items)
|
|
31467
|
-
console.log(` ${repo.name} ${
|
|
31561
|
+
console.log(` ${repo.name} ${chalk44.dim(repo.defaultBranch)}`);
|
|
31468
31562
|
}
|
|
31469
31563
|
});
|
|
31470
31564
|
return;
|
|
@@ -31474,8 +31568,8 @@ AI Agent Directive:
|
|
|
31474
31568
|
function registerLink(repos, gateway) {
|
|
31475
31569
|
repos.command("link").description("Link repositories to this workspace now; using a reachable repository links it too").argument("<repositories...>", "owner/name (or GitHub repository id), 1–25").addHelpText("after", `
|
|
31476
31570
|
Examples:
|
|
31477
|
-
${
|
|
31478
|
-
${
|
|
31571
|
+
${chalk44.dim("$")} mutagent gateway repos link owner/name
|
|
31572
|
+
${chalk44.dim("$")} mutagent gateway repos link owner/one owner/two
|
|
31479
31573
|
|
|
31480
31574
|
Idempotent: an already-linked repository is returned unchanged. All-or-nothing —
|
|
31481
31575
|
if one of several repositories can't be linked, none are.
|
|
@@ -31500,7 +31594,7 @@ AI Agent Directive:
|
|
|
31500
31594
|
function registerUnlink(repos, gateway) {
|
|
31501
31595
|
repos.command("unlink").description("Unlink a repository — its triggers and routines pause, they are not deleted").argument("<owner/name>", "The repository to unlink").option("-f, --force", "Confirm the unlink (required; never prompted for)").option("--yes", "Same as --force").addHelpText("after", `
|
|
31502
31596
|
Examples:
|
|
31503
|
-
${
|
|
31597
|
+
${chalk44.dim("$")} mutagent gateway repos unlink owner/name --force
|
|
31504
31598
|
|
|
31505
31599
|
Dependent triggers and routines PAUSE (visibly — 'repository_unlinked'), never delete.
|
|
31506
31600
|
Never prompts: without --force (or --yes) the command refuses
|
|
@@ -31517,11 +31611,11 @@ AI Agent Directive:
|
|
|
31517
31611
|
const result = await unlinkRepository(repository);
|
|
31518
31612
|
printGatewayOk(isJson, result, {
|
|
31519
31613
|
human: () => {
|
|
31520
|
-
console.log(
|
|
31614
|
+
console.log(chalk44.green(`✓ Unlinked ${result.repository.name}`));
|
|
31521
31615
|
if (result.paused.triggers.length > 0)
|
|
31522
|
-
console.log(
|
|
31616
|
+
console.log(chalk44.yellow(` paused triggers: ${result.paused.triggers.join(", ")}`));
|
|
31523
31617
|
if (result.paused.routines.length > 0)
|
|
31524
|
-
console.log(
|
|
31618
|
+
console.log(chalk44.yellow(` paused routines: ${result.paused.routines.join(", ")}`));
|
|
31525
31619
|
}
|
|
31526
31620
|
});
|
|
31527
31621
|
return;
|
|
@@ -31531,7 +31625,7 @@ AI Agent Directive:
|
|
|
31531
31625
|
function registerGrantMore(repos, gateway) {
|
|
31532
31626
|
repos.command("grant-more").description("Print the GitHub page for granting the app access to more repositories").addHelpText("after", `
|
|
31533
31627
|
Examples:
|
|
31534
|
-
${
|
|
31628
|
+
${chalk44.dim("$")} mutagent gateway repos grant-more --json
|
|
31535
31629
|
|
|
31536
31630
|
Opens no browser itself — prints the URL. Open it in the SAME browser you signed
|
|
31537
31631
|
in to Mutagent with, then 'repos link owner/name'.
|
|
@@ -31545,7 +31639,7 @@ AI Agent Directive:
|
|
|
31545
31639
|
printGatewayOk(isJson, result, {
|
|
31546
31640
|
next: ["mutagent gateway repos link owner/name"],
|
|
31547
31641
|
human: () => {
|
|
31548
|
-
console.log(`Open this URL (in the browser you signed in with): ${
|
|
31642
|
+
console.log(`Open this URL (in the browser you signed in with): ${chalk44.cyan(result.url)}`);
|
|
31549
31643
|
}
|
|
31550
31644
|
});
|
|
31551
31645
|
return;
|
|
@@ -31565,7 +31659,7 @@ function registerGatewayReposCommands(gateway) {
|
|
|
31565
31659
|
// src/commands/gateway/triggers.ts
|
|
31566
31660
|
import { readFileSync as readFileSync18 } from "node:fs";
|
|
31567
31661
|
import { Command as Command18 } from "commander";
|
|
31568
|
-
import
|
|
31662
|
+
import chalk47 from "chalk";
|
|
31569
31663
|
|
|
31570
31664
|
// src/lib/gateway-api-triggers.ts
|
|
31571
31665
|
var TRIGGER_KINDS = ["github.issue.opened", "slack.mention", "webhook", "github.ci-failed", "trace.threshold"];
|
|
@@ -31702,7 +31796,7 @@ function updatedTriggerFilter(options, id) {
|
|
|
31702
31796
|
}
|
|
31703
31797
|
|
|
31704
31798
|
// src/commands/gateway/env-flag.ts
|
|
31705
|
-
import
|
|
31799
|
+
import chalk45 from "chalk";
|
|
31706
31800
|
var ENVIRONMENT_NAME = /^[A-Za-z0-9._-]{1,64}$/;
|
|
31707
31801
|
function parseEnvFlag(raw, resource) {
|
|
31708
31802
|
if (raw === undefined)
|
|
@@ -31719,7 +31813,7 @@ function envField(environment) {
|
|
|
31719
31813
|
}
|
|
31720
31814
|
function printEnvironment2(environment) {
|
|
31721
31815
|
if (environment)
|
|
31722
|
-
console.log(
|
|
31816
|
+
console.log(chalk45.dim(` environment: ${environment}`));
|
|
31723
31817
|
}
|
|
31724
31818
|
function envHelp(verb) {
|
|
31725
31819
|
const clear = verb === "update" ? `--env "" clears it: runs then load no Environment. Changing or clearing it writes a new version.` : `--env "" is the same as leaving it out: no Environment.`;
|
|
@@ -31730,7 +31824,7 @@ Environment. The workspace must have it when you write this: an unknown name is
|
|
|
31730
31824
|
}
|
|
31731
31825
|
|
|
31732
31826
|
// src/commands/gateway/stage-subject.ts
|
|
31733
|
-
import
|
|
31827
|
+
import chalk46 from "chalk";
|
|
31734
31828
|
var CLEAR = "none";
|
|
31735
31829
|
function parseStageFlag(raw, resource) {
|
|
31736
31830
|
if (raw === undefined)
|
|
@@ -31791,9 +31885,9 @@ function stageSubjectFields(stage, subject) {
|
|
|
31791
31885
|
}
|
|
31792
31886
|
function printStageSubject(stage, subject) {
|
|
31793
31887
|
if (stage)
|
|
31794
|
-
console.log(
|
|
31888
|
+
console.log(chalk46.dim(` stage: ${stage}`));
|
|
31795
31889
|
if (subject)
|
|
31796
|
-
console.log(
|
|
31890
|
+
console.log(chalk46.dim(` subject: ${subject.kind} ${subject.names.join(", ")}`));
|
|
31797
31891
|
}
|
|
31798
31892
|
var STAGE_COMMANDS = CONFIG_STAGES.map((s) => `${s} = ${STAGE_PRESETS[s].command}`).join(", ");
|
|
31799
31893
|
var STAGE_HELP = `--stage labels what this serves: evaluate, diagnose or optimize; none clears it.
|
|
@@ -31894,12 +31988,12 @@ function trackRepoFlags(command) {
|
|
|
31894
31988
|
// src/commands/gateway/triggers.ts
|
|
31895
31989
|
var RESOURCE = "triggers";
|
|
31896
31990
|
function printTrigger(t) {
|
|
31897
|
-
const mark = t.status === "enabled" ?
|
|
31898
|
-
const builtin = t.builtin ?
|
|
31899
|
-
const repository = t.repository?.name ??
|
|
31900
|
-
console.log(` ${mark} ${t.id} ${t.name}${builtin} ${
|
|
31991
|
+
const mark = t.status === "enabled" ? chalk47.green("✓") : t.status === "paused" ? chalk47.yellow("⏸") : chalk47.dim("○");
|
|
31992
|
+
const builtin = t.builtin ? chalk47.dim(" [built-in]") : "";
|
|
31993
|
+
const repository = t.repository?.name ?? chalk47.dim(t.builtin ? "the repository the mention names or picks" : "No repository");
|
|
31994
|
+
console.log(` ${mark} ${t.id} ${t.name}${builtin} ${chalk47.dim(t.kind)} ${repository}`);
|
|
31901
31995
|
if (t.pausedReason)
|
|
31902
|
-
console.log(
|
|
31996
|
+
console.log(chalk47.yellow(` paused: ${t.pausedReason.reason}`));
|
|
31903
31997
|
printStageSubject(t.stage, t.subject);
|
|
31904
31998
|
printEnvironment2(t.environment);
|
|
31905
31999
|
}
|
|
@@ -31917,7 +32011,7 @@ function registerList3(gateway) {
|
|
|
31917
32011
|
gateway.addCommand(triggers);
|
|
31918
32012
|
triggers.description("List triggers — user-created first, then built-ins").addHelpText("after", `
|
|
31919
32013
|
Examples:
|
|
31920
|
-
${
|
|
32014
|
+
${chalk47.dim("$")} mutagent gateway triggers --json
|
|
31921
32015
|
|
|
31922
32016
|
Built-in triggers (the default @mention behaviour) are listed, marked 'builtin: true',
|
|
31923
32017
|
and are read-only — 'update'/'enable'/'disable'/'delete' on one refuse (409). A built-in
|
|
@@ -31934,7 +32028,7 @@ AI Agent Directive:
|
|
|
31934
32028
|
printGatewayOk(isJson, { items }, {
|
|
31935
32029
|
human: () => {
|
|
31936
32030
|
if (items.length === 0) {
|
|
31937
|
-
console.log(
|
|
32031
|
+
console.log(chalk47.gray("No triggers."));
|
|
31938
32032
|
return;
|
|
31939
32033
|
}
|
|
31940
32034
|
for (const t of items)
|
|
@@ -31973,12 +32067,12 @@ function createBody(options) {
|
|
|
31973
32067
|
function registerCreate(triggers, gateway, readGitRemote) {
|
|
31974
32068
|
const create4 = triggers.command("create").description("Create a trigger").option("--on <kind>", `REQUIRED — trigger kind: ${TRIGGER_KINDS.join(" | ")} | emit:<kind>`).option("--repo <owner/name>", "The repository its runs check out (default: this directory's GitHub remote)").option("--no-repo", "No repository: its runs have no checkout (webhook, emit:<kind>, trace.threshold only)").option("--instruction <text>", "The instruction Helix runs").option("--instruction-file <path>", "Read the instruction from a file").option("--name <name>", "Name (default: derived from kind + repository)").option("--key <key>", "Idempotency key — a retry with the same key returns the same trigger").option("--channel <id...>", "slack.mention only: limit to these Slack channel ids").option("--threshold <n>", "trace.threshold only: fire at or above this many traces (1–1,000,000)").option("--window <duration>", "trace.threshold only: the counting window, e.g. 60m, 24h, 7d").option("--service <name>", "trace.threshold only: limit to this service name").option("--session <id>", "trace.threshold only: limit to this session id").option("--stage <stage>", "The stage it serves: evaluate | diagnose | optimize | none").option("--subject <kind:names>", "trace.threshold only: count only these subjects, e.g. agent:support-bot,triage-bot").option("--env <name>", "A workspace Environment every run loads (see mutagent env list)").addHelpText("after", `
|
|
31975
32069
|
Examples:
|
|
31976
|
-
${
|
|
31977
|
-
${
|
|
31978
|
-
${
|
|
31979
|
-
${
|
|
31980
|
-
${
|
|
31981
|
-
${
|
|
32070
|
+
${chalk47.dim("$")} mutagent gateway triggers create --on github.issue.opened --repo owner/name --instruction "Triage: label, estimate, ask one clarifying question if needed"
|
|
32071
|
+
${chalk47.dim("$")} mutagent gateway triggers create --on slack.mention --channel C0123 --instruction "…"
|
|
32072
|
+
${chalk47.dim("$")} mutagent gateway triggers create --on trace.threshold --threshold 100 --window 60m --repo owner/name --instruction "Investigate the volume spike"
|
|
32073
|
+
${chalk47.dim("$")} mutagent gateway triggers create --on trace.threshold --threshold 50 --window 24h --subject agent:support-bot --stage diagnose --instruction "/diagnose why support-bot traces spiked"
|
|
32074
|
+
${chalk47.dim("$")} mutagent gateway triggers create --on github.issue.opened --repo owner/name --env staging --instruction "Reproduce the issue against staging"
|
|
32075
|
+
${chalk47.dim("$")} mutagent gateway triggers create --on webhook --no-repo --instruction "Summarise the payload and post it"
|
|
31982
32076
|
|
|
31983
32077
|
The repository is chosen on the trigger, never from the event payload:
|
|
31984
32078
|
- --repo owner/name: that repository. Any repository the GitHub App reaches is
|
|
@@ -32056,7 +32150,7 @@ AI Agent Directive:
|
|
|
32056
32150
|
const line = remoteChoiceLine(choice);
|
|
32057
32151
|
if (line !== undefined)
|
|
32058
32152
|
console.log(line);
|
|
32059
|
-
console.log(
|
|
32153
|
+
console.log(chalk47.green(`✓ Created trigger ${trigger.id}`));
|
|
32060
32154
|
printTrigger(trigger);
|
|
32061
32155
|
}
|
|
32062
32156
|
});
|
|
@@ -32089,14 +32183,14 @@ function updateBody(id, options) {
|
|
|
32089
32183
|
function registerUpdate(triggers, gateway) {
|
|
32090
32184
|
triggers.command("update").description("Change a trigger: only the fields you pass are sent").argument("<id>", "Trigger id").option("--instruction <text>", "New instruction Helix runs").option("--instruction-file <path>", "Read the new instruction from a file").option("--name <name>", "New name").option("--channel <id...>", "slack.mention only: replace the Slack channel ids").option("--threshold <n>", "trace.threshold only: new trace count (with --window)").option("--window <duration>", "trace.threshold only: new counting window, e.g. 60m, 24h, 7d (with --threshold)").option("--service <name>", "trace.threshold only: limit to this service name").option("--session <id>", "trace.threshold only: limit to this session id").option("--stage <stage>", "New stage: evaluate | diagnose | optimize, or none to clear it").option("--subject <kind:names>", "trace.threshold only: new subject selector, or none to clear it").option("--env <name>", 'New workspace Environment every run loads; "" clears it').addHelpText("after", `
|
|
32091
32185
|
Examples:
|
|
32092
|
-
${
|
|
32093
|
-
${
|
|
32094
|
-
${
|
|
32095
|
-
${
|
|
32096
|
-
${
|
|
32097
|
-
${
|
|
32098
|
-
${
|
|
32099
|
-
${
|
|
32186
|
+
${chalk47.dim("$")} mutagent gateway triggers update trg_abc --instruction "Label, estimate, and link duplicates"
|
|
32187
|
+
${chalk47.dim("$")} mutagent gateway triggers update trg_abc --name issue-triage --json
|
|
32188
|
+
${chalk47.dim("$")} mutagent gateway triggers update trg_abc --channel C0123 C0456
|
|
32189
|
+
${chalk47.dim("$")} mutagent gateway triggers update trg_abc --threshold 200 --window 24h
|
|
32190
|
+
${chalk47.dim("$")} mutagent gateway triggers update trg_abc --stage evaluate --subject skill:grader
|
|
32191
|
+
${chalk47.dim("$")} mutagent gateway triggers update trg_abc --stage none --subject none
|
|
32192
|
+
${chalk47.dim("$")} mutagent gateway triggers update trg_abc --env prod
|
|
32193
|
+
${chalk47.dim("$")} mutagent gateway triggers update trg_abc --env ""
|
|
32100
32194
|
|
|
32101
32195
|
Only the fields you pass are sent; everything else stays as it is. An instruction,
|
|
32102
32196
|
filter, subject or Environment change writes a new version of the trigger; a stage or name change
|
|
@@ -32122,7 +32216,7 @@ AI Agent Directive:
|
|
|
32122
32216
|
printGatewayOk(isJson, trigger, {
|
|
32123
32217
|
next: [`mutagent gateway triggers show ${trigger.id} --json`],
|
|
32124
32218
|
human: () => {
|
|
32125
|
-
console.log(
|
|
32219
|
+
console.log(chalk47.green(`✓ Updated trigger ${trigger.id}`));
|
|
32126
32220
|
printTrigger(trigger);
|
|
32127
32221
|
}
|
|
32128
32222
|
});
|
|
@@ -32161,7 +32255,7 @@ Built-in triggers refuse this (409 BUILTIN_TRIGGER_READ_ONLY).
|
|
|
32161
32255
|
function registerDelete2(triggers, gateway) {
|
|
32162
32256
|
triggers.command("delete").alias("rm").description("Delete a trigger").argument("<id>", "Trigger id").option("-f, --force", "Confirm the delete (required; never prompted for)").option("--yes", "Same as --force").addHelpText("after", `
|
|
32163
32257
|
Examples:
|
|
32164
|
-
${
|
|
32258
|
+
${chalk47.dim("$")} mutagent gateway triggers delete trg_abc --force
|
|
32165
32259
|
|
|
32166
32260
|
Built-in triggers refuse this. Never prompts: without --force (or --yes) the command
|
|
32167
32261
|
refuses (CONFIRMATION_REQUIRED, exit 1) and sends nothing.
|
|
@@ -32175,7 +32269,7 @@ AI Agent Directive:
|
|
|
32175
32269
|
requireConfirmation(options, `Deleting trigger ${id}`, `mutagent gateway triggers delete ${id} --force`, RESOURCE);
|
|
32176
32270
|
await deleteTrigger(id);
|
|
32177
32271
|
printGatewayOk(isJson, { id, deleted: true }, { human: () => {
|
|
32178
|
-
console.log(
|
|
32272
|
+
console.log(chalk47.green(`✓ Deleted trigger ${id}`));
|
|
32179
32273
|
} });
|
|
32180
32274
|
return;
|
|
32181
32275
|
}, RESOURCE);
|
|
@@ -32184,7 +32278,7 @@ AI Agent Directive:
|
|
|
32184
32278
|
function registerTest(triggers, gateway) {
|
|
32185
32279
|
triggers.command("test").description("Dry run: would a sample event match this trigger?").argument("<id>", "Trigger id").option("--event <file>", "REQUIRED — JSON sample event, as @file.json").addHelpText("after", `
|
|
32186
32280
|
Examples:
|
|
32187
|
-
${
|
|
32281
|
+
${chalk47.dim("$")} mutagent gateway triggers test trg_abc --event @sample.json
|
|
32188
32282
|
|
|
32189
32283
|
sample.json: { "source": "github", "kind": "github.issues.opened", "repositoryId": "123" }
|
|
32190
32284
|
Zero side effects — this never fires the trigger.
|
|
@@ -32214,7 +32308,7 @@ AI Agent Directive:
|
|
|
32214
32308
|
human: () => {
|
|
32215
32309
|
console.log(`matches: ${String(result.matches)} wouldRun: ${String(result.wouldRun)}`);
|
|
32216
32310
|
for (const c of result.checks)
|
|
32217
|
-
console.log(` ${c.passed ?
|
|
32311
|
+
console.log(` ${c.passed ? chalk47.green("✓") : chalk47.red("✗")} ${c.check}: ${c.detail}`);
|
|
32218
32312
|
}
|
|
32219
32313
|
});
|
|
32220
32314
|
return;
|
|
@@ -32233,7 +32327,7 @@ function registerGatewayTriggersCommands(gateway, readGitRemote) {
|
|
|
32233
32327
|
|
|
32234
32328
|
// src/commands/gateway/routines.ts
|
|
32235
32329
|
import { Command as Command19 } from "commander";
|
|
32236
|
-
import
|
|
32330
|
+
import chalk48 from "chalk";
|
|
32237
32331
|
|
|
32238
32332
|
// src/lib/gateway-api-routines.ts
|
|
32239
32333
|
var ROUTINE_EVERY_GRAMMAR = [
|
|
@@ -32310,12 +32404,12 @@ async function waitForRun(eventId) {
|
|
|
32310
32404
|
// src/commands/gateway/routines.ts
|
|
32311
32405
|
var RESOURCE2 = "routines";
|
|
32312
32406
|
function printRoutine(r) {
|
|
32313
|
-
const mark = r.status === "active" ?
|
|
32314
|
-
console.log(` ${mark} ${r.id} ${r.name} ${
|
|
32407
|
+
const mark = r.status === "active" ? chalk48.green("✓") : chalk48.yellow("⏸");
|
|
32408
|
+
console.log(` ${mark} ${r.id} ${r.name} ${chalk48.dim(`${r.schedule.cron} ${r.schedule.timezone}`)} ${r.repository?.name ?? chalk48.dim("No repository")}`);
|
|
32315
32409
|
if (r.schedule.next.length > 0)
|
|
32316
|
-
console.log(
|
|
32410
|
+
console.log(chalk48.dim(` next: ${r.schedule.next.join(", ")}`));
|
|
32317
32411
|
if (r.pausedReason)
|
|
32318
|
-
console.log(
|
|
32412
|
+
console.log(chalk48.yellow(` paused: ${r.pausedReason.reason}`));
|
|
32319
32413
|
printStageSubject(r.stage);
|
|
32320
32414
|
printEnvironment2(r.environment);
|
|
32321
32415
|
}
|
|
@@ -32324,7 +32418,7 @@ function registerList4(gateway) {
|
|
|
32324
32418
|
gateway.addCommand(routines);
|
|
32325
32419
|
routines.description("List routines, with their next three fire times").addHelpText("after", `
|
|
32326
32420
|
Examples:
|
|
32327
|
-
${
|
|
32421
|
+
${chalk48.dim("$")} mutagent gateway routines --json
|
|
32328
32422
|
|
|
32329
32423
|
AI Agent Directive:
|
|
32330
32424
|
--json returns { success, ok, data: { items: Routine[] } }. schedule.next is 3 ISO-8601
|
|
@@ -32336,7 +32430,7 @@ AI Agent Directive:
|
|
|
32336
32430
|
printGatewayOk(isJson, { items }, {
|
|
32337
32431
|
human: () => {
|
|
32338
32432
|
if (items.length === 0) {
|
|
32339
|
-
console.log(
|
|
32433
|
+
console.log(chalk48.gray("No routines."));
|
|
32340
32434
|
return;
|
|
32341
32435
|
}
|
|
32342
32436
|
for (const r of items)
|
|
@@ -32385,10 +32479,10 @@ function createBody2(options) {
|
|
|
32385
32479
|
function registerCreate2(routines, gateway, readGitRemote) {
|
|
32386
32480
|
const create4 = routines.command("create").description("Create a routine").option("--every <schedule>", "Plain-language schedule — see --help for the grammar").option("--cron <expr>", "5-field cron expression (minute hour day-of-month month day-of-week)").option("--tz <IANA timezone>", "REQUIRED — e.g. Europe/Berlin").option("--repo <owner/name>", "The repository its runs check out (default: this directory's GitHub remote)").option("--no-repo", "No repository: its runs have no checkout").option("--instruction <text>", "The instruction Helix runs").option("--instruction-file <path>", "Read the instruction from a file").option("--name <name>", "Name (default: derived)").option("--key <key>", "Idempotency key").option("--stage <stage>", "The stage it serves: evaluate | diagnose | optimize | none").option("--env <name>", "A workspace Environment every run loads (see mutagent env list)").addHelpText("after", `
|
|
32387
32481
|
Examples:
|
|
32388
|
-
${
|
|
32389
|
-
${
|
|
32390
|
-
${
|
|
32391
|
-
${
|
|
32482
|
+
${chalk48.dim("$")} mutagent gateway routines create --every "weekdays 09:00" --tz Europe/Berlin --repo owner/name --instruction "Check main's failing CI and open an issue for each new failure"
|
|
32483
|
+
${chalk48.dim("$")} mutagent gateway routines create --cron "0 9 * * 1-5" --tz America/New_York --repo owner/name --instruction "…"
|
|
32484
|
+
${chalk48.dim("$")} mutagent gateway routines create --every "daily 06:00" --tz Europe/Berlin --repo owner/name --stage evaluate --instruction "/evaluate yesterday's support-bot traces"
|
|
32485
|
+
${chalk48.dim("$")} mutagent gateway routines create --every "weekdays 09:00" --tz Europe/Berlin --repo owner/name --env staging --instruction "Smoke-test staging"
|
|
32392
32486
|
|
|
32393
32487
|
Exactly one of --every / --cron. --tz is REQUIRED — omitting it is refused locally,
|
|
32394
32488
|
before any request:
|
|
@@ -32434,7 +32528,7 @@ AI Agent Directive:
|
|
|
32434
32528
|
const line = remoteChoiceLine(choice);
|
|
32435
32529
|
if (line !== undefined)
|
|
32436
32530
|
console.log(line);
|
|
32437
|
-
console.log(
|
|
32531
|
+
console.log(chalk48.green(`✓ Created routine ${routine.id}`));
|
|
32438
32532
|
printRoutine(routine);
|
|
32439
32533
|
}
|
|
32440
32534
|
});
|
|
@@ -32471,11 +32565,11 @@ function updateBody2(id, options) {
|
|
|
32471
32565
|
function registerUpdate2(routines, gateway) {
|
|
32472
32566
|
routines.command("update").description("Change a routine: only the fields you pass are sent").argument("<id>", "Routine id").option("--every <schedule>", "New plain-language schedule (with --tz) — grammar in routines create --help").option("--cron <expr>", "New 5-field cron expression (with --tz)").option("--tz <IANA timezone>", "Timezone: required with --every/--cron; alone, moves the current schedule").option("--instruction <text>", "New instruction Helix runs").option("--instruction-file <path>", "Read the new instruction from a file").option("--name <name>", "New name").option("--stage <stage>", "New stage: evaluate | diagnose | optimize, or none to clear it").option("--env <name>", 'New workspace Environment every run loads; "" clears it').addHelpText("after", `
|
|
32473
32567
|
Examples:
|
|
32474
|
-
${
|
|
32475
|
-
${
|
|
32476
|
-
${
|
|
32477
|
-
${
|
|
32478
|
-
${
|
|
32568
|
+
${chalk48.dim("$")} mutagent gateway routines update rtn_abc --every "weekdays 10:00" --tz Europe/Berlin
|
|
32569
|
+
${chalk48.dim("$")} mutagent gateway routines update rtn_abc --instruction "Check CI and label flaky tests" --json
|
|
32570
|
+
${chalk48.dim("$")} mutagent gateway routines update rtn_abc --tz America/New_York
|
|
32571
|
+
${chalk48.dim("$")} mutagent gateway routines update rtn_abc --stage none
|
|
32572
|
+
${chalk48.dim("$")} mutagent gateway routines update rtn_abc --env ""
|
|
32479
32573
|
|
|
32480
32574
|
Only the fields you pass are sent; everything else stays as it is. An instruction
|
|
32481
32575
|
or Environment change writes a new version of the routine; a schedule, name or stage
|
|
@@ -32499,7 +32593,7 @@ AI Agent Directive:
|
|
|
32499
32593
|
printGatewayOk(isJson, routine, {
|
|
32500
32594
|
next: [`mutagent gateway routines show ${routine.id} --json`],
|
|
32501
32595
|
human: () => {
|
|
32502
|
-
console.log(
|
|
32596
|
+
console.log(chalk48.green(`✓ Updated routine ${routine.id}`));
|
|
32503
32597
|
printRoutine(routine);
|
|
32504
32598
|
}
|
|
32505
32599
|
});
|
|
@@ -32536,7 +32630,7 @@ function registerPauseResume(routines, gateway) {
|
|
|
32536
32630
|
function registerDelete3(routines, gateway) {
|
|
32537
32631
|
routines.command("delete").alias("rm").argument("<id>", "Routine id").option("-f, --force", "Confirm the delete (required; never prompted for)").option("--yes", "Same as --force").description("Delete a routine").addHelpText("after", `
|
|
32538
32632
|
Examples:
|
|
32539
|
-
${
|
|
32633
|
+
${chalk48.dim("$")} mutagent gateway routines delete rtn_abc --force
|
|
32540
32634
|
|
|
32541
32635
|
Never prompts: without --force (or --yes) the command refuses (CONFIRMATION_REQUIRED,
|
|
32542
32636
|
exit 1) and sends nothing. To stop a routine without losing it, use 'routines pause'.
|
|
@@ -32550,7 +32644,7 @@ AI Agent Directive:
|
|
|
32550
32644
|
requireConfirmation(options, `Deleting routine ${id}`, `mutagent gateway routines delete ${id} --force`, RESOURCE2);
|
|
32551
32645
|
await deleteRoutine(id);
|
|
32552
32646
|
printGatewayOk(isJson, { id, deleted: true }, { human: () => {
|
|
32553
|
-
console.log(
|
|
32647
|
+
console.log(chalk48.green(`✓ Deleted routine ${id}`));
|
|
32554
32648
|
} });
|
|
32555
32649
|
return;
|
|
32556
32650
|
}, RESOURCE2);
|
|
@@ -32559,7 +32653,7 @@ AI Agent Directive:
|
|
|
32559
32653
|
function registerRunNow(routines, gateway) {
|
|
32560
32654
|
routines.command("run-now").argument("<id>", "Routine id").option("--wait", "Poll until the run settles instead of returning the event id immediately").option("--key <key>", "Idempotency key (default: a fresh key each call — same key is the same run)").description("Run a routine once, right now").addHelpText("after", `
|
|
32561
32655
|
Examples:
|
|
32562
|
-
${
|
|
32656
|
+
${chalk48.dim("$")} mutagent gateway routines run-now rtn_abc --wait
|
|
32563
32657
|
|
|
32564
32658
|
Idempotent per key: the same --key returns the SAME run, not a new one.
|
|
32565
32659
|
|
|
@@ -32575,7 +32669,7 @@ AI Agent Directive:
|
|
|
32575
32669
|
printGatewayOk(isJson, result, {
|
|
32576
32670
|
next: [`mutagent gateway runs show ${result.eventId} --json`],
|
|
32577
32671
|
human: () => {
|
|
32578
|
-
console.log(
|
|
32672
|
+
console.log(chalk48.dim(`event: ${result.eventId}${result.created ? "" : " (existing run for this key)"}`));
|
|
32579
32673
|
}
|
|
32580
32674
|
});
|
|
32581
32675
|
return;
|
|
@@ -32606,7 +32700,7 @@ function registerGatewayRoutinesCommands(gateway, readGitRemote) {
|
|
|
32606
32700
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
32607
32701
|
import { readFileSync as readFileSync19 } from "node:fs";
|
|
32608
32702
|
import { Command as Command20 } from "commander";
|
|
32609
|
-
import
|
|
32703
|
+
import chalk49 from "chalk";
|
|
32610
32704
|
|
|
32611
32705
|
// src/lib/gateway-api-runs.ts
|
|
32612
32706
|
init_known_secrets();
|
|
@@ -32763,32 +32857,32 @@ function printRunError(error3, indent) {
|
|
|
32763
32857
|
if (error3 === null)
|
|
32764
32858
|
return;
|
|
32765
32859
|
if (error3.triageItem !== undefined) {
|
|
32766
|
-
console.log(
|
|
32767
|
-
console.log(
|
|
32860
|
+
console.log(chalk49.green(`${indent}${filedAsTriageLine(error3.triageItem)}`));
|
|
32861
|
+
console.log(chalk49.dim(`${indent}next: ${filedAsTriageNext(error3.triageItem).join(", ")}`));
|
|
32768
32862
|
return;
|
|
32769
32863
|
}
|
|
32770
|
-
console.log(
|
|
32864
|
+
console.log(chalk49.red(`${indent}${error3.code}: ${error3.reason}`));
|
|
32771
32865
|
for (const step of error3.fix)
|
|
32772
|
-
console.log(
|
|
32866
|
+
console.log(chalk49.yellow(`${indent}Fix: ${step}`));
|
|
32773
32867
|
}
|
|
32774
32868
|
function nextForRun(run) {
|
|
32775
32869
|
return run.error?.triageItem === undefined ? undefined : filedAsTriageNext(run.error.triageItem);
|
|
32776
32870
|
}
|
|
32777
32871
|
function printRunStatus(run) {
|
|
32778
|
-
console.log(`${
|
|
32872
|
+
console.log(`${chalk49.bold(run.eventId)} ${run.phase}`);
|
|
32779
32873
|
if (run.sandbox)
|
|
32780
|
-
console.log(
|
|
32874
|
+
console.log(chalk49.dim(` sandbox: ${run.sandbox.kind} (${run.sandbox.environment})`));
|
|
32781
32875
|
if (run.startedAt)
|
|
32782
|
-
console.log(
|
|
32876
|
+
console.log(chalk49.dim(` started: ${run.startedAt}`));
|
|
32783
32877
|
if (run.finishedAt)
|
|
32784
|
-
console.log(
|
|
32878
|
+
console.log(chalk49.dim(` finished: ${run.finishedAt}`));
|
|
32785
32879
|
printRunError(run.error, " ");
|
|
32786
32880
|
}
|
|
32787
32881
|
function registerTestRun(gateway) {
|
|
32788
32882
|
gateway.command("test-run").description("Run the built-in onboarding test agent on a repository").option("--repo <owner/name>", "REQUIRED — the repository to run on").option("--wait", "Poll until the run settles instead of returning the event id immediately").option("--key <key>", "Idempotency key — the same key is one run (default: a fresh key each call)").addHelpText("after", `
|
|
32789
32883
|
Examples:
|
|
32790
|
-
${
|
|
32791
|
-
${
|
|
32884
|
+
${chalk49.dim("$")} mutagent gateway test-run --repo owner/name --wait
|
|
32885
|
+
${chalk49.dim("$")} mutagent gateway test-run --repo owner/name --key onboarding-check-1
|
|
32792
32886
|
|
|
32793
32887
|
Proves the whole pipeline runs: GitHub/Slack connection, repository access, and a
|
|
32794
32888
|
Helix agent turn in a sandbox, latest default-branch commit.
|
|
@@ -32808,7 +32902,7 @@ AI Agent Directive:
|
|
|
32808
32902
|
printGatewayOk(isJson, { eventId }, {
|
|
32809
32903
|
next: [`mutagent gateway runs show ${eventId} --json`],
|
|
32810
32904
|
human: () => {
|
|
32811
|
-
console.log(
|
|
32905
|
+
console.log(chalk49.dim(`event: ${eventId}`));
|
|
32812
32906
|
}
|
|
32813
32907
|
});
|
|
32814
32908
|
return;
|
|
@@ -32826,14 +32920,14 @@ AI Agent Directive:
|
|
|
32826
32920
|
});
|
|
32827
32921
|
}
|
|
32828
32922
|
function printRunSummary(r) {
|
|
32829
|
-
console.log(` ${r.id} ${
|
|
32923
|
+
console.log(` ${r.id} ${chalk49.dim(r.state)} ${r.origin.kind}${r.origin.id ? `:${r.origin.id}` : ""} ${r.repository?.name ?? ""}`);
|
|
32830
32924
|
printRunError(r.error, " ");
|
|
32831
32925
|
}
|
|
32832
32926
|
function registerRunsList(runs, gateway) {
|
|
32833
32927
|
runs.description("Runs from triggers, routines, the test run and emit — newest first").option("--status <s>", "Comma-separated states to filter to").option("--since <duration>", "ISO-8601 timestamp, or a duration like 30m / 24h / 7d").option("--trigger <id>", "Only runs launched by this trigger").option("--routine <id>", "Only runs launched by this routine").addHelpText("after", `
|
|
32834
32928
|
Examples:
|
|
32835
|
-
${
|
|
32836
|
-
${
|
|
32929
|
+
${chalk49.dim("$")} mutagent gateway runs --since 24h --json
|
|
32930
|
+
${chalk49.dim("$")} mutagent gateway runs --status failed --json
|
|
32837
32931
|
|
|
32838
32932
|
AI Agent Directive:
|
|
32839
32933
|
--json returns { success, ok, data: { items: RunSummary[] } }. state is one of queued |
|
|
@@ -32854,7 +32948,7 @@ AI Agent Directive:
|
|
|
32854
32948
|
printGatewayOk(isJson, { items: display }, {
|
|
32855
32949
|
human: () => {
|
|
32856
32950
|
if (display.length === 0) {
|
|
32857
|
-
console.log(
|
|
32951
|
+
console.log(chalk49.gray("No runs."));
|
|
32858
32952
|
return;
|
|
32859
32953
|
}
|
|
32860
32954
|
for (const r of display)
|
|
@@ -32868,8 +32962,8 @@ AI Agent Directive:
|
|
|
32868
32962
|
function registerRunsShow(runs, gateway) {
|
|
32869
32963
|
runs.command("show").description("Run status — by event id or run id").argument("<id>", "The event id (from test-run, emit or mutagent gateway events list) or the run id (from mutagent gateway runs)").addHelpText("after", `
|
|
32870
32964
|
Examples:
|
|
32871
|
-
${
|
|
32872
|
-
${
|
|
32965
|
+
${chalk49.dim("$")} mutagent gateway runs show evt_abc123 --json
|
|
32966
|
+
${chalk49.dim("$")} mutagent gateway runs show run_abc123 --json
|
|
32873
32967
|
|
|
32874
32968
|
Tries the event-id route first ('GET events/:eventId/run', unchanged since test-run
|
|
32875
32969
|
and emit have always used it); an id that route doesn't recognise (not_found) is
|
|
@@ -32914,9 +33008,9 @@ AI Agent Directive:
|
|
|
32914
33008
|
function registerRunsLogs(runs, gateway) {
|
|
32915
33009
|
runs.command("logs").description("A run's logs, from its Helix session — by run id or event id").argument("<id>", "The run id (from mutagent gateway runs) or the event id (from test-run, emit or mutagent gateway events list)").option("--follow", "Poll and print new entries until the run is done").addHelpText("after", `
|
|
32916
33010
|
Examples:
|
|
32917
|
-
${
|
|
32918
|
-
${
|
|
32919
|
-
${
|
|
33011
|
+
${chalk49.dim("$")} mutagent gateway runs logs run_abc123 --json
|
|
33012
|
+
${chalk49.dim("$")} mutagent gateway runs logs run_abc123 --follow
|
|
33013
|
+
${chalk49.dim("$")} mutagent gateway runs logs evt_abc123 --json
|
|
32920
33014
|
|
|
32921
33015
|
Takes the same ids as 'runs show', looked up the same way: the event-id route first,
|
|
32922
33016
|
then the id as a run id. An event id reads the logs of the run that event started
|
|
@@ -32945,7 +33039,7 @@ AI Agent Directive:
|
|
|
32945
33039
|
printGatewayOk(isJson, page, {
|
|
32946
33040
|
human: () => {
|
|
32947
33041
|
for (const entry of page.items)
|
|
32948
|
-
console.log(`${
|
|
33042
|
+
console.log(`${chalk49.dim(entry.at)} ${entry.text}`);
|
|
32949
33043
|
}
|
|
32950
33044
|
});
|
|
32951
33045
|
if (options.follow !== true || page.done)
|
|
@@ -32971,8 +33065,8 @@ async function cancelWithHints(runId, reason) {
|
|
|
32971
33065
|
function registerRunsCancel(runs, gateway) {
|
|
32972
33066
|
runs.command("cancel").description("Cancel a run: stop it and its Helix session").argument("<runId>", "The run id (from mutagent gateway runs or runs show)").option("-f, --force", "Confirm the cancel (required; never prompted for)").option("--yes", "Same as --force").option("--reason <text>", "Why, for the server log only (never stored on the run or shown back)").addHelpText("after", `
|
|
32973
33067
|
Examples:
|
|
32974
|
-
${
|
|
32975
|
-
${
|
|
33068
|
+
${chalk49.dim("$")} mutagent gateway runs cancel run_abc123 --force
|
|
33069
|
+
${chalk49.dim("$")} mutagent gateway runs cancel run_abc123 --force --reason "wrong repository" --json
|
|
32976
33070
|
|
|
32977
33071
|
Stops the run and its Helix session; the run ends with the error code 'cancelled'.
|
|
32978
33072
|
Cancelling a run that is already cancelled changes nothing and succeeds. A run that
|
|
@@ -32996,7 +33090,7 @@ AI Agent Directive:
|
|
|
32996
33090
|
printGatewayOk(isJson, display, {
|
|
32997
33091
|
next: [`mutagent gateway runs show ${runId} --json`],
|
|
32998
33092
|
human: () => {
|
|
32999
|
-
console.log(run.state === "cancelled" ?
|
|
33093
|
+
console.log(run.state === "cancelled" ? chalk49.green(`✓ Cancelled run ${runId}`) : chalk49.yellow(`Run ${runId} is stopping (state: ${run.state})`));
|
|
33000
33094
|
printRunSummary(display);
|
|
33001
33095
|
}
|
|
33002
33096
|
});
|
|
@@ -33024,8 +33118,8 @@ function readPayloadFile(path) {
|
|
|
33024
33118
|
function registerEmit(gateway) {
|
|
33025
33119
|
gateway.command("emit").description("Emit a user-defined event into the gateway").argument("<kind>", "Event kind — matched against emit:<kind> triggers").option("--key <key>", "Idempotency key (default: a fresh key each call)").option("--payload <file>", "JSON payload, as @file.json").option("--wait", "Poll every resulting run to a terminal phase before returning").addHelpText("after", `
|
|
33026
33120
|
Examples:
|
|
33027
|
-
${
|
|
33028
|
-
${
|
|
33121
|
+
${chalk49.dim("$")} mutagent gateway emit deploy.finished --payload @payload.json --wait
|
|
33122
|
+
${chalk49.dim("$")} mutagent gateway emit heartbeat --key daily-2026-09-22
|
|
33029
33123
|
|
|
33030
33124
|
--payload takes an '@' file reference, e.g. --payload @payload.json — never inline JSON
|
|
33031
33125
|
(shells mangle quoting on long payloads).
|
|
@@ -33046,7 +33140,7 @@ AI Agent Directive:
|
|
|
33046
33140
|
if (options.wait !== true || result.eventIds.length === 0) {
|
|
33047
33141
|
printGatewayOk(isJson, result, {
|
|
33048
33142
|
human: () => {
|
|
33049
|
-
console.log(`${result.kind} ${
|
|
33143
|
+
console.log(`${result.kind} ${chalk49.dim(`${String(result.eventIds.length)} event(s)`)}`);
|
|
33050
33144
|
for (const id of result.eventIds)
|
|
33051
33145
|
console.log(` ${id}`);
|
|
33052
33146
|
}
|
|
@@ -33088,7 +33182,7 @@ function registerGatewayRunCommands(gateway) {
|
|
|
33088
33182
|
|
|
33089
33183
|
// src/commands/gateway/events.ts
|
|
33090
33184
|
import { Command as Command21 } from "commander";
|
|
33091
|
-
import
|
|
33185
|
+
import chalk50 from "chalk";
|
|
33092
33186
|
|
|
33093
33187
|
// src/lib/gateway-api-events.ts
|
|
33094
33188
|
import { GatewayStreamError, streamGatewayUpdates } from "@mutagent/sdk/custom/gateway-stream.js";
|
|
@@ -33157,8 +33251,8 @@ function parseLimit2(raw, feed) {
|
|
|
33157
33251
|
return value2;
|
|
33158
33252
|
}
|
|
33159
33253
|
function eventRow(e) {
|
|
33160
|
-
const triage = e.filesTriage === true ?
|
|
33161
|
-
return ` ${
|
|
33254
|
+
const triage = e.filesTriage === true ? chalk50.yellow(" files a triage item") : "";
|
|
33255
|
+
return ` ${chalk50.dim(e.receivedAt)} ${e.outcome.padEnd(8)} ${e.kind} ${chalk50.dim(e.source)} ${e.id}${triage}`;
|
|
33162
33256
|
}
|
|
33163
33257
|
function displayNotice(n) {
|
|
33164
33258
|
const rendered = renderRunErrorForDisplay({ code: n.code, reason: n.reason, fix: n.fix });
|
|
@@ -33167,10 +33261,10 @@ function displayNotice(n) {
|
|
|
33167
33261
|
function registerEventsList(events, gateway) {
|
|
33168
33262
|
events.command("list").alias("ls").description("Events that reached the workspace, newest first, with their outcome").option("--since <when>", "ISO-8601 timestamp, or a duration like 30m / 24h / 7d").option("--cursor <cursor>", "nextCursor from the previous page").option("--limit <n>", "Page size, 1-100").option("--follow", "Stay connected and print each event as it settles (Ctrl-C to stop)").addHelpText("after", `
|
|
33169
33263
|
Examples:
|
|
33170
|
-
${
|
|
33171
|
-
${
|
|
33172
|
-
${
|
|
33173
|
-
${
|
|
33264
|
+
${chalk50.dim("$")} mutagent gateway events list --since 24h
|
|
33265
|
+
${chalk50.dim("$")} mutagent gateway events list --limit 50 --json
|
|
33266
|
+
${chalk50.dim("$")} mutagent gateway events list --cursor <nextCursor> --json
|
|
33267
|
+
${chalk50.dim("$")} mutagent gateway events list --follow --json
|
|
33174
33268
|
|
|
33175
33269
|
outcome is matched (a trigger or rule took it), no_match, or refused. Events being
|
|
33176
33270
|
matched appear once they settle. filesTriage: true marks a Slack mention leading
|
|
@@ -33217,7 +33311,7 @@ AI Agent Directive:
|
|
|
33217
33311
|
next: page.nextCursor === null ? undefined : [`${again} --cursor ${page.nextCursor}${isJson ? " --json" : ""}`],
|
|
33218
33312
|
human: () => {
|
|
33219
33313
|
if (page.items.length === 0) {
|
|
33220
|
-
console.log(
|
|
33314
|
+
console.log(chalk50.gray("No events."));
|
|
33221
33315
|
return;
|
|
33222
33316
|
}
|
|
33223
33317
|
for (const e of page.items)
|
|
@@ -33236,7 +33330,7 @@ async function followEvents(isJson) {
|
|
|
33236
33330
|
process.once("SIGINT", stop);
|
|
33237
33331
|
process.once("SIGTERM", stop);
|
|
33238
33332
|
if (!isJson)
|
|
33239
|
-
console.error(
|
|
33333
|
+
console.error(chalk50.dim("Following gateway events (Ctrl-C to stop)…"));
|
|
33240
33334
|
try {
|
|
33241
33335
|
for await (const frame of followGateway(controller.signal)) {
|
|
33242
33336
|
if (frame.event !== "event" && frame.event !== "ready" && frame.event !== "error")
|
|
@@ -33247,7 +33341,7 @@ async function followEvents(isJson) {
|
|
|
33247
33341
|
console.log(eventRow(scrubKnownSuccessDeep(frame.data)));
|
|
33248
33342
|
} else if (frame.event === "error") {
|
|
33249
33343
|
const data = frame.data;
|
|
33250
|
-
console.error(
|
|
33344
|
+
console.error(chalk50.yellow(`stream: ${data.code}: ${data.reason} (reconnecting)`));
|
|
33251
33345
|
}
|
|
33252
33346
|
}
|
|
33253
33347
|
} finally {
|
|
@@ -33255,13 +33349,13 @@ async function followEvents(isJson) {
|
|
|
33255
33349
|
process.removeListener("SIGTERM", stop);
|
|
33256
33350
|
}
|
|
33257
33351
|
if (!isJson)
|
|
33258
|
-
console.error(
|
|
33352
|
+
console.error(chalk50.dim("Stopped."));
|
|
33259
33353
|
}
|
|
33260
33354
|
function registerNoticesList(notices, gateway) {
|
|
33261
33355
|
notices.command("list").alias("ls").description('"Could not run" notices: why an app mention started no run, and the reply sent').option("--cursor <cursor>", "nextCursor from the previous page").option("--limit <n>", "Page size, 1-100").addHelpText("after", `
|
|
33262
33356
|
Examples:
|
|
33263
|
-
${
|
|
33264
|
-
${
|
|
33357
|
+
${chalk50.dim("$")} mutagent gateway notices list
|
|
33358
|
+
${chalk50.dim("$")} mutagent gateway notices list --cursor <nextCursor> --json
|
|
33265
33359
|
|
|
33266
33360
|
Each notice says why a Slack or GitHub mention started no run (code, reason), the fix
|
|
33267
33361
|
as a command, and whether the reply reached the thread (replySent, replyState). The
|
|
@@ -33285,19 +33379,19 @@ AI Agent Directive:
|
|
|
33285
33379
|
next: page.nextCursor === null ? undefined : [`mutagent gateway notices list${limit === undefined ? "" : ` --limit ${String(limit)}`} --cursor ${page.nextCursor}${isJson ? " --json" : ""}`],
|
|
33286
33380
|
human: () => {
|
|
33287
33381
|
if (items.length === 0) {
|
|
33288
|
-
console.log(
|
|
33382
|
+
console.log(chalk50.gray("No notices."));
|
|
33289
33383
|
return;
|
|
33290
33384
|
}
|
|
33291
33385
|
for (const n of items) {
|
|
33292
|
-
console.log(` ${
|
|
33386
|
+
console.log(` ${chalk50.dim(n.createdAt)} ${n.eventKind} ${chalk50.dim(n.eventId)} reply ${n.replyTo}: ${n.replyState}`);
|
|
33293
33387
|
if (n.triageItem !== undefined) {
|
|
33294
|
-
console.log(
|
|
33295
|
-
console.log(
|
|
33388
|
+
console.log(chalk50.green(` ${filedAsTriageLine(n.triageItem)}`));
|
|
33389
|
+
console.log(chalk50.dim(` next: ${filedAsTriageNext(n.triageItem).join(", ")}`));
|
|
33296
33390
|
continue;
|
|
33297
33391
|
}
|
|
33298
33392
|
console.log(` ${n.code}: ${n.reason}`);
|
|
33299
33393
|
for (const step of n.fix)
|
|
33300
|
-
console.log(
|
|
33394
|
+
console.log(chalk50.yellow(` Fix: ${step}`));
|
|
33301
33395
|
}
|
|
33302
33396
|
}
|
|
33303
33397
|
});
|
|
@@ -33316,7 +33410,7 @@ function registerGatewayEventsCommands(gateway) {
|
|
|
33316
33410
|
|
|
33317
33411
|
// src/commands/gateway/admin.ts
|
|
33318
33412
|
import { Command as Command22 } from "commander";
|
|
33319
|
-
import
|
|
33413
|
+
import chalk51 from "chalk";
|
|
33320
33414
|
|
|
33321
33415
|
// src/lib/gateway-admin.ts
|
|
33322
33416
|
import { execFile as execFile2 } from "node:child_process";
|
|
@@ -33395,7 +33489,7 @@ init_known_secrets();
|
|
|
33395
33489
|
function registerPreflight(admin, gateway) {
|
|
33396
33490
|
admin.command("preflight").description("End-to-end check: could this deployment serve a gateway delivery right now?").option("--workspace <id>", "Scope repository/channel/target checks to one workspace (default: the configured workspace)").addHelpText("after", `
|
|
33397
33491
|
Examples:
|
|
33398
|
-
${
|
|
33492
|
+
${chalk51.dim("$")} mutagent gateway admin preflight --json
|
|
33399
33493
|
|
|
33400
33494
|
Wraps 'bun run gateway:preflight' in the mutagent/ server checkout. Operator-only —
|
|
33401
33495
|
see 'mutagent gateway admin --help' for what that requires (checkout + DATABASE_URL).
|
|
@@ -33418,9 +33512,9 @@ AI Agent Directive:
|
|
|
33418
33512
|
throw new GatewayCliError("SERVER_FAULT", `gateway:preflight did not print JSON (exit ${String(result.exitCode)}): ${scrubKnownSuccess(result.stderr || result.stdout).slice(0, 500)}`, { notes: ["The server script failed before it could report. Its output is above; run it from the server checkout to see the full error."] });
|
|
33419
33513
|
}
|
|
33420
33514
|
const human = () => {
|
|
33421
|
-
console.log(`${report.verdict === "PASS" ?
|
|
33515
|
+
console.log(`${report.verdict === "PASS" ? chalk51.green("PASS") : chalk51.red("BLOCKED")} ${chalk51.dim(`${String(report.checked.length)} checked`)}`);
|
|
33422
33516
|
for (const finding of report.findings)
|
|
33423
|
-
console.log(` ${
|
|
33517
|
+
console.log(` ${chalk51.red("✗")} ${finding.item}: ${finding.detail}`);
|
|
33424
33518
|
};
|
|
33425
33519
|
if (report.verdict === "PASS") {
|
|
33426
33520
|
printGatewayOk(isJson, report, { human });
|
|
@@ -33436,7 +33530,7 @@ AI Agent Directive:
|
|
|
33436
33530
|
function registerSeedApps(admin, gateway) {
|
|
33437
33531
|
admin.command("seed-apps").description("Load a GitHub App's / Slack app's credentials from the environment").addHelpText("after", `
|
|
33438
33532
|
Examples:
|
|
33439
|
-
${
|
|
33533
|
+
${chalk51.dim("$")} mutagent gateway admin seed-apps --json
|
|
33440
33534
|
|
|
33441
33535
|
Wraps 'bun run gateway:seed-apps' in the mutagent/ server checkout. Operator-only —
|
|
33442
33536
|
see 'mutagent gateway admin --help'. Credentials come from the environment ONLY
|
|
@@ -33471,8 +33565,8 @@ AI Agent Directive:
|
|
|
33471
33565
|
function registerLimits(admin, gateway) {
|
|
33472
33566
|
const limits = new Command22("limits").description("Show or set the workspace's run-concurrency and daily-run caps").addHelpText("after", `
|
|
33473
33567
|
Examples:
|
|
33474
|
-
${
|
|
33475
|
-
${
|
|
33568
|
+
${chalk51.dim("$")} mutagent gateway admin limits --json
|
|
33569
|
+
${chalk51.dim("$")} mutagent gateway admin limits set --concurrent 5 --daily 100 --json
|
|
33476
33570
|
|
|
33477
33571
|
Bare (or 'admin limits'): shows the current caps. 'set': changes them — admins only.
|
|
33478
33572
|
|
|
@@ -33488,8 +33582,8 @@ AI Agent Directive:
|
|
|
33488
33582
|
const current = await getWorkspaceLimits();
|
|
33489
33583
|
printGatewayOk(isJson, current, {
|
|
33490
33584
|
human: () => {
|
|
33491
|
-
console.log(`concurrent: ${String(current.concurrent)} daily: ${String(current.daily)} ${
|
|
33492
|
-
console.log(
|
|
33585
|
+
console.log(`concurrent: ${String(current.concurrent)} daily: ${String(current.daily)} ${chalk51.dim(`(${current.source})`)}`);
|
|
33586
|
+
console.log(chalk51.dim(`used today (${current.day}): ${String(current.usedToday)} / ${String(current.daily)}`));
|
|
33493
33587
|
}
|
|
33494
33588
|
});
|
|
33495
33589
|
return;
|
|
@@ -33497,7 +33591,7 @@ AI Agent Directive:
|
|
|
33497
33591
|
});
|
|
33498
33592
|
limits.command("set").description("Set the workspace's run-concurrency and/or daily-run caps").option("--concurrent <n>", `Runs in flight at once (${String(WORKSPACE_LIMIT_BOUNDS.concurrent.min)}–${String(WORKSPACE_LIMIT_BOUNDS.concurrent.max)})`).option("--daily <n>", `Runs started per UTC day (${String(WORKSPACE_LIMIT_BOUNDS.daily.min)}–${String(WORKSPACE_LIMIT_BOUNDS.daily.max)})`).addHelpText("after", `
|
|
33499
33593
|
Examples:
|
|
33500
|
-
${
|
|
33594
|
+
${chalk51.dim("$")} mutagent gateway admin limits set --concurrent 5 --daily 100
|
|
33501
33595
|
|
|
33502
33596
|
Admins only (workspace admin, or org owner/admin) — anyone else is refused.
|
|
33503
33597
|
Pass one or both of --concurrent / --daily; the other stays unchanged.
|
|
@@ -33531,7 +33625,7 @@ AI Agent Directive:
|
|
|
33531
33625
|
const updated = await setWorkspaceLimits(body);
|
|
33532
33626
|
printGatewayOk(isJson, updated, {
|
|
33533
33627
|
human: () => {
|
|
33534
|
-
console.log(
|
|
33628
|
+
console.log(chalk51.green(`✓ concurrent: ${String(updated.concurrent)} daily: ${String(updated.daily)}`));
|
|
33535
33629
|
}
|
|
33536
33630
|
});
|
|
33537
33631
|
return;
|
|
@@ -33568,12 +33662,12 @@ function createGatewayCommand(deps = {}) {
|
|
|
33568
33662
|
registerGatewayEventsCommands(gateway);
|
|
33569
33663
|
registerGatewayAdminCommands(gateway);
|
|
33570
33664
|
gateway.addHelpText("after", `
|
|
33571
|
-
${
|
|
33572
|
-
mutagent gateway ${
|
|
33665
|
+
${chalk52.yellow("Start here:")}
|
|
33666
|
+
mutagent gateway ${chalk52.dim("= status: connected, missing, next command")}
|
|
33573
33667
|
mutagent gateway status [--json]
|
|
33574
|
-
mutagent gateway doctor ${
|
|
33668
|
+
mutagent gateway doctor ${chalk52.dim("End-to-end check, with fixes")}
|
|
33575
33669
|
|
|
33576
|
-
${
|
|
33670
|
+
${chalk52.yellow("Configure:")}
|
|
33577
33671
|
mutagent gateway connect github|slack [--wait] [--open] [--attempt <id>]
|
|
33578
33672
|
mutagent gateway reconnect github|slack
|
|
33579
33673
|
mutagent gateway disconnect github|slack --force
|
|
@@ -33582,17 +33676,17 @@ ${chalk51.yellow("Configure:")}
|
|
|
33582
33676
|
mutagent gateway repos unlink owner/name --force
|
|
33583
33677
|
mutagent gateway repos grant-more
|
|
33584
33678
|
|
|
33585
|
-
${
|
|
33679
|
+
${chalk52.yellow("Configure — triggers (event → agent run):")}
|
|
33586
33680
|
mutagent gateway triggers
|
|
33587
33681
|
mutagent gateway triggers create --on <kind> [--repo owner/name | --no-repo] (--instruction "…" | --instruction-file f.md) [--name n]
|
|
33588
|
-
[--stage evaluate|diagnose|optimize] [--subject agent|skill|service:name,…] ${
|
|
33682
|
+
[--stage evaluate|diagnose|optimize] [--subject agent|skill|service:name,…] ${chalk52.dim("--subject: trace.threshold only")}
|
|
33589
33683
|
mutagent gateway triggers update <id> [--instruction "…" | --instruction-file f.md] [--name n] [--channel id…]
|
|
33590
33684
|
[--stage <stage>|none] [--subject <kind:names>|none]
|
|
33591
33685
|
mutagent gateway triggers show|enable|disable <id>
|
|
33592
33686
|
mutagent gateway triggers delete <id> --force
|
|
33593
33687
|
mutagent gateway triggers test <id> --event @sample.json
|
|
33594
33688
|
|
|
33595
|
-
${
|
|
33689
|
+
${chalk52.yellow("Configure — routines (schedule → agent run):")}
|
|
33596
33690
|
mutagent gateway routines
|
|
33597
33691
|
mutagent gateway routines create (--every "weekdays 09:00" | --cron "0 9 * * 1-5") --tz Europe/Berlin [--repo owner/name | --no-repo] (--instruction "…" | --instruction-file f.md) [--name n] [--stage <stage>]
|
|
33598
33692
|
mutagent gateway routines update <id> [(--every "…" | --cron "…") --tz zone] [--instruction "…"] [--name n] [--stage <stage>|none]
|
|
@@ -33600,7 +33694,7 @@ ${chalk51.yellow("Configure — routines (schedule → agent run):")}
|
|
|
33600
33694
|
mutagent gateway routines run-now <id> [--wait]
|
|
33601
33695
|
mutagent gateway routines delete <id> --force
|
|
33602
33696
|
|
|
33603
|
-
${
|
|
33697
|
+
${chalk52.yellow("Operate:")}
|
|
33604
33698
|
mutagent gateway test-run [--repo owner/name] [--wait] [--key k]
|
|
33605
33699
|
mutagent gateway runs [--status s] [--since 24h] [--trigger id|--routine id]
|
|
33606
33700
|
mutagent gateway runs show <eventId|runId>
|
|
@@ -33608,18 +33702,18 @@ ${chalk51.yellow("Operate:")}
|
|
|
33608
33702
|
mutagent gateway runs cancel <runId> --force [--reason "…"]
|
|
33609
33703
|
mutagent gateway emit <kind> [--key k] [--payload @file] [--wait]
|
|
33610
33704
|
mutagent gateway events list [--since 24h] [--cursor c] [--limit n]
|
|
33611
|
-
mutagent gateway events list --follow ${
|
|
33705
|
+
mutagent gateway events list --follow ${chalk52.dim("Live, until Ctrl-C (--json: one frame per line)")}
|
|
33612
33706
|
mutagent gateway notices list [--cursor c] [--limit n]
|
|
33613
33707
|
|
|
33614
|
-
${
|
|
33708
|
+
${chalk52.yellow("Admin:")}
|
|
33615
33709
|
mutagent gateway admin preflight [--workspace id]
|
|
33616
33710
|
mutagent gateway admin seed-apps
|
|
33617
33711
|
mutagent gateway admin limits
|
|
33618
33712
|
mutagent gateway admin limits set --concurrent N --daily N
|
|
33619
33713
|
|
|
33620
|
-
${
|
|
33621
|
-
Success: ${
|
|
33622
|
-
Failure: ${
|
|
33714
|
+
${chalk52.yellow("--json output and exit codes (the same as every mutagent command):")}
|
|
33715
|
+
Success: ${chalk52.bold("{ success: true, ok: true, data, next }")}
|
|
33716
|
+
Failure: ${chalk52.bold("{ success: false, ok: false, error, code, suggestedAction, _agentGuidance }")}
|
|
33623
33717
|
${EXIT_CODES_LINE}.
|
|
33624
33718
|
'code' is specific (RUN_STARTING, GITHUB_NOT_CONNECTED, CONFIRMATION_REQUIRED, …) —
|
|
33625
33719
|
branch on it, never on the error text. 'error' says what went wrong.
|
|
@@ -33635,7 +33729,7 @@ ${chalk51.yellow("--json output and exit codes (the same as every mutagent comma
|
|
|
33635
33729
|
'_agentGuidance.escalate' is present only when a person has to act (a browser
|
|
33636
33730
|
consent, a workspace admin, a Mutagent operator, a confirmation) and says who.
|
|
33637
33731
|
|
|
33638
|
-
${
|
|
33732
|
+
${chalk52.yellow("AI Agent Directive:")}
|
|
33639
33733
|
1. Run 'mutagent gateway --json' first, every time, and run what 'next' says.
|
|
33640
33734
|
2. On 'connect', a person opens 'data.signInUrl' first and signs in, then opens
|
|
33641
33735
|
'data.url' in that SAME browser — the callback only completes in a browser signed
|
|
@@ -33657,18 +33751,18 @@ ${chalk51.yellow("AI Agent Directive:")}
|
|
|
33657
33751
|
reaches is usable and links on create; one it cannot reach is refused with
|
|
33658
33752
|
REPOSITORY_INACCESSIBLE (fix: mutagent gateway repos grant-more).
|
|
33659
33753
|
${!hasCredentials() ? `
|
|
33660
|
-
` +
|
|
33754
|
+
` + chalk52.yellow(" Warning: Not authenticated. Run: mutagent login --browser") + `
|
|
33661
33755
|
` : ""}`);
|
|
33662
33756
|
return gateway;
|
|
33663
33757
|
}
|
|
33664
33758
|
|
|
33665
33759
|
// src/commands/reports/index.ts
|
|
33666
33760
|
import { Command as Command24 } from "commander";
|
|
33667
|
-
import
|
|
33761
|
+
import chalk55 from "chalk";
|
|
33668
33762
|
|
|
33669
33763
|
// src/commands/reports/manage.ts
|
|
33670
33764
|
import { writeFileSync as writeFileSync7 } from "fs";
|
|
33671
|
-
import
|
|
33765
|
+
import chalk53 from "chalk";
|
|
33672
33766
|
init_errors();
|
|
33673
33767
|
init_output();
|
|
33674
33768
|
|
|
@@ -33882,9 +33976,9 @@ function row(r) {
|
|
|
33882
33976
|
function registerList5(reports) {
|
|
33883
33977
|
reports.command("list").alias("ls").description("Reports in the workspace, newest first").option("--subject <id>", "Only reports about this agent, skill or workflow").option("--kind <kind>", "Only this kind: diagnostics|discovery|evaluator|hitl").option("--run-id <id>", "Only reports from this run").option("--session-ref <ref>", "Only reports from this Helix session").option("--cursor <cursor>", "Continue from a previous page's nextCursor").addHelpText("after", `
|
|
33884
33978
|
Examples:
|
|
33885
|
-
${
|
|
33886
|
-
${
|
|
33887
|
-
${
|
|
33979
|
+
${chalk53.dim("$")} mutagent reports list
|
|
33980
|
+
${chalk53.dim("$")} mutagent reports list --kind evaluator --subject support-bot --json
|
|
33981
|
+
${chalk53.dim("$")} mutagent reports list --cursor <nextCursor> --json
|
|
33888
33982
|
|
|
33889
33983
|
Filters combine with AND. A page ends with nextCursor; pass it as --cursor for the next.
|
|
33890
33984
|
|
|
@@ -33906,20 +34000,20 @@ AI Agent Directive:
|
|
|
33906
34000
|
return;
|
|
33907
34001
|
}
|
|
33908
34002
|
if (page.reports.length === 0) {
|
|
33909
|
-
console.log(
|
|
34003
|
+
console.log(chalk53.gray("No reports."));
|
|
33910
34004
|
return;
|
|
33911
34005
|
}
|
|
33912
34006
|
new OutputFormatter("table").output(page.reports.map(row));
|
|
33913
34007
|
if (page.nextCursor !== null)
|
|
33914
|
-
console.log(
|
|
34008
|
+
console.log(chalk53.dim(`More: mutagent reports list --cursor ${page.nextCursor}`));
|
|
33915
34009
|
});
|
|
33916
34010
|
});
|
|
33917
34011
|
}
|
|
33918
34012
|
function registerShow4(reports) {
|
|
33919
34013
|
reports.command("show").description("A report with its render input; --html saves the published HTML").argument("<id>", "The report id (from reports list or push)").option("--html <file>", "Write the published HTML to this file").addHelpText("after", `
|
|
33920
34014
|
Examples:
|
|
33921
|
-
${
|
|
33922
|
-
${
|
|
34015
|
+
${chalk53.dim("$")} mutagent reports show rep_123
|
|
34016
|
+
${chalk53.dim("$")} mutagent reports show rep_123 --html report.html --json
|
|
33923
34017
|
|
|
33924
34018
|
The HTML is never printed; it is served as a file under a sandboxing CSP.
|
|
33925
34019
|
|
|
@@ -33946,21 +34040,21 @@ AI Agent Directive:
|
|
|
33946
34040
|
return;
|
|
33947
34041
|
}
|
|
33948
34042
|
const r = detail.report;
|
|
33949
|
-
console.log(
|
|
34043
|
+
console.log(chalk53.bold(r.title));
|
|
33950
34044
|
for (const [label, value2] of Object.entries({ ...row(r), session: detail.sessionRef ?? "", html: links.html })) {
|
|
33951
34045
|
if (label !== "title" && value2 !== "")
|
|
33952
34046
|
console.log(` ${label.padEnd(9)}${value2}`);
|
|
33953
34047
|
}
|
|
33954
34048
|
if (htmlFile !== undefined)
|
|
33955
|
-
console.log(
|
|
34049
|
+
console.log(chalk53.green(`✓ HTML written to ${htmlFile}`));
|
|
33956
34050
|
});
|
|
33957
34051
|
});
|
|
33958
34052
|
}
|
|
33959
34053
|
function registerReview(reports) {
|
|
33960
34054
|
reports.command("review").description("Mark a report reviewed (--undo: unreviewed)").argument("<id>", "The report id").option("--undo", "Mark it unreviewed instead").addHelpText("after", `
|
|
33961
34055
|
Examples:
|
|
33962
|
-
${
|
|
33963
|
-
${
|
|
34056
|
+
${chalk53.dim("$")} mutagent reports review rep_123
|
|
34057
|
+
${chalk53.dim("$")} mutagent reports review rep_123 --undo --json
|
|
33964
34058
|
|
|
33965
34059
|
AI Agent Directive:
|
|
33966
34060
|
A write: confirm with the user first. --json returns { success, report, _links,
|
|
@@ -33983,15 +34077,15 @@ AI Agent Directive:
|
|
|
33983
34077
|
echoDirectiveToStderr(directive);
|
|
33984
34078
|
return;
|
|
33985
34079
|
}
|
|
33986
|
-
console.log(
|
|
34080
|
+
console.log(chalk53.green(`✓ Report ${report.id} marked ${reviewed ? "reviewed" : "unreviewed"}: ${report.title}`));
|
|
33987
34081
|
});
|
|
33988
34082
|
});
|
|
33989
34083
|
}
|
|
33990
34084
|
function registerRetract(reports) {
|
|
33991
34085
|
reports.command("retract").description("Delete a report, its findings and its HTML").argument("<id>", "The report id").option("-f, --force", "Confirm the retract (required in every mode; never prompted for)").option("-y, --yes", "Same as --force").addHelpText("after", `
|
|
33992
34086
|
Examples:
|
|
33993
|
-
${
|
|
33994
|
-
${
|
|
34087
|
+
${chalk53.dim("$")} mutagent reports retract rep_123 --force
|
|
34088
|
+
${chalk53.dim("$")} mutagent reports retract rep_123 --force --json
|
|
33995
34089
|
|
|
33996
34090
|
Requires --force (or --yes) in every mode: a terminal, --json, --non-interactive or a
|
|
33997
34091
|
pipe is not consent, and nothing prompts. Without it the command refuses
|
|
@@ -34019,7 +34113,7 @@ AI Agent Directive:
|
|
|
34019
34113
|
echoDirectiveToStderr(directive);
|
|
34020
34114
|
return;
|
|
34021
34115
|
}
|
|
34022
|
-
console.log(
|
|
34116
|
+
console.log(chalk53.green(`✓ Retracted report ${id}`));
|
|
34023
34117
|
});
|
|
34024
34118
|
});
|
|
34025
34119
|
}
|
|
@@ -34032,7 +34126,7 @@ function registerReportsManage(reports) {
|
|
|
34032
34126
|
|
|
34033
34127
|
// src/commands/reports/push.ts
|
|
34034
34128
|
init_errors();
|
|
34035
|
-
import
|
|
34129
|
+
import chalk54 from "chalk";
|
|
34036
34130
|
import { ReportKind as SdkReportKind } from "@mutagent/sdk/models";
|
|
34037
34131
|
init_output();
|
|
34038
34132
|
|
|
@@ -34193,11 +34287,11 @@ Usage:
|
|
|
34193
34287
|
${PUSH_USAGE}
|
|
34194
34288
|
|
|
34195
34289
|
Examples:
|
|
34196
|
-
${
|
|
34197
|
-
${
|
|
34198
|
-
${
|
|
34199
|
-
${
|
|
34200
|
-
${
|
|
34290
|
+
${chalk54.dim("$")} helix-cli report publish runs/42/report.html runs/42/report.client.html
|
|
34291
|
+
${chalk54.dim("$")} mutagent reports push runs/42 --kind evaluator
|
|
34292
|
+
${chalk54.dim("$")} mutagent reports push runs/42/report.client.html --kind diagnostics --run-id run-42 --json
|
|
34293
|
+
${chalk54.dim("$")} mutagent reports push runs/42 --kind evaluator --replace
|
|
34294
|
+
${chalk54.dim("$")} mutagent reports push review/ --kind hitl
|
|
34201
34295
|
|
|
34202
34296
|
Kinds, and the helix-cli render kind each one comes from:
|
|
34203
34297
|
diagnosis → diagnostics · discover → discovery · eval → evaluator · review → hitl
|
|
@@ -34275,12 +34369,12 @@ AI Agent Directive:
|
|
|
34275
34369
|
return;
|
|
34276
34370
|
}
|
|
34277
34371
|
if (created)
|
|
34278
|
-
console.log(
|
|
34372
|
+
console.log(chalk54.green(`✓ Stored report ${report.id} (${report.kind}): ${report.title}`));
|
|
34279
34373
|
else if (replaced)
|
|
34280
|
-
console.log(
|
|
34374
|
+
console.log(chalk54.green(`✓ Replaced the content of report ${report.id} (${report.kind}): ${report.title}`));
|
|
34281
34375
|
else {
|
|
34282
|
-
console.log(
|
|
34283
|
-
console.log(
|
|
34376
|
+
console.log(chalk54.blue(`ℹ already stored (created: false): report ${report.id} for run ${report.runId ?? "—"} kept its first content.`));
|
|
34377
|
+
console.log(chalk54.dim(" Pass --replace to swap it."));
|
|
34284
34378
|
}
|
|
34285
34379
|
console.log(` HTML: ${links.html}`);
|
|
34286
34380
|
console.log(` Next: mutagent reports show ${report.id}`);
|
|
@@ -34295,11 +34389,11 @@ function createReportsCommand() {
|
|
|
34295
34389
|
registerReportsManage(reports);
|
|
34296
34390
|
reports.addHelpText("after", `
|
|
34297
34391
|
Examples:
|
|
34298
|
-
${
|
|
34299
|
-
${
|
|
34300
|
-
${
|
|
34301
|
-
${
|
|
34302
|
-
${
|
|
34392
|
+
${chalk55.dim("$")} ${PUSH_USAGE}
|
|
34393
|
+
${chalk55.dim("$")} mutagent reports list [--subject <id>] [--kind <kind>] [--run-id <id>] [--session-ref <ref>] [--cursor <c>]
|
|
34394
|
+
${chalk55.dim("$")} mutagent reports show <id> [--html <file>]
|
|
34395
|
+
${chalk55.dim("$")} mutagent reports review <id> [--undo]
|
|
34396
|
+
${chalk55.dim("$")} mutagent reports retract <id> --force
|
|
34303
34397
|
|
|
34304
34398
|
Kinds: diagnostics · discovery · evaluator · hitl
|
|
34305
34399
|
The workspace is the usual one: --workspace, MUTAGENT_WORKSPACE_ID or 'mutagent workspaces use'.
|
|
@@ -34316,7 +34410,7 @@ AI Agent Directive:
|
|
|
34316
34410
|
// src/commands/findings/index.ts
|
|
34317
34411
|
init_errors();
|
|
34318
34412
|
import { Command as Command25 } from "commander";
|
|
34319
|
-
import
|
|
34413
|
+
import chalk56 from "chalk";
|
|
34320
34414
|
import { FindingStatus } from "@mutagent/sdk/models";
|
|
34321
34415
|
|
|
34322
34416
|
// src/lib/findings-status.ts
|
|
@@ -34422,9 +34516,9 @@ function statusDirective(f, links) {
|
|
|
34422
34516
|
function registerList6(findings) {
|
|
34423
34517
|
findings.command("list").alias("ls").description("Findings in the workspace, newest first").option("--status <status>", "Only this status: open|in-diagnostics|resolved").option("--subject <id>", "Only findings about this agent, skill or workflow").option("--run-id <id>", "Only findings from this run").option("--report <id>", "Only findings from this report").addHelpText("after", `
|
|
34424
34518
|
Examples:
|
|
34425
|
-
${
|
|
34426
|
-
${
|
|
34427
|
-
${
|
|
34519
|
+
${chalk56.dim("$")} mutagent findings list
|
|
34520
|
+
${chalk56.dim("$")} mutagent findings list --status open --subject support-bot --json
|
|
34521
|
+
${chalk56.dim("$")} mutagent findings list --report rpt_123 --json
|
|
34428
34522
|
|
|
34429
34523
|
Filters combine with AND. The whole list comes back in one page.
|
|
34430
34524
|
|
|
@@ -34446,7 +34540,7 @@ AI Agent Directive:
|
|
|
34446
34540
|
return;
|
|
34447
34541
|
}
|
|
34448
34542
|
if (page.findings.length === 0) {
|
|
34449
|
-
console.log(
|
|
34543
|
+
console.log(chalk56.gray("No findings."));
|
|
34450
34544
|
return;
|
|
34451
34545
|
}
|
|
34452
34546
|
new OutputFormatter("table").output(page.findings.map(row2));
|
|
@@ -34456,8 +34550,8 @@ AI Agent Directive:
|
|
|
34456
34550
|
function registerSetStatus(findings) {
|
|
34457
34551
|
findings.command("set-status").description("Resolve or reopen a finding").argument("<id>", "The finding id (from findings list)").argument("<open|resolved>", "resolved to close it, open to reopen it").addHelpText("after", `
|
|
34458
34552
|
Examples:
|
|
34459
|
-
${
|
|
34460
|
-
${
|
|
34553
|
+
${chalk56.dim("$")} mutagent findings set-status fnd_123 resolved
|
|
34554
|
+
${chalk56.dim("$")} mutagent findings set-status fnd_123 open --json
|
|
34461
34555
|
|
|
34462
34556
|
The ladder: open → resolved, resolved → open, in-diagnostics → open or resolved.
|
|
34463
34557
|
in-diagnostics itself is set only by routing a finding to diagnostics, which also
|
|
@@ -34490,7 +34584,7 @@ AI Agent Directive:
|
|
|
34490
34584
|
echoDirectiveToStderr(directive);
|
|
34491
34585
|
return;
|
|
34492
34586
|
}
|
|
34493
|
-
console.log(
|
|
34587
|
+
console.log(chalk56.green(`✓ Finding ${finding.id} (${finding.criterion}) is ${finding.status}`));
|
|
34494
34588
|
console.log(` Report: ${links.report}`);
|
|
34495
34589
|
});
|
|
34496
34590
|
});
|
|
@@ -34501,8 +34595,8 @@ function createFindingsCommand() {
|
|
|
34501
34595
|
registerSetStatus(findings);
|
|
34502
34596
|
findings.addHelpText("after", `
|
|
34503
34597
|
Examples:
|
|
34504
|
-
${
|
|
34505
|
-
${
|
|
34598
|
+
${chalk56.dim("$")} mutagent findings list [--status <status>] [--subject <id>] [--run-id <id>] [--report <id>]
|
|
34599
|
+
${chalk56.dim("$")} mutagent findings set-status <id> <open|resolved>
|
|
34506
34600
|
|
|
34507
34601
|
Findings are created when an evaluator report is pushed: mutagent reports push <run> --kind evaluator
|
|
34508
34602
|
The workspace is the usual one: --workspace, MUTAGENT_WORKSPACE_ID or 'mutagent workspaces use'.
|
|
@@ -34518,7 +34612,7 @@ AI Agent Directive:
|
|
|
34518
34612
|
// src/commands/triage/index.ts
|
|
34519
34613
|
init_errors();
|
|
34520
34614
|
import { Command as Command26 } from "commander";
|
|
34521
|
-
import
|
|
34615
|
+
import chalk58 from "chalk";
|
|
34522
34616
|
import { FindingStatus as FindingStatus2 } from "@mutagent/sdk/models";
|
|
34523
34617
|
init_output();
|
|
34524
34618
|
|
|
@@ -34526,7 +34620,7 @@ init_output();
|
|
|
34526
34620
|
init_errors();
|
|
34527
34621
|
init_output();
|
|
34528
34622
|
import { readFileSync as readFileSync22 } from "fs";
|
|
34529
|
-
import
|
|
34623
|
+
import chalk57 from "chalk";
|
|
34530
34624
|
import { CreateTriageRequestSeverity, CreateTriageRequestSubjectKind, TriageSource } from "@mutagent/sdk/models";
|
|
34531
34625
|
|
|
34532
34626
|
// src/lib/triage-request.ts
|
|
@@ -34755,10 +34849,10 @@ async function ask() {
|
|
|
34755
34849
|
function registerTriageFile(triage) {
|
|
34756
34850
|
triage.command("file").description("File a problem about an agent, skill or workflow (preview, then send on consent)").option("--subject <id>", "REQUIRED: the agent, skill or workflow the problem is about").option("--title <text>", "REQUIRED: one line").option("--body <text|@file>", "REQUIRED: what happened, or @path to read it from a file").option("--repo <owner/name>", "The linked GitHub repository, as owner/name (sent as repository)").option("--subject-kind <kind>", "What the subject is: agent | skill | workflow | multi-agent-system").option("--severity <level>", "CRIT | HIGH | MED | LOW (any case); left out, none is stored").option("--source <source>", "Who is filing: chat (default) | trace-score | external | mention").option("-y, --yes", "Consent to send without a prompt (after the user agreed to the preview)").addHelpText("after", `
|
|
34757
34851
|
Examples:
|
|
34758
|
-
${
|
|
34759
|
-
${
|
|
34760
|
-
${
|
|
34761
|
-
${
|
|
34852
|
+
${chalk57.dim("$")} mutagent triage file --subject support-bot --title "Quotes the wrong refund window" --body "Told a customer 60 days; the policy is 30."
|
|
34853
|
+
${chalk57.dim("$")} mutagent triage file --subject support-bot --title "Refund window" --body @what-happened.md --severity high --json
|
|
34854
|
+
${chalk57.dim("$")} mutagent triage file --subject support-bot --subject-kind agent --repo acme/support-bot --title "Refund window" --body @what-happened.md --json
|
|
34855
|
+
${chalk57.dim("$")} mutagent triage file --subject support-bot --title "Refund window" --body @what-happened.md --severity high --yes --json
|
|
34762
34856
|
|
|
34763
34857
|
Nothing is sent without consent. The command first prints a preview of exactly what
|
|
34764
34858
|
will be sent (workspace, server, every field, the full body), then:
|
|
@@ -34796,7 +34890,7 @@ AI Agent Directive:
|
|
|
34796
34890
|
new OutputFormatter("json").output({ success: true, sent: false, consentRequired: true, request, preview, next });
|
|
34797
34891
|
return;
|
|
34798
34892
|
}
|
|
34799
|
-
console.log(
|
|
34893
|
+
console.log(chalk57.yellow(consent === "declined" ? "Not filed. Nothing was sent." : "Nothing was sent. To file it, re-run the same command with --yes."));
|
|
34800
34894
|
return;
|
|
34801
34895
|
}
|
|
34802
34896
|
let item;
|
|
@@ -34817,7 +34911,7 @@ AI Agent Directive:
|
|
|
34817
34911
|
echoDirectiveToStderr(directive);
|
|
34818
34912
|
return;
|
|
34819
34913
|
}
|
|
34820
|
-
console.log(
|
|
34914
|
+
console.log(chalk57.green(`✓ Filed triage item ${item.id} (${item.status}): ${item.title}`));
|
|
34821
34915
|
console.log(` API: ${links.api}`);
|
|
34822
34916
|
});
|
|
34823
34917
|
});
|
|
@@ -34839,8 +34933,8 @@ function row3(i) {
|
|
|
34839
34933
|
function registerList7(triage) {
|
|
34840
34934
|
triage.command("list").alias("ls").description("Triage items in the workspace, newest first").option("--status <status>", "Only this status: open|in-diagnostics|resolved").option("--subject <id>", "Only items about this agent, skill or workflow").addHelpText("after", `
|
|
34841
34935
|
Examples:
|
|
34842
|
-
${
|
|
34843
|
-
${
|
|
34936
|
+
${chalk58.dim("$")} mutagent triage list
|
|
34937
|
+
${chalk58.dim("$")} mutagent triage list --status open --subject support-bot --json
|
|
34844
34938
|
|
|
34845
34939
|
Filters combine with AND. The whole list comes back in one page.
|
|
34846
34940
|
|
|
@@ -34865,7 +34959,7 @@ AI Agent Directive:
|
|
|
34865
34959
|
return;
|
|
34866
34960
|
}
|
|
34867
34961
|
if (page.items.length === 0) {
|
|
34868
|
-
console.log(
|
|
34962
|
+
console.log(chalk58.gray("No triage items."));
|
|
34869
34963
|
return;
|
|
34870
34964
|
}
|
|
34871
34965
|
new OutputFormatter("table").output(page.items.map(row3));
|
|
@@ -34875,8 +34969,8 @@ AI Agent Directive:
|
|
|
34875
34969
|
function registerShow5(triage) {
|
|
34876
34970
|
triage.command("show").description("One triage item, with its body").argument("<id>", "The triage item id (from triage list or file)").addHelpText("after", `
|
|
34877
34971
|
Examples:
|
|
34878
|
-
${
|
|
34879
|
-
${
|
|
34972
|
+
${chalk58.dim("$")} mutagent triage show tri_123
|
|
34973
|
+
${chalk58.dim("$")} mutagent triage show tri_123 --json
|
|
34880
34974
|
|
|
34881
34975
|
AI Agent Directive:
|
|
34882
34976
|
--json returns { item, _links }. Reading is free. An unknown id is TRIAGE_NOT_FOUND (exit 1).
|
|
@@ -34893,7 +34987,7 @@ AI Agent Directive:
|
|
|
34893
34987
|
new OutputFormatter("json").output({ item, _links: triageLinks(item.id) });
|
|
34894
34988
|
return;
|
|
34895
34989
|
}
|
|
34896
|
-
console.log(
|
|
34990
|
+
console.log(chalk58.bold(`${item.id} ${item.title}`));
|
|
34897
34991
|
console.log(` status ${item.status}`);
|
|
34898
34992
|
console.log(` subject ${item.subject}${item.subjectKind ? ` (${item.subjectKind})` : ""}`);
|
|
34899
34993
|
console.log(` severity ${item.severity ?? "—"}`);
|
|
@@ -34911,8 +35005,8 @@ AI Agent Directive:
|
|
|
34911
35005
|
function registerSetStatus2(triage) {
|
|
34912
35006
|
triage.command("set-status").description("Resolve or reopen a triage item").argument("<id>", "The triage item id (from triage list)").argument("<open|resolved>", "resolved to close it, open to reopen it").addHelpText("after", `
|
|
34913
35007
|
Examples:
|
|
34914
|
-
${
|
|
34915
|
-
${
|
|
35008
|
+
${chalk58.dim("$")} mutagent triage set-status tri_123 resolved
|
|
35009
|
+
${chalk58.dim("$")} mutagent triage set-status tri_123 open --json
|
|
34916
35010
|
|
|
34917
35011
|
The ladder is the findings one: open → resolved, resolved → open, in-diagnostics → open
|
|
34918
35012
|
or resolved. in-diagnostics itself is set only by routing an item to diagnostics, which
|
|
@@ -34950,7 +35044,7 @@ AI Agent Directive:
|
|
|
34950
35044
|
echoDirectiveToStderr(directive);
|
|
34951
35045
|
return;
|
|
34952
35046
|
}
|
|
34953
|
-
console.log(
|
|
35047
|
+
console.log(chalk58.green(`✓ Triage item ${item.id} (${item.title}) is ${item.status}`));
|
|
34954
35048
|
});
|
|
34955
35049
|
});
|
|
34956
35050
|
}
|
|
@@ -34962,10 +35056,10 @@ function createTriageCommand() {
|
|
|
34962
35056
|
registerSetStatus2(triage);
|
|
34963
35057
|
triage.addHelpText("after", `
|
|
34964
35058
|
Examples:
|
|
34965
|
-
${
|
|
34966
|
-
${
|
|
34967
|
-
${
|
|
34968
|
-
${
|
|
35059
|
+
${chalk58.dim("$")} mutagent triage file --subject <id> --title "<one line>" --body "<text>|@file" [--subject-kind <kind>] [--repo <owner/name>] [--severity <level>] [--source <source>] [--yes]
|
|
35060
|
+
${chalk58.dim("$")} mutagent triage list [--status <status>] [--subject <id>]
|
|
35061
|
+
${chalk58.dim("$")} mutagent triage show <id>
|
|
35062
|
+
${chalk58.dim("$")} mutagent triage set-status <id> <open|resolved>
|
|
34969
35063
|
|
|
34970
35064
|
There is no delete: the server keeps every item, so an item is resolved, not removed.
|
|
34971
35065
|
The workspace is the usual one: --workspace, MUTAGENT_WORKSPACE_ID or 'mutagent workspaces use'.
|
|
@@ -34981,11 +35075,11 @@ AI Agent Directive:
|
|
|
34981
35075
|
|
|
34982
35076
|
// src/commands/inbox/index.ts
|
|
34983
35077
|
import { Command as Command27 } from "commander";
|
|
34984
|
-
import
|
|
35078
|
+
import chalk60 from "chalk";
|
|
34985
35079
|
init_output();
|
|
34986
35080
|
|
|
34987
35081
|
// src/commands/inbox/list.ts
|
|
34988
|
-
import
|
|
35082
|
+
import chalk59 from "chalk";
|
|
34989
35083
|
init_output();
|
|
34990
35084
|
|
|
34991
35085
|
// src/commands/inbox/shared.ts
|
|
@@ -35046,10 +35140,10 @@ function inboxError(error3) {
|
|
|
35046
35140
|
|
|
35047
35141
|
// src/commands/inbox/list.ts
|
|
35048
35142
|
function printItem(item) {
|
|
35049
|
-
const mark = item.read ? " " :
|
|
35050
|
-
const action = item.needsAction ?
|
|
35143
|
+
const mark = item.read ? " " : chalk59.cyan("●");
|
|
35144
|
+
const action = item.needsAction ? chalk59.yellow(" needs action") : "";
|
|
35051
35145
|
const where = item.projectPath ?? "—";
|
|
35052
|
-
console.log(`${mark} ${item.id} ${
|
|
35146
|
+
console.log(`${mark} ${item.id} ${chalk59.dim(item.kind)} ${item.title} ${chalk59.dim(where)} ${chalk59.dim(new Date(item.ts).toISOString())}${action}`);
|
|
35053
35147
|
}
|
|
35054
35148
|
function unreadLine(list) {
|
|
35055
35149
|
const byProject = Object.entries(list.unreadByProject).filter(([, n]) => n > 0).map(([project, n]) => `${project === "" ? "(no repository)" : project}: ${String(n)}`);
|
|
@@ -35058,9 +35152,9 @@ function unreadLine(list) {
|
|
|
35058
35152
|
function registerInboxList(inbox) {
|
|
35059
35153
|
inbox.command("list").alias("ls").description("Your inbox items, newest first").option("--limit <n>", "Items per page, 1 to 100 (server default 50)").option("--cursor <cursor>", "The next page: the nextCursor a previous list returned").addHelpText("after", `
|
|
35060
35154
|
Examples:
|
|
35061
|
-
${
|
|
35062
|
-
${
|
|
35063
|
-
${
|
|
35155
|
+
${chalk59.dim("$")} mutagent inbox list
|
|
35156
|
+
${chalk59.dim("$")} mutagent inbox list --limit 20 --json
|
|
35157
|
+
${chalk59.dim("$")} mutagent inbox list --cursor <nextCursor> --json
|
|
35064
35158
|
|
|
35065
35159
|
The read flag and the unread counts are yours: read state is per user. unread and
|
|
35066
35160
|
unreadByProject count every unread item, not just this page. A cursor the server did
|
|
@@ -35099,7 +35193,7 @@ AI Agent Directive:
|
|
|
35099
35193
|
return;
|
|
35100
35194
|
}
|
|
35101
35195
|
if (list.items.length === 0) {
|
|
35102
|
-
console.log(
|
|
35196
|
+
console.log(chalk59.gray("Inbox is empty."));
|
|
35103
35197
|
return;
|
|
35104
35198
|
}
|
|
35105
35199
|
for (const item of list.items)
|
|
@@ -35107,7 +35201,7 @@ AI Agent Directive:
|
|
|
35107
35201
|
console.log("");
|
|
35108
35202
|
console.log(unreadLine(list));
|
|
35109
35203
|
if (next[0] !== undefined)
|
|
35110
|
-
console.log(
|
|
35204
|
+
console.log(chalk59.dim(`More: ${next[0]}`));
|
|
35111
35205
|
});
|
|
35112
35206
|
});
|
|
35113
35207
|
}
|
|
@@ -35116,8 +35210,8 @@ AI Agent Directive:
|
|
|
35116
35210
|
function registerRead(inbox) {
|
|
35117
35211
|
inbox.command("read").description("Mark one inbox item read").argument("<id>", "The inbox item id (from inbox list)").addHelpText("after", `
|
|
35118
35212
|
Examples:
|
|
35119
|
-
${
|
|
35120
|
-
${
|
|
35213
|
+
${chalk60.dim("$")} mutagent inbox read ibx_123
|
|
35214
|
+
${chalk60.dim("$")} mutagent inbox read ibx_123 --json
|
|
35121
35215
|
|
|
35122
35216
|
Marks the item read for you only; other members keep their own read state.
|
|
35123
35217
|
Idempotent: an item already read stays read and the command succeeds.
|
|
@@ -35148,15 +35242,15 @@ AI Agent Directive:
|
|
|
35148
35242
|
echoDirectiveToStderr(directive);
|
|
35149
35243
|
return;
|
|
35150
35244
|
}
|
|
35151
|
-
console.log(
|
|
35245
|
+
console.log(chalk60.green(`✓ Marked ${id} read`));
|
|
35152
35246
|
});
|
|
35153
35247
|
});
|
|
35154
35248
|
}
|
|
35155
35249
|
function registerReadAll(inbox) {
|
|
35156
35250
|
inbox.command("read-all").description("Mark every inbox item read").addHelpText("after", `
|
|
35157
35251
|
Examples:
|
|
35158
|
-
${
|
|
35159
|
-
${
|
|
35252
|
+
${chalk60.dim("$")} mutagent inbox read-all
|
|
35253
|
+
${chalk60.dim("$")} mutagent inbox read-all --json
|
|
35160
35254
|
|
|
35161
35255
|
Marks every item in this workspace read for you only; other members keep their own
|
|
35162
35256
|
read state. Idempotent. Nothing is deleted, so it takes no force flag and never
|
|
@@ -35188,7 +35282,7 @@ AI Agent Directive:
|
|
|
35188
35282
|
echoDirectiveToStderr(directive);
|
|
35189
35283
|
return;
|
|
35190
35284
|
}
|
|
35191
|
-
console.log(
|
|
35285
|
+
console.log(chalk60.green("✓ Marked every inbox item read"));
|
|
35192
35286
|
});
|
|
35193
35287
|
});
|
|
35194
35288
|
}
|
|
@@ -35199,9 +35293,9 @@ function createInboxCommand() {
|
|
|
35199
35293
|
registerReadAll(inbox);
|
|
35200
35294
|
inbox.addHelpText("after", `
|
|
35201
35295
|
Examples:
|
|
35202
|
-
${
|
|
35203
|
-
${
|
|
35204
|
-
${
|
|
35296
|
+
${chalk60.dim("$")} mutagent inbox list [--limit <n>] [--cursor <cursor>]
|
|
35297
|
+
${chalk60.dim("$")} mutagent inbox read <id>
|
|
35298
|
+
${chalk60.dim("$")} mutagent inbox read-all
|
|
35205
35299
|
|
|
35206
35300
|
Items come from findings, reports, session status, approvals, routines and triggers.
|
|
35207
35301
|
Read state is yours alone. There is no delete: the server expires old items itself.
|
|
@@ -35217,13 +35311,13 @@ AI Agent Directive:
|
|
|
35217
35311
|
|
|
35218
35312
|
// src/commands/integrations/index.ts
|
|
35219
35313
|
import { Command as Command28 } from "commander";
|
|
35220
|
-
import
|
|
35314
|
+
import chalk63 from "chalk";
|
|
35221
35315
|
|
|
35222
35316
|
// src/commands/integrations/pulls.ts
|
|
35223
35317
|
init_errors();
|
|
35224
35318
|
import { accessSync as accessSync5, closeSync as closeSync2, constants as constants5, openSync as openSync2, rmSync as rmSync3, writeSync } from "fs";
|
|
35225
35319
|
import { dirname as dirname10, resolve as resolve11 } from "path";
|
|
35226
|
-
import
|
|
35320
|
+
import chalk61 from "chalk";
|
|
35227
35321
|
|
|
35228
35322
|
// src/lib/integration-sources-input.ts
|
|
35229
35323
|
init_errors();
|
|
@@ -35754,9 +35848,9 @@ function pullNext(id, p) {
|
|
|
35754
35848
|
function registerPull(sources) {
|
|
35755
35849
|
sources.command("pull").description("Start a pull of a source's traces into UniTF on the server").argument("<id>", "The source id").option("--since <time>", "Window start, ISO-8601 (omit for open)").option("--until <time>", "Window end, ISO-8601 (omit for open)").option("--limit <n>", "At most this many traces, 1-5000 (server default 500)").option("--agent-name <name>", "Only traces of this agent").option("--session-id <id>", "Only traces of this session").option("--tag <tag>", "Only traces with this tag (repeatable, at most 20)", (v, acc = []) => [...acc, v]).addHelpText("after", `
|
|
35756
35850
|
Examples:
|
|
35757
|
-
${
|
|
35758
|
-
${
|
|
35759
|
-
${
|
|
35851
|
+
${chalk61.dim("$")} ${SOURCES2} pull src_123
|
|
35852
|
+
${chalk61.dim("$")} ${SOURCES2} pull src_123 --since 2026-09-01T00:00:00Z --until 2026-09-02T00:00:00Z --limit 1000
|
|
35853
|
+
${chalk61.dim("$")} ${SOURCES2} pull src_123 --agent-name support-bot --tag prod --tag eu --json
|
|
35760
35854
|
|
|
35761
35855
|
Starts the pull and returns at once (status running). Poll it with pull-get; once it has
|
|
35762
35856
|
succeeded, read pull-manifest and pull-traces. One running pull per source. A throttled or
|
|
@@ -35785,7 +35879,7 @@ AI Agent Directive:
|
|
|
35785
35879
|
echoDirectiveToStderr(directive);
|
|
35786
35880
|
return;
|
|
35787
35881
|
}
|
|
35788
|
-
console.log(
|
|
35882
|
+
console.log(chalk61.green(`✓ Pull ${started.id} started (${started.status})`));
|
|
35789
35883
|
console.log(` Next: ${next[0] ?? ""}`);
|
|
35790
35884
|
});
|
|
35791
35885
|
});
|
|
@@ -35793,8 +35887,8 @@ AI Agent Directive:
|
|
|
35793
35887
|
function registerPulls(sources) {
|
|
35794
35888
|
sources.command("pulls").description("A source's pulls, newest first (at most 50; kept 90 days)").argument("<id>", "The source id").addHelpText("after", `
|
|
35795
35889
|
Examples:
|
|
35796
|
-
${
|
|
35797
|
-
${
|
|
35890
|
+
${chalk61.dim("$")} ${SOURCES2} pulls src_123
|
|
35891
|
+
${chalk61.dim("$")} ${SOURCES2} pulls src_123 --json
|
|
35798
35892
|
|
|
35799
35893
|
AI Agent Directive:
|
|
35800
35894
|
Reading is free. --json returns { pulls, count }.
|
|
@@ -35808,7 +35902,7 @@ AI Agent Directive:
|
|
|
35808
35902
|
return;
|
|
35809
35903
|
}
|
|
35810
35904
|
if (list.items.length === 0) {
|
|
35811
|
-
console.log(
|
|
35905
|
+
console.log(chalk61.gray(`No pulls. Start one: ${SOURCES2} pull ${id}`));
|
|
35812
35906
|
return;
|
|
35813
35907
|
}
|
|
35814
35908
|
new OutputFormatter("table").output(list.items.map((p) => ({
|
|
@@ -35824,8 +35918,8 @@ AI Agent Directive:
|
|
|
35824
35918
|
function registerPullGet(sources) {
|
|
35825
35919
|
sources.command("pull-get").description("One pull: its status, counts and coverage").argument("<id>", "The source id").argument("<pullId>", "The pull id (from pull or pulls)").addHelpText("after", `
|
|
35826
35920
|
Examples:
|
|
35827
|
-
${
|
|
35828
|
-
${
|
|
35921
|
+
${chalk61.dim("$")} ${SOURCES2} pull-get src_123 pull_456
|
|
35922
|
+
${chalk61.dim("$")} ${SOURCES2} pull-get src_123 pull_456 --json
|
|
35829
35923
|
|
|
35830
35924
|
AI Agent Directive:
|
|
35831
35925
|
Reading is free: poll it while status is running. --json returns { pull, note, next, _links }.
|
|
@@ -35839,7 +35933,7 @@ AI Agent Directive:
|
|
|
35839
35933
|
new OutputFormatter("json").output({ pull: pullView(p), note, next, _links: pullLinks(id, pullId) });
|
|
35840
35934
|
return;
|
|
35841
35935
|
}
|
|
35842
|
-
console.log(`${
|
|
35936
|
+
console.log(`${chalk61.bold(p.id)} ${p.status} ${String(p.traces)} traces`);
|
|
35843
35937
|
if (p.truncated)
|
|
35844
35938
|
console.log(` truncated: ${p.truncationCause ?? "yes"}`);
|
|
35845
35939
|
if (p.dropped > 0)
|
|
@@ -35853,8 +35947,8 @@ AI Agent Directive:
|
|
|
35853
35947
|
function registerPullManifest(sources) {
|
|
35854
35948
|
sources.command("pull-manifest").description("A pull's unitf@0.1 manifest: what the JSONL holds and how completely").argument("<id>", "The source id").argument("<pullId>", "The pull id").addHelpText("after", `
|
|
35855
35949
|
Examples:
|
|
35856
|
-
${
|
|
35857
|
-
${
|
|
35950
|
+
${chalk61.dim("$")} ${SOURCES2} pull-manifest src_123 pull_456
|
|
35951
|
+
${chalk61.dim("$")} ${SOURCES2} pull-manifest src_123 pull_456 --json
|
|
35858
35952
|
|
|
35859
35953
|
Available once the pull has succeeded (INTEGRATION_PULL_NOT_READY before).
|
|
35860
35954
|
|
|
@@ -35871,12 +35965,12 @@ AI Agent Directive:
|
|
|
35871
35965
|
return;
|
|
35872
35966
|
}
|
|
35873
35967
|
const complete = manifest.coverage?.complete;
|
|
35874
|
-
console.log(`${
|
|
35968
|
+
console.log(`${chalk61.bold(manifest.format)} ${manifest.platform} ${String(manifest.count)} traces`);
|
|
35875
35969
|
console.log(` complete: ${complete === undefined ? "not recorded" : complete ? "yes" : "no"}`);
|
|
35876
35970
|
if (manifest.truncated)
|
|
35877
35971
|
console.log(` truncated: ${manifest.truncationReason ?? "yes"}`);
|
|
35878
35972
|
for (const w of manifest.warnings ?? [])
|
|
35879
|
-
console.log(
|
|
35973
|
+
console.log(chalk61.yellow(` ⚠ ${w}`));
|
|
35880
35974
|
});
|
|
35881
35975
|
});
|
|
35882
35976
|
}
|
|
@@ -35927,8 +36021,8 @@ var stdoutSink = {
|
|
|
35927
36021
|
function registerPullTraces(sources) {
|
|
35928
36022
|
sources.command("pull-traces").description("Stream a pull's UniTF JSONL to stdout, or to a file with --out").argument("<id>", "The source id").argument("<pullId>", "The pull id").option("-o, --out <file>", "Write the JSONL to this file instead of stdout").addHelpText("after", `
|
|
35929
36023
|
Examples:
|
|
35930
|
-
${
|
|
35931
|
-
${
|
|
36024
|
+
${chalk61.dim("$")} ${SOURCES2} pull-traces src_123 pull_456 > traces.jsonl
|
|
36025
|
+
${chalk61.dim("$")} ${SOURCES2} pull-traces src_123 pull_456 --out traces.jsonl --json
|
|
35932
36026
|
|
|
35933
36027
|
One UniTF 0.1 trace per line, streamed as it arrives. Available once the pull has succeeded.
|
|
35934
36028
|
--json: without --out, stdout is the JSONL unchanged (each line is already JSON; nothing
|
|
@@ -35965,7 +36059,7 @@ AI Agent Directive:
|
|
|
35965
36059
|
new OutputFormatter("json").output({ success: true, file: opts.out, bytes, lines: sink.lines, _links: pullLinks(id, pullId) });
|
|
35966
36060
|
return;
|
|
35967
36061
|
}
|
|
35968
|
-
console.log(
|
|
36062
|
+
console.log(chalk61.green(`✓ Wrote ${String(sink.lines)} traces (${String(bytes)} bytes) to ${opts.out}`));
|
|
35969
36063
|
});
|
|
35970
36064
|
});
|
|
35971
36065
|
}
|
|
@@ -35978,7 +36072,7 @@ function registerPullVerbs(sources) {
|
|
|
35978
36072
|
}
|
|
35979
36073
|
|
|
35980
36074
|
// src/commands/integrations/sources.ts
|
|
35981
|
-
import
|
|
36075
|
+
import chalk62 from "chalk";
|
|
35982
36076
|
init_known_secrets();
|
|
35983
36077
|
init_output();
|
|
35984
36078
|
var WRITE_DIRECTIVE = `AI Agent Directive:
|
|
@@ -36010,8 +36104,8 @@ function row4(s) {
|
|
|
36010
36104
|
function registerList8(sources) {
|
|
36011
36105
|
sources.command("list").alias("ls").description("Trace sources in the workspace, newest first").addHelpText("after", `
|
|
36012
36106
|
Examples:
|
|
36013
|
-
${
|
|
36014
|
-
${
|
|
36107
|
+
${chalk62.dim("$")} ${SOURCES2} list
|
|
36108
|
+
${chalk62.dim("$")} ${SOURCES2} list --json
|
|
36015
36109
|
|
|
36016
36110
|
Credentials are never returned; each source names its current ones by credentialRef.
|
|
36017
36111
|
A row marked read-only is OTLP ingest: it lists while OTLP traces arrive (latest trace
|
|
@@ -36029,7 +36123,7 @@ AI Agent Directive:
|
|
|
36029
36123
|
return;
|
|
36030
36124
|
}
|
|
36031
36125
|
if (all.length === 0) {
|
|
36032
|
-
console.log(
|
|
36126
|
+
console.log(chalk62.gray(`No trace sources. Connect one: ${SOURCES2} add langfuse --name <name> --public-key <pk> --secret-stdin`));
|
|
36033
36127
|
return;
|
|
36034
36128
|
}
|
|
36035
36129
|
new OutputFormatter("table").output(all.map(row4));
|
|
@@ -36039,10 +36133,10 @@ AI Agent Directive:
|
|
|
36039
36133
|
function registerAdd(sources) {
|
|
36040
36134
|
addCredentialOptions(sources.command("add").description("Connect a Langfuse or OpenObserve trace source (credentials are write-only)").argument("<kind>", "langfuse | openobserve").option("--name <name>", "A name, unique in the workspace (1-100 characters)").option("--host <url>", "Base URL: langfuse default https://cloud.langfuse.com; required for openobserve").option("--openobserve-org <org>", `openobserve: organization id, the model's org (default "default"); not the global --org`).option("--stream <stream>", 'openobserve: stream name (default "default")').option("--signal <signal>", "openobserve: events | spans (omit to detect it from the rows)")).addHelpText("after", `
|
|
36041
36135
|
Examples:
|
|
36042
|
-
${
|
|
36043
|
-
${
|
|
36044
|
-
${
|
|
36045
|
-
${
|
|
36136
|
+
${chalk62.dim("$")} pass show langfuse/sk | ${SOURCES2} add langfuse --name prod --public-key pk-lf-… --secret-stdin
|
|
36137
|
+
${chalk62.dim("$")} ${SOURCES2} add langfuse --name self-hosted --host https://langfuse.example.com --public-key pk-lf-… --secret-env LANGFUSE_SECRET_KEY
|
|
36138
|
+
${chalk62.dim("$")} ${SOURCES2} add openobserve --name oo --host https://api.openobserve.ai --openobserve-org acme --email ops@acme.com --secret-stdin
|
|
36139
|
+
${chalk62.dim("$")} ${SOURCES2} add openobserve --name oo --host http://oo.internal.example:5080 --secret-env OO_TOKEN --json
|
|
36046
36140
|
|
|
36047
36141
|
The secret (langfuse secret key; openobserve password with --email, or token without) comes
|
|
36048
36142
|
from its flag, from --secret-env <VAR>, or from stdin with --secret-stdin: exactly one. A flag
|
|
@@ -36066,7 +36160,7 @@ ${WRITE_DIRECTIVE}
|
|
|
36066
36160
|
echoDirectiveToStderr(directive);
|
|
36067
36161
|
return;
|
|
36068
36162
|
}
|
|
36069
|
-
console.log(
|
|
36163
|
+
console.log(chalk62.green(`✓ Added ${view.kind} source ${view.name} (id: ${view.id})`));
|
|
36070
36164
|
console.log(` Next: ${SOURCES2} test ${view.id}`);
|
|
36071
36165
|
});
|
|
36072
36166
|
});
|
|
@@ -36074,8 +36168,8 @@ ${WRITE_DIRECTIVE}
|
|
|
36074
36168
|
function registerRemove(sources) {
|
|
36075
36169
|
sources.command("remove").description("Delete a trace source, its credentials, its pulls and their output").argument("<id>", "The source id (from list)").option("-f, --force", "Required: confirms the delete (every mode; there is no prompt)").option("-y, --yes", "Same as --force").addHelpText("after", `
|
|
36076
36170
|
Examples:
|
|
36077
|
-
${
|
|
36078
|
-
${
|
|
36171
|
+
${chalk62.dim("$")} ${SOURCES2} remove src_123 --force
|
|
36172
|
+
${chalk62.dim("$")} ${SOURCES2} remove src_123 --force --json
|
|
36079
36173
|
|
|
36080
36174
|
Destructive: without -f/--force (or --yes) it refuses and sends nothing, in a terminal
|
|
36081
36175
|
or not, with --json or not. There is no confirmation prompt. Removing a source that is
|
|
@@ -36103,15 +36197,15 @@ AI Agent Directive:
|
|
|
36103
36197
|
echoDirectiveToStderr(directive);
|
|
36104
36198
|
return;
|
|
36105
36199
|
}
|
|
36106
|
-
console.log(
|
|
36200
|
+
console.log(chalk62.green(`✓ Removed trace source ${id}`));
|
|
36107
36201
|
});
|
|
36108
36202
|
});
|
|
36109
36203
|
}
|
|
36110
36204
|
function registerTest2(sources) {
|
|
36111
36205
|
sources.command("test").description("Test a source's connection with its stored credentials").argument("<id>", "The source id").addHelpText("after", `
|
|
36112
36206
|
Examples:
|
|
36113
|
-
${
|
|
36114
|
-
${
|
|
36207
|
+
${chalk62.dim("$")} ${SOURCES2} test src_123
|
|
36208
|
+
${chalk62.dim("$")} ${SOURCES2} test src_123 --json
|
|
36115
36209
|
|
|
36116
36210
|
One authenticated request from the server to the source; the outcome is recorded as the
|
|
36117
36211
|
source's last test. A failed test exits 1 and names the check that failed:
|
|
@@ -36135,16 +36229,16 @@ AI Agent Directive:
|
|
|
36135
36229
|
return;
|
|
36136
36230
|
}
|
|
36137
36231
|
const total = test.totalItems === null ? "" : ` (${String(test.totalItems)} traces reported)`;
|
|
36138
|
-
console.log(
|
|
36232
|
+
console.log(chalk62.green(`✓ Source ${id} connected${total}`));
|
|
36139
36233
|
});
|
|
36140
36234
|
});
|
|
36141
36235
|
}
|
|
36142
36236
|
function registerRotate(sources) {
|
|
36143
36237
|
addCredentialOptions(sources.command("rotate").description("Replace a source's credentials (the key version goes up, the last test is cleared)").argument("<id>", "The source id")).addHelpText("after", `
|
|
36144
36238
|
Examples:
|
|
36145
|
-
${
|
|
36146
|
-
${
|
|
36147
|
-
${
|
|
36239
|
+
${chalk62.dim("$")} pass show langfuse/sk | ${SOURCES2} rotate src_123 --public-key pk-lf-… --secret-stdin
|
|
36240
|
+
${chalk62.dim("$")} ${SOURCES2} rotate src_456 --secret-env OO_TOKEN --json
|
|
36241
|
+
${chalk62.dim("$")} ${SOURCES2} rotate src_456 --email ops@acme.com --secret-stdin
|
|
36148
36242
|
|
|
36149
36243
|
Takes the credentials the source's kind takes (it reads the source's kind first): langfuse
|
|
36150
36244
|
--public-key and a secret key; openobserve --email and a password, or a token. The secret
|
|
@@ -36170,7 +36264,7 @@ ${WRITE_DIRECTIVE}
|
|
|
36170
36264
|
echoDirectiveToStderr(directive);
|
|
36171
36265
|
return;
|
|
36172
36266
|
}
|
|
36173
|
-
console.log(
|
|
36267
|
+
console.log(chalk62.green(`✓ Rotated the credentials of ${view.name} (key version ${String(view.keyVersion)})`));
|
|
36174
36268
|
console.log(` Next: ${SOURCES2} test ${id}`);
|
|
36175
36269
|
});
|
|
36176
36270
|
});
|
|
@@ -36191,16 +36285,16 @@ function createSourcesCommand() {
|
|
|
36191
36285
|
registerPullVerbs(sources);
|
|
36192
36286
|
sources.addHelpText("after", `
|
|
36193
36287
|
Examples:
|
|
36194
|
-
${
|
|
36195
|
-
${
|
|
36196
|
-
${
|
|
36197
|
-
${
|
|
36198
|
-
${
|
|
36199
|
-
${
|
|
36200
|
-
${
|
|
36201
|
-
${
|
|
36202
|
-
${
|
|
36203
|
-
${
|
|
36288
|
+
${chalk63.dim("$")} ${SOURCES2} list
|
|
36289
|
+
${chalk63.dim("$")} pass show langfuse/sk | ${SOURCES2} add langfuse --name prod --public-key pk-lf-… --secret-stdin
|
|
36290
|
+
${chalk63.dim("$")} ${SOURCES2} test <id>
|
|
36291
|
+
${chalk63.dim("$")} ${SOURCES2} rotate <id> --public-key pk-lf-… --secret-env LANGFUSE_SECRET_KEY
|
|
36292
|
+
${chalk63.dim("$")} ${SOURCES2} remove <id> --force
|
|
36293
|
+
${chalk63.dim("$")} ${SOURCES2} pull <id> [--since <iso>] [--until <iso>] [--limit <n>] [--agent-name <n>] [--session-id <s>] [--tag <t>]…
|
|
36294
|
+
${chalk63.dim("$")} ${SOURCES2} pulls <id>
|
|
36295
|
+
${chalk63.dim("$")} ${SOURCES2} pull-get <id> <pullId>
|
|
36296
|
+
${chalk63.dim("$")} ${SOURCES2} pull-manifest <id> <pullId>
|
|
36297
|
+
${chalk63.dim("$")} ${SOURCES2} pull-traces <id> <pullId> [--out <file>]
|
|
36204
36298
|
|
|
36205
36299
|
Credentials are write-only: they are stored encrypted and no command ever prints them.
|
|
36206
36300
|
A secret comes from its flag, from --secret-env <VAR>, or from stdin with --secret-stdin.
|
|
@@ -36233,8 +36327,8 @@ Deploy targets are not available yet: the platform has not built them, so there
|
|
|
36233
36327
|
command for them. Messaging (GitHub, Slack, events, runs) lives in 'mutagent gateway'.
|
|
36234
36328
|
|
|
36235
36329
|
Examples:
|
|
36236
|
-
${
|
|
36237
|
-
${
|
|
36330
|
+
${chalk63.dim("$")} ${SOURCES2} list
|
|
36331
|
+
${chalk63.dim("$")} ${SOURCES2} --help
|
|
36238
36332
|
|
|
36239
36333
|
AI Agent Directive:
|
|
36240
36334
|
Start with '${SOURCES2} list --json'. Do not look for a targets command; there is none yet.
|
|
@@ -36392,7 +36486,7 @@ init_key_check();
|
|
|
36392
36486
|
init_config();
|
|
36393
36487
|
init_organization_scope();
|
|
36394
36488
|
init_output();
|
|
36395
|
-
import
|
|
36489
|
+
import chalk64 from "chalk";
|
|
36396
36490
|
|
|
36397
36491
|
// src/lib/brand.ts
|
|
36398
36492
|
var BRAND = {
|
|
@@ -36980,44 +37074,44 @@ A managed agent is an agent.md folder deployed with mutagent agent deploy.
|
|
|
36980
37074
|
});
|
|
36981
37075
|
program.addHelpText("beforeAll", () => renderBanner());
|
|
36982
37076
|
program.addHelpText("after", `
|
|
36983
|
-
${
|
|
37077
|
+
${chalk64.yellow("Get started:")}
|
|
36984
37078
|
1. mutagent login
|
|
36985
|
-
${
|
|
37079
|
+
${chalk64.dim("Sign in: in the browser, or with MUTAGENT_API_KEY set")}
|
|
36986
37080
|
2. mutagent providers add --provider openai --name "My OpenAI" --api-key-stdin < key.txt
|
|
36987
|
-
${
|
|
37081
|
+
${chalk64.dim("Add your LLM provider key, read from stdin (mutagent providers mirror copies your local Helix logins instead)")}
|
|
36988
37082
|
3. mutagent env set staging GREETING=hello --secrets-from-file .env.secrets
|
|
36989
|
-
${
|
|
37083
|
+
${chalk64.dim("Create an Environment: the variables and secrets a sandbox gets")}
|
|
36990
37084
|
4. mutagent helix --env staging -p "<task>"
|
|
36991
|
-
${
|
|
36992
|
-
${
|
|
36993
|
-
|
|
36994
|
-
${
|
|
36995
|
-
mutagent agent deploy <agent.md> ${
|
|
36996
|
-
mutagent helix agent @<slug> -p "<task>" ${
|
|
36997
|
-
mutagent agent --help ${
|
|
36998
|
-
|
|
36999
|
-
${
|
|
37000
|
-
mutagent workspaces use <name> ${
|
|
37001
|
-
mutagent workspaces current ${
|
|
37002
|
-
mutagent workspaces list ${
|
|
37003
|
-
--workspace <name|id> ${
|
|
37004
|
-
mutagent login --org <slug> ${
|
|
37005
|
-
mutagent providers list ${
|
|
37006
|
-
mutagent helix models ${
|
|
37007
|
-
mutagent env list ${
|
|
37008
|
-
mutagent usage ${
|
|
37009
|
-
|
|
37010
|
-
${
|
|
37011
|
-
MUTAGENT_API_KEY=mg_live_... ${
|
|
37012
|
-
--json ${
|
|
37013
|
-
--non-interactive ${
|
|
37014
|
-
-v, --version ${
|
|
37015
|
-
|
|
37016
|
-
${
|
|
37085
|
+
${chalk64.dim("Run Helix on the task in a cloud sandbox and print its answer")}
|
|
37086
|
+
${chalk64.dim("To run Helix on this machine instead: mutagent install helix installs the standalone binary")}
|
|
37087
|
+
|
|
37088
|
+
${chalk64.yellow("Managed agents:")}
|
|
37089
|
+
mutagent agent deploy <agent.md> ${chalk64.dim("Check, upload and activate an agent.md folder (--env names the Environment whose slot is used)")}
|
|
37090
|
+
mutagent helix agent @<slug> -p "<task>" ${chalk64.dim("Run a managed agent in the cloud")}
|
|
37091
|
+
mutagent agent --help ${chalk64.dim("check, pack, run, deploy, activate, list, inspect, retire")}
|
|
37092
|
+
|
|
37093
|
+
${chalk64.yellow("Workspace:")}
|
|
37094
|
+
mutagent workspaces use <name> ${chalk64.dim("Choose the workspace every later command works in")}
|
|
37095
|
+
mutagent workspaces current ${chalk64.dim("The key's scope, organization and the verified workspace")}
|
|
37096
|
+
mutagent workspaces list ${chalk64.dim("Your workspaces in the key's organization")}
|
|
37097
|
+
--workspace <name|id> ${chalk64.dim("One command in another workspace (then MUTAGENT_WORKSPACE_ID, then the selection)")}
|
|
37098
|
+
mutagent login --org <slug> ${chalk64.dim("Sign in for another organization")}
|
|
37099
|
+
mutagent providers list ${chalk64.dim("LLM providers in the workspace")}
|
|
37100
|
+
mutagent helix models ${chalk64.dim("Models Helix can use in the cloud, and the workspace default model")}
|
|
37101
|
+
mutagent env list ${chalk64.dim("Environments: variables and secrets for tools")}
|
|
37102
|
+
mutagent usage ${chalk64.dim("Count the workspace's LLM providers and your workspaces")}
|
|
37103
|
+
|
|
37104
|
+
${chalk64.yellow("Automation:")}
|
|
37105
|
+
MUTAGENT_API_KEY=mg_live_... ${chalk64.dim("Sign in without a browser (or --api-key <key>)")}
|
|
37106
|
+
--json ${chalk64.dim("Structured output")}
|
|
37107
|
+
--non-interactive ${chalk64.dim("No sign-in method or consent prompts (also when CI=true or stdin is not a terminal); a first sign-in in a terminal ends with a menu unless --json")}
|
|
37108
|
+
-v, --version ${chalk64.dim("CLI version (only before a subcommand)")}
|
|
37109
|
+
|
|
37110
|
+
${chalk64.yellow("Report a problem:")}
|
|
37017
37111
|
mutagent feedback send "<what happened>" --category cli
|
|
37018
|
-
${
|
|
37112
|
+
${chalk64.dim("--category accepts: cli | helix | stage:<spec|build|evaluate|diagnose|optimize>")}
|
|
37019
37113
|
|
|
37020
|
-
${
|
|
37114
|
+
${chalk64.yellow("AI Agent Directive:")}
|
|
37021
37115
|
Install the skill first: mutagent skills install (.claude/skills/mutagent-cli/SKILL.md).
|
|
37022
37116
|
It holds the full workflows. These rules apply to every command:
|
|
37023
37117
|
1. Sign in: with MUTAGENT_API_KEY set, run mutagent login --json. To help a user sign in,
|
|
@@ -37033,7 +37127,7 @@ ${chalk63.yellow("AI Agent Directive:")}
|
|
|
37033
37127
|
6. Ask the user through your own question tool. With --json only mutagent login can prompt, in a terminal; pass --browser or set MUTAGENT_API_KEY.
|
|
37034
37128
|
7. Keep secrets off the command line: --api-key-stdin for an LLM provider key, --secrets-from-file for Environment secrets.
|
|
37035
37129
|
${!hasCredentials() ? `
|
|
37036
|
-
` +
|
|
37130
|
+
` + chalk64.yellow(" Not signed in: start with step 1, mutagent login.") + `
|
|
37037
37131
|
` : ""}`);
|
|
37038
37132
|
const rawArgs = rescopeProviderApiKeyFlag(argv);
|
|
37039
37133
|
if (isGlobalVersionFlag(rawArgs)) {
|
|
@@ -37109,4 +37203,4 @@ if (process.env.CLI_VERSION) {
|
|
|
37109
37203
|
}
|
|
37110
37204
|
runCli(process.argv.slice(2), cliVersion);
|
|
37111
37205
|
|
|
37112
|
-
//# debugId=
|
|
37206
|
+
//# debugId=D8F738AA79625F7864756E2164756E21
|