@mushi-mushi/cli 0.30.6 → 0.32.0
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/{chunk-YAF2NATT.js → chunk-3YMPNCJ4.js} +1 -1
- package/dist/{chunk-BNO37ZO5.js → chunk-7PSMATX3.js} +1 -1
- package/dist/chunk-MARVQVJC.js +8 -0
- package/dist/chunk-XIB5NTHP.js +10 -0
- package/dist/{connect-D7FYRBAP.js → connect-JWNAYQEU.js} +2 -2
- package/dist/{connect-YKI7VZMP.js → connect-MINIBKHX.js} +2 -2
- package/dist/index.js +134 -4
- package/dist/init.js +3 -3
- package/dist/{version-NJJQDMYO.js → version-AX72RMKE.js} +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-D7ZVFRYW.js +0 -10
- package/dist/chunk-QR6NCHXT.js +0 -8
|
@@ -6,10 +6,10 @@ import {
|
|
|
6
6
|
saveConfig,
|
|
7
7
|
savedSdkKeyFor,
|
|
8
8
|
waitForIngestReady
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-7PSMATX3.js";
|
|
10
10
|
import {
|
|
11
11
|
MUSHI_MCP_PIN_SPEC
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-MARVQVJC.js";
|
|
13
13
|
import {
|
|
14
14
|
detectFramework,
|
|
15
15
|
envVarsToWrite,
|
package/dist/index.js
CHANGED
|
@@ -54,11 +54,11 @@ import {
|
|
|
54
54
|
syncKeychainAfterKeyChange,
|
|
55
55
|
trySaveKeyToKeychain,
|
|
56
56
|
writeMcpServerEntry
|
|
57
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-3YMPNCJ4.js";
|
|
58
58
|
import {
|
|
59
59
|
MUSHI_CLI_VERSION,
|
|
60
60
|
MUSHI_MCP_PIN_SPEC
|
|
61
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-XIB5NTHP.js";
|
|
62
62
|
import {
|
|
63
63
|
CLOUD_API_ENDPOINT,
|
|
64
64
|
CLOUD_MCP_OAUTH_URL,
|
|
@@ -1546,7 +1546,7 @@ async function checkOnboardingStatus(config, _consoleBase, cwd, doFetch = global
|
|
|
1546
1546
|
}
|
|
1547
1547
|
async function checkVersionDrift(cwd, doFetch) {
|
|
1548
1548
|
const checks = [];
|
|
1549
|
-
const { MUSHI_CLI_VERSION: MUSHI_CLI_VERSION2 } = await import("./version-
|
|
1549
|
+
const { MUSHI_CLI_VERSION: MUSHI_CLI_VERSION2 } = await import("./version-AX72RMKE.js");
|
|
1550
1550
|
if (MUSHI_CLI_VERSION2 === "0.0.0-dev") return checks;
|
|
1551
1551
|
const parse2 = (v) => {
|
|
1552
1552
|
const m = v.replace(/^[~^]/, "").match(/^(\d+)\.(\d+)\.(\d+)/);
|
|
@@ -2470,7 +2470,7 @@ async function maybeOfferConnect(credentials, options, _consoleBase) {
|
|
|
2470
2470
|
if (p.isCancel(answer) || !answer) return;
|
|
2471
2471
|
const endpoint = resolveCloudEndpoint(options.endpoint);
|
|
2472
2472
|
try {
|
|
2473
|
-
const { runConnect: runConnect2 } = await import("./connect-
|
|
2473
|
+
const { runConnect: runConnect2 } = await import("./connect-JWNAYQEU.js");
|
|
2474
2474
|
const saved = loadConfig();
|
|
2475
2475
|
const result = await runConnect2(
|
|
2476
2476
|
{
|
|
@@ -4521,6 +4521,9 @@ Examples:
|
|
|
4521
4521
|
"--method <method>",
|
|
4522
4522
|
"GitHub merge method: squash (default), merge, or rebase",
|
|
4523
4523
|
"squash"
|
|
4524
|
+
).option(
|
|
4525
|
+
"--override",
|
|
4526
|
+
'Not available here: the CLI signs in with an API key, and only a person in the Mushi console can override an Opus "hold" (with a reason)'
|
|
4524
4527
|
).option("--json", "Machine-readable JSON output").action(async (fixId, opts) => {
|
|
4525
4528
|
const config = loadConfig();
|
|
4526
4529
|
if (!config.apiKey) {
|
|
@@ -4531,6 +4534,12 @@ Examples:
|
|
|
4531
4534
|
console.error("No endpoint configured. Run `mushi init`");
|
|
4532
4535
|
process.exit(1);
|
|
4533
4536
|
}
|
|
4537
|
+
if (opts.override) {
|
|
4538
|
+
console.error(
|
|
4539
|
+
'Overriding an Opus "hold" needs a person in the Mushi console: open the fix, read the findings, and choose Merge anyway with a reason. The CLI signs in with an API key, which cannot override (ADR 0030).'
|
|
4540
|
+
);
|
|
4541
|
+
process.exit(1);
|
|
4542
|
+
}
|
|
4534
4543
|
const method = opts.method;
|
|
4535
4544
|
if (!["squash", "merge", "rebase"].includes(method)) {
|
|
4536
4545
|
console.error("--method must be squash, merge, or rebase");
|
|
@@ -4545,6 +4554,9 @@ Examples:
|
|
|
4545
4554
|
console.log(JSON.stringify({ ok: false, error: result.error }, null, 2));
|
|
4546
4555
|
} else {
|
|
4547
4556
|
console.error("Merge failed:", result.error.message);
|
|
4557
|
+
if (result.error.code === "REVIEW_HOLD") {
|
|
4558
|
+
console.error(`Read the review: mushi fixes review ${fixId} --show. To merge anyway, override the hold in the Mushi console (with a reason).`);
|
|
4559
|
+
}
|
|
4548
4560
|
}
|
|
4549
4561
|
process.exit(1);
|
|
4550
4562
|
}
|
|
@@ -4558,6 +4570,46 @@ Examples:
|
|
|
4558
4570
|
} else {
|
|
4559
4571
|
console.log(`Merged successfully. Report status: ${data.reportStatus ?? "fixed"}`);
|
|
4560
4572
|
}
|
|
4573
|
+
if (data.review) {
|
|
4574
|
+
console.log(`${data.review.label}${data.review.overridden ? " (overridden)" : ""}`);
|
|
4575
|
+
}
|
|
4576
|
+
});
|
|
4577
|
+
function printReview(review) {
|
|
4578
|
+
console.log(review.label);
|
|
4579
|
+
if (review.reason) console.log(review.reason);
|
|
4580
|
+
if (review.summary) console.log(`
|
|
4581
|
+
${review.summary}`);
|
|
4582
|
+
for (const f of review.findings) {
|
|
4583
|
+
const where = f.file === "(general)" ? "" : ` ${f.file}${f.line ? `:${f.line}` : ""}`;
|
|
4584
|
+
console.log(` - ${f.severity}${where}: ${f.issue} Fix: ${f.suggested_fix}`);
|
|
4585
|
+
}
|
|
4586
|
+
for (const r of review.removesBehavior) console.log(` - removes: ${r}`);
|
|
4587
|
+
if (review.needsHumanDecision) console.log(`Needs your decision: ${review.needsHumanDecision}`);
|
|
4588
|
+
if (review.commentUrl) console.log(`On GitHub: ${review.commentUrl}`);
|
|
4589
|
+
}
|
|
4590
|
+
fixes.command("review <fixId>").description("Re-run the Opus review of a fix PR (ADR 0030), or show the current one with --show").option("--show", "Show the current review instead of starting a new one").option("--json", "Machine-readable JSON output").action(async (fixId, opts) => {
|
|
4591
|
+
const config = loadConfig();
|
|
4592
|
+
if (!config.apiKey) {
|
|
4593
|
+
console.error("Run `mushi login` first");
|
|
4594
|
+
process.exit(1);
|
|
4595
|
+
}
|
|
4596
|
+
if (!config.endpoint) {
|
|
4597
|
+
console.error("No endpoint configured. Run `mushi init`");
|
|
4598
|
+
process.exit(1);
|
|
4599
|
+
}
|
|
4600
|
+
const result = opts.show ? await apiCall(`/v1/admin/fixes/${fixId}/timeline`, config) : await apiCall(`/v1/admin/fixes/${fixId}/review`, config, { method: "POST" });
|
|
4601
|
+
if (!result.ok) {
|
|
4602
|
+
if (opts.json) console.log(JSON.stringify({ ok: false, error: result.error }, null, 2));
|
|
4603
|
+
else console.error(opts.show ? "Could not read the review:" : "Review not started:", result.error.message);
|
|
4604
|
+
process.exit(1);
|
|
4605
|
+
}
|
|
4606
|
+
const review = result.data?.review;
|
|
4607
|
+
if (opts.json) {
|
|
4608
|
+
console.log(JSON.stringify({ ok: true, review: review ?? null }, null, 2));
|
|
4609
|
+
return;
|
|
4610
|
+
}
|
|
4611
|
+
if (!opts.show) console.log("Review queued. It takes a few minutes; check with --show.");
|
|
4612
|
+
if (review) printReview(review);
|
|
4561
4613
|
});
|
|
4562
4614
|
fixes.command("refresh-ci <fixId>").description("Pull latest GitHub Actions check-run status for a fix attempt (on-demand ci-sync)").option("--json", "Machine-readable JSON output").action(async (fixId, opts) => {
|
|
4563
4615
|
const config = loadConfig();
|
|
@@ -5322,6 +5374,31 @@ Approve: mushi tdd approve <id>`);
|
|
|
5322
5374
|
});
|
|
5323
5375
|
}
|
|
5324
5376
|
|
|
5377
|
+
// src/spend-down.ts
|
|
5378
|
+
function wholeNumber(raw, flag, min, max) {
|
|
5379
|
+
const n = Number(raw);
|
|
5380
|
+
if (!Number.isInteger(n) || n < min || n > max) throw new Error(`${flag} must be a whole number from ${min} to ${max}`);
|
|
5381
|
+
return n;
|
|
5382
|
+
}
|
|
5383
|
+
function spendDownBody(flags) {
|
|
5384
|
+
if (flags.on && flags.off) throw new Error("Pass --on or --off, not both");
|
|
5385
|
+
const body = {};
|
|
5386
|
+
if (flags.on) body.enabled = true;
|
|
5387
|
+
if (flags.off) body.enabled = false;
|
|
5388
|
+
if (flags.expires !== void 0) body.creditsExpireAt = flags.expires;
|
|
5389
|
+
if (flags.model !== void 0) body.model = flags.model === "" ? null : flags.model;
|
|
5390
|
+
if (flags.perDay !== void 0) body.dailyLimit = wholeNumber(flags.perDay, "--per-day", 1, 200);
|
|
5391
|
+
if (flags.windowDays !== void 0) body.windowDays = wholeNumber(flags.windowDays, "--window-days", 1, 90);
|
|
5392
|
+
return Object.keys(body).length > 0 ? body : null;
|
|
5393
|
+
}
|
|
5394
|
+
function spendDownStatusLine(k) {
|
|
5395
|
+
const name = `${k.label ?? "(no label)"} ${k.keyHint ?? ""}`.trim();
|
|
5396
|
+
const expires = k.creditsExpireAt ? k.creditsExpireAt.slice(0, 10) : "not set";
|
|
5397
|
+
const model = k.model ?? "app default";
|
|
5398
|
+
const apps = k.projects.length > 0 ? k.projects.map((p3) => p3.name).join(", ") : "none";
|
|
5399
|
+
return `${name} [${k.scope}] ${k.state} \xB7 ${k.dispatchedToday}/${k.dailyLimit} today \xB7 credits expire ${expires} \xB7 model ${model} \xB7 pays for ${apps} \u2014 ${k.id}`;
|
|
5400
|
+
}
|
|
5401
|
+
|
|
5325
5402
|
// src/commands/keys.ts
|
|
5326
5403
|
function registerKeysCommands(program2) {
|
|
5327
5404
|
const keys = program2.command("keys").description("Manage API key pool (BYOK)");
|
|
@@ -5501,6 +5578,59 @@ function registerKeysCommands(program2) {
|
|
|
5501
5578
|
);
|
|
5502
5579
|
console.log(` ${res.data.validation.detail}`);
|
|
5503
5580
|
});
|
|
5581
|
+
keys.command("spend-down [key-id]").description(
|
|
5582
|
+
"Spend down expiring Cursor credits on open bugs (ADR 0028): show status, or set it for one key"
|
|
5583
|
+
).option("--on", "Turn spend-down on (needs --expires once)").option("--off", "Turn spend-down off").option("--expires <date>", "When the credits expire, YYYY-MM-DD").option("--model <spec>", "Cursor model, e.g. 'grok-4.7?reasoning_effort=xhigh&context=500k' ('' = app default)").option("--per-day <n>", "Fixes per day across the apps this key pays for (1-200)").option("--window-days <n>", "Start this many days before the credits expire (1-90)").option("--json", "Output as JSON (alias for -o json)").action(async (keyId, opts) => {
|
|
5584
|
+
const config = loadConfig();
|
|
5585
|
+
if (!config.apiKey || !config.projectId) {
|
|
5586
|
+
console.error("Run `mushi login` first");
|
|
5587
|
+
process.exit(1);
|
|
5588
|
+
}
|
|
5589
|
+
let body;
|
|
5590
|
+
try {
|
|
5591
|
+
body = spendDownBody(opts);
|
|
5592
|
+
} catch (err) {
|
|
5593
|
+
console.error(`Error: ${err.message}`);
|
|
5594
|
+
process.exit(1);
|
|
5595
|
+
}
|
|
5596
|
+
if (keyId && body) {
|
|
5597
|
+
const res2 = await apiCall(
|
|
5598
|
+
`/v1/admin/byok/keys/${encodeURIComponent(keyId)}/spend-down`,
|
|
5599
|
+
config,
|
|
5600
|
+
{ method: "PATCH", body: JSON.stringify(body) }
|
|
5601
|
+
);
|
|
5602
|
+
if (!res2.ok) {
|
|
5603
|
+
console.error(`Error: ${res2.error.message}`);
|
|
5604
|
+
process.exit(1);
|
|
5605
|
+
}
|
|
5606
|
+
console.log(
|
|
5607
|
+
`\u2713 Spend-down ${res2.data.enabled ? "on" : "off"}${res2.data.creditsExpireAt ? `, credits expire ${res2.data.creditsExpireAt.slice(0, 10)}` : ""} \u2014 id: ${res2.data.id}`
|
|
5608
|
+
);
|
|
5609
|
+
return;
|
|
5610
|
+
}
|
|
5611
|
+
if (keyId && !body) {
|
|
5612
|
+
console.error("Nothing to change: pass --on, --off, --expires, --model, --per-day or --window-days");
|
|
5613
|
+
process.exit(1);
|
|
5614
|
+
}
|
|
5615
|
+
const res = await apiCall(
|
|
5616
|
+
`/v1/admin/byok/spend-down?project_id=${encodeURIComponent(config.projectId)}`,
|
|
5617
|
+
config
|
|
5618
|
+
);
|
|
5619
|
+
if (!res.ok) {
|
|
5620
|
+
console.error(`Error: ${res.error.message}`);
|
|
5621
|
+
process.exit(1);
|
|
5622
|
+
}
|
|
5623
|
+
printResult(res.data, {
|
|
5624
|
+
json: opts.json,
|
|
5625
|
+
render(d) {
|
|
5626
|
+
if (d.keys.length === 0) {
|
|
5627
|
+
console.log("No Cursor key for this project. Add one with `mushi keys add --provider cursor`.");
|
|
5628
|
+
return;
|
|
5629
|
+
}
|
|
5630
|
+
for (const k of d.keys) console.log(spendDownStatusLine(k));
|
|
5631
|
+
}
|
|
5632
|
+
});
|
|
5633
|
+
});
|
|
5504
5634
|
keys.command("remove <key-id>").description("Permanently remove one pooled key and its Vault secret").action(async (keyId) => {
|
|
5505
5635
|
const config = loadConfig();
|
|
5506
5636
|
if (!config.apiKey || !config.projectId) {
|
package/dist/init.js
CHANGED
|
@@ -25,10 +25,10 @@ import {
|
|
|
25
25
|
saveConfig,
|
|
26
26
|
savedSdkKeyFor,
|
|
27
27
|
trySaveKeyToKeychain
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-7PSMATX3.js";
|
|
29
29
|
import {
|
|
30
30
|
MUSHI_CLI_VERSION
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-MARVQVJC.js";
|
|
32
32
|
import {
|
|
33
33
|
FRAMEWORKS,
|
|
34
34
|
detectFramework,
|
|
@@ -2058,7 +2058,7 @@ async function maybeOfferConnect(credentials, options, _consoleBase) {
|
|
|
2058
2058
|
if (p.isCancel(answer) || !answer) return;
|
|
2059
2059
|
const endpoint = resolveCloudEndpoint(options.endpoint);
|
|
2060
2060
|
try {
|
|
2061
|
-
const { runConnect } = await import("./connect-
|
|
2061
|
+
const { runConnect } = await import("./connect-MINIBKHX.js");
|
|
2062
2062
|
const saved = loadConfig();
|
|
2063
2063
|
const result = await runConnect(
|
|
2064
2064
|
{
|
package/dist/version.d.ts
CHANGED
|
@@ -14,6 +14,6 @@ declare const MUSHI_CLI_VERSION: string;
|
|
|
14
14
|
* setup refreshes the pin. Synced to packages/mcp/package.json by
|
|
15
15
|
* `scripts/sync-mcp-pin.mjs` — never hand-edit the version.
|
|
16
16
|
*/
|
|
17
|
-
declare const MUSHI_MCP_PIN_SPEC = "@mushi-mushi/mcp@0.
|
|
17
|
+
declare const MUSHI_MCP_PIN_SPEC = "@mushi-mushi/mcp@0.28.0";
|
|
18
18
|
|
|
19
19
|
export { MUSHI_CLI_VERSION, MUSHI_MCP_PIN_SPEC };
|
package/dist/version.js
CHANGED
package/package.json
CHANGED
package/dist/chunk-D7ZVFRYW.js
DELETED