@mushi-mushi/cli 0.34.0 → 0.34.1
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/README.md +3 -1
- package/dist/{chunk-OS2ZLURO.js → chunk-67WU4UYB.js} +1 -1
- package/dist/chunk-QI7DE6J3.js +8 -0
- package/dist/{chunk-VECP4KOK.js → chunk-VBEYT4RS.js} +1 -1
- package/dist/chunk-XXBGTUGX.js +10 -0
- package/dist/{connect-3UDYCZKF.js → connect-354QHAUQ.js} +2 -2
- package/dist/{connect-T5BBOIWS.js → connect-HZAHHWBI.js} +2 -2
- package/dist/index.js +70 -15
- package/dist/init.js +3 -3
- package/dist/{version-UVLMVFNO.js → version-MD563FA6.js} +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-CY2BHCA5.js +0 -8
- package/dist/chunk-FPVAQNHT.js +0 -10
package/README.md
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
The `mushi` command for [Mushi Mushi](https://github.com/kensaurus/mushi-mushi). Install the SDK in your app, connect your editor, then read bugs, dispatch fixes and merge them without leaving the terminal.
|
|
6
6
|
|
|
7
|
+
Docs: [CLI reference](https://kensaur.us/mushi-mushi/docs/sdks/cli)
|
|
8
|
+
|
|
7
9
|
```mermaid
|
|
8
10
|
flowchart LR
|
|
9
11
|
A["mushi init<br/>SDK in your app"] --> B["mushi setup<br/>editor reads diagnoses"] --> C["mushi reports<br/>see what broke"] --> D["mushi fix<br/>agent opens a draft PR"] --> E["mushi fixes merge"]
|
|
@@ -70,7 +72,7 @@ Other `init` flags: `--framework next`, `--cwd apps/web` (monorepos), `--endpoin
|
|
|
70
72
|
| `MUSHI_NO_UPDATE_CHECK=1` | Skip the "newer version" hint |
|
|
71
73
|
| `MUSHI_DEBUG=1` | Full stack traces on error |
|
|
72
74
|
|
|
73
|
-
Config lives in `~/.config/mushi/config.json
|
|
75
|
+
Config lives in `~/.config/mushi/config.json` (`%APPDATA%\mushi\config.json` on Windows, `$XDG_CONFIG_HOME/mushi/config.json` when that is set), written with mode `0o600` on macOS and Linux and an account-only ACL on Windows (a legacy `~/.mushirc` is auto-migrated). `--endpoint` must be `https://` except on localhost.
|
|
74
76
|
|
|
75
77
|
## Programmatic use
|
|
76
78
|
|
|
@@ -6,10 +6,10 @@ import {
|
|
|
6
6
|
saveConfig,
|
|
7
7
|
savedSdkKeyFor,
|
|
8
8
|
waitForIngestReady
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-67WU4UYB.js";
|
|
10
10
|
import {
|
|
11
11
|
MUSHI_MCP_PIN_SPEC
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-QI7DE6J3.js";
|
|
13
13
|
import {
|
|
14
14
|
detectFramework,
|
|
15
15
|
envVarsToWrite,
|
package/dist/index.js
CHANGED
|
@@ -57,11 +57,11 @@ import {
|
|
|
57
57
|
syncKeychainAfterKeyChange,
|
|
58
58
|
trySaveKeyToKeychain,
|
|
59
59
|
writeMcpServerEntry
|
|
60
|
-
} from "./chunk-
|
|
60
|
+
} from "./chunk-VBEYT4RS.js";
|
|
61
61
|
import {
|
|
62
62
|
MUSHI_CLI_VERSION,
|
|
63
63
|
MUSHI_MCP_PIN_SPEC
|
|
64
|
-
} from "./chunk-
|
|
64
|
+
} from "./chunk-XXBGTUGX.js";
|
|
65
65
|
import {
|
|
66
66
|
CLOUD_API_ENDPOINT,
|
|
67
67
|
CLOUD_MCP_OAUTH_URL,
|
|
@@ -1552,7 +1552,7 @@ async function checkOnboardingStatus(config, _consoleBase, cwd, doFetch = global
|
|
|
1552
1552
|
}
|
|
1553
1553
|
async function checkVersionDrift(cwd, doFetch) {
|
|
1554
1554
|
const checks = [];
|
|
1555
|
-
const { MUSHI_CLI_VERSION: MUSHI_CLI_VERSION2 } = await import("./version-
|
|
1555
|
+
const { MUSHI_CLI_VERSION: MUSHI_CLI_VERSION2 } = await import("./version-MD563FA6.js");
|
|
1556
1556
|
if (MUSHI_CLI_VERSION2 === "0.0.0-dev") return checks;
|
|
1557
1557
|
const parse2 = (v) => {
|
|
1558
1558
|
const m = v.replace(/^[~^]/, "").match(/^(\d+)\.(\d+)\.(\d+)/);
|
|
@@ -2476,7 +2476,7 @@ async function maybeOfferConnect(credentials, options, _consoleBase) {
|
|
|
2476
2476
|
if (p.isCancel(answer) || !answer) return;
|
|
2477
2477
|
const endpoint = resolveCloudEndpoint(options.endpoint);
|
|
2478
2478
|
try {
|
|
2479
|
-
const { runConnect: runConnect2 } = await import("./connect-
|
|
2479
|
+
const { runConnect: runConnect2 } = await import("./connect-HZAHHWBI.js");
|
|
2480
2480
|
const saved = loadConfig();
|
|
2481
2481
|
const result = await runConnect2(
|
|
2482
2482
|
{
|
|
@@ -13055,6 +13055,7 @@ import { createHash as createHash3 } from "crypto";
|
|
|
13055
13055
|
import { existsSync as existsSync7, mkdirSync as mkdirSync4, rmSync } from "fs";
|
|
13056
13056
|
import { homedir, tmpdir } from "os";
|
|
13057
13057
|
import { basename as basename3, join as join13 } from "path";
|
|
13058
|
+
import { stripVTControlCharacters } from "util";
|
|
13058
13059
|
var WORK_AGENT_KIND = "mcp";
|
|
13059
13060
|
var WORK_AGENT_TIMEOUT_MS = 30 * 6e4;
|
|
13060
13061
|
var PROMPT_MAX_CHARS = 4e4;
|
|
@@ -13212,6 +13213,32 @@ function prTitle(summary, reportId) {
|
|
|
13212
13213
|
return `fix: ${s.charAt(0).toLowerCase()}${s.slice(1)}${suffix}`;
|
|
13213
13214
|
}
|
|
13214
13215
|
var SUBJECT_MAX = 72;
|
|
13216
|
+
var BODY_LINE_MAX = 100;
|
|
13217
|
+
var FOOTER_LIKE = /^(?:[\w-]+(?:\([^)]*\))?!?:|BREAKING[ -]CHANGE\b)/i;
|
|
13218
|
+
function commitBody(...paragraphs) {
|
|
13219
|
+
const width = BODY_LINE_MAX - 2;
|
|
13220
|
+
return paragraphs.map((p4) => p4.replace(/\s+/g, " ").trim()).filter(Boolean).map((p4) => {
|
|
13221
|
+
const lines = [];
|
|
13222
|
+
let line = "";
|
|
13223
|
+
for (let word of p4.split(" ")) {
|
|
13224
|
+
while (word.length > width) {
|
|
13225
|
+
if (line) lines.push(line);
|
|
13226
|
+
line = "";
|
|
13227
|
+
lines.push(word.slice(0, width));
|
|
13228
|
+
word = word.slice(width);
|
|
13229
|
+
}
|
|
13230
|
+
if (!word) continue;
|
|
13231
|
+
if (!line) line = word;
|
|
13232
|
+
else if (line.length + 1 + word.length <= width) line += ` ${word}`;
|
|
13233
|
+
else {
|
|
13234
|
+
lines.push(line);
|
|
13235
|
+
line = word;
|
|
13236
|
+
}
|
|
13237
|
+
}
|
|
13238
|
+
if (line) lines.push(line);
|
|
13239
|
+
return lines.map((l) => FOOTER_LIKE.test(l) ? ` ${l}` : l).join("\n");
|
|
13240
|
+
}).join("\n\n");
|
|
13241
|
+
}
|
|
13215
13242
|
function agentEnv(base, emptyDir) {
|
|
13216
13243
|
const keep = ["PATH", "HOME", "USER", "LOGNAME", "LANG", "LC_ALL", "TERM", "SHELL", "TMPDIR", "TZ", "XDG_CONFIG_HOME", "XDG_DATA_HOME", "XDG_CACHE_HOME", "NODE_OPTIONS"];
|
|
13217
13244
|
const env = {};
|
|
@@ -13405,9 +13432,7 @@ async function workOne(api, detail, o) {
|
|
|
13405
13432
|
}
|
|
13406
13433
|
await git(wt, ["add", "-A"]);
|
|
13407
13434
|
const last = run.stdout.trim().split("\n").filter((l) => l.trim()).slice(-6).join(" ");
|
|
13408
|
-
await commitWithHooks(wt, ["--quiet", "-m", prTitle(detail.summary, detail.id), "-m", `Mushi report: ${detail.id}
|
|
13409
|
-
|
|
13410
|
-
Made by a local Cursor agent through \`mushi work\`.`], o.log);
|
|
13435
|
+
await commitWithHooks(wt, ["--quiet", "-m", prTitle(detail.summary, detail.id), "-m", commitBody(`Mushi report: ${detail.id}`, "Made by a local Cursor agent through `mushi work`.")], o.log);
|
|
13411
13436
|
const sha = await git(wt, ["rev-parse", "HEAD"]);
|
|
13412
13437
|
const numstat = await git(wt, ["diff", "--numstat", `origin/${base}`, "HEAD"]);
|
|
13413
13438
|
const files = [];
|
|
@@ -13492,9 +13517,7 @@ async function followUpOne(api, f, o) {
|
|
|
13492
13517
|
return { fixId: f.fixId, outcome: `no change: ${why || `cursor-agent exited ${run.code}`}` };
|
|
13493
13518
|
}
|
|
13494
13519
|
await git(wt, ["add", "-A"]);
|
|
13495
|
-
await commitWithHooks(wt, ["--quiet", "-m", `fix: address the Opus review (round ${claim.round})`, "-m",
|
|
13496
|
-
|
|
13497
|
-
Made by a local Cursor agent through \`mushi work --followups\`.`], o.log);
|
|
13520
|
+
await commitWithHooks(wt, ["--quiet", "-m", `fix: address the Opus review (round ${claim.round})`, "-m", commitBody(cap(last, 1500) || "See the diff.", "Made by a local Cursor agent through `mushi work --followups`.")], o.log);
|
|
13498
13521
|
const sha = await git(wt, ["rev-parse", "HEAD"]);
|
|
13499
13522
|
await git(wt, ["push", "--quiet", "origin", `HEAD:refs/heads/${claim.branch}`]);
|
|
13500
13523
|
await done(sha, cap(last, 300));
|
|
@@ -13536,11 +13559,41 @@ async function commitWithHooks(wt, args, log3) {
|
|
|
13536
13559
|
await git(wt, ["commit", ...args]);
|
|
13537
13560
|
}
|
|
13538
13561
|
}
|
|
13539
|
-
|
|
13540
|
-
|
|
13541
|
-
if (
|
|
13562
|
+
function cursorSignInState(p4) {
|
|
13563
|
+
if (p4.code === null && /\bENOENT\b/.test(p4.stderr)) return "missing";
|
|
13564
|
+
if (p4.timedOut || p4.code === null) return "unknown";
|
|
13565
|
+
const out = stripVTControlCharacters(`${p4.stdout}
|
|
13566
|
+
${p4.stderr}`);
|
|
13567
|
+
if (/\bnot\s+(?:logged|signed)\s+in\b|\blogged\s+out\b/i.test(out)) return "signed_out";
|
|
13568
|
+
if (p4.code === 0 && /\b(?:logged|signed)\s+in\b/i.test(out)) return "signed_in";
|
|
13569
|
+
return "unknown";
|
|
13570
|
+
}
|
|
13571
|
+
var CURSOR_STATUS_TIMEOUT_MS = 9e4;
|
|
13572
|
+
var CURSOR_STATUS_RETRY_DELAY_MS = 5e3;
|
|
13573
|
+
async function checkCursorSignIn(run = runProc, wait = (ms) => new Promise((r) => setTimeout(r, ms))) {
|
|
13574
|
+
let last = { state: "unknown", detail: "not checked" };
|
|
13575
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
13576
|
+
if (attempt > 0) await wait(CURSOR_STATUS_RETRY_DELAY_MS);
|
|
13577
|
+
const p4 = await run("cursor-agent", ["status"], { timeoutMs: CURSOR_STATUS_TIMEOUT_MS });
|
|
13578
|
+
const state = cursorSignInState(p4);
|
|
13579
|
+
const detail = p4.timedOut ? `timed out after ${CURSOR_STATUS_TIMEOUT_MS / 1e3} s` : stripVTControlCharacters(`${p4.stdout}
|
|
13580
|
+
${p4.stderr}`).trim().split("\n")[0]?.slice(0, 200) || `exit ${p4.code}`;
|
|
13581
|
+
last = { state, detail };
|
|
13582
|
+
if (state === "signed_in" || state === "missing") break;
|
|
13583
|
+
}
|
|
13584
|
+
return last;
|
|
13585
|
+
}
|
|
13586
|
+
async function preflight(repoDir, warn) {
|
|
13587
|
+
const signIn = await checkCursorSignIn();
|
|
13588
|
+
if (signIn.state === "missing") {
|
|
13589
|
+
throw new MushiCliError("E_FILE_NOT_FOUND", "The Cursor CLI (cursor-agent) is not installed or not on PATH.", "Install it: https://cursor.com/cli");
|
|
13590
|
+
}
|
|
13591
|
+
if (signIn.state === "signed_out") {
|
|
13542
13592
|
throw new MushiCliError("E_AUTH_MISSING", "The Cursor CLI is not signed in.", "Run: cursor-agent login");
|
|
13543
13593
|
}
|
|
13594
|
+
if (signIn.state === "unknown") {
|
|
13595
|
+
warn(`Could not confirm the Cursor CLI sign-in (${signIn.detail}); continuing. If it is signed out, the agent stops at once: run cursor-agent login.`);
|
|
13596
|
+
}
|
|
13544
13597
|
const gh = await runProc("gh", ["auth", "status"], { timeoutMs: 3e4 });
|
|
13545
13598
|
if (gh.code !== 0) throw new MushiCliError("E_AUTH_MISSING", "gh is not signed in.", "Run: gh auth login");
|
|
13546
13599
|
await git(repoDir, ["rev-parse", "--git-dir"]);
|
|
@@ -13568,6 +13621,8 @@ function registerWorkCommands(program2) {
|
|
|
13568
13621
|
if (!opts.json) process.stdout.write(`${l}
|
|
13569
13622
|
`);
|
|
13570
13623
|
};
|
|
13624
|
+
const warn = (l) => process.stderr.write(`${l}
|
|
13625
|
+
`);
|
|
13571
13626
|
if (opts.followups) {
|
|
13572
13627
|
const listed = await api(`/v1/admin/projects/${cfg.projectId}/local-followups`);
|
|
13573
13628
|
const due = listed.fixes.slice(0, max);
|
|
@@ -13578,7 +13633,7 @@ function registerWorkCommands(program2) {
|
|
|
13578
13633
|
if (!due.length) log3("No pull request is waiting for a follow-up.");
|
|
13579
13634
|
return;
|
|
13580
13635
|
}
|
|
13581
|
-
await preflight(opts.repoDir);
|
|
13636
|
+
await preflight(opts.repoDir, warn);
|
|
13582
13637
|
await requireWriteScope(cfg);
|
|
13583
13638
|
const results2 = [];
|
|
13584
13639
|
for (const f of due) {
|
|
@@ -13605,7 +13660,7 @@ function registerWorkCommands(program2) {
|
|
|
13605
13660
|
if (!plan.length) log3("Nothing to work on.");
|
|
13606
13661
|
return;
|
|
13607
13662
|
}
|
|
13608
|
-
await preflight(opts.repoDir);
|
|
13663
|
+
await preflight(opts.repoDir, warn);
|
|
13609
13664
|
await requireWriteScope(cfg);
|
|
13610
13665
|
const results = [];
|
|
13611
13666
|
for (const d of picked) {
|
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-67WU4UYB.js";
|
|
29
29
|
import {
|
|
30
30
|
MUSHI_CLI_VERSION
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-QI7DE6J3.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-354QHAUQ.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.29.
|
|
17
|
+
declare const MUSHI_MCP_PIN_SPEC = "@mushi-mushi/mcp@0.29.2";
|
|
18
18
|
|
|
19
19
|
export { MUSHI_CLI_VERSION, MUSHI_MCP_PIN_SPEC };
|
package/dist/version.js
CHANGED
package/package.json
CHANGED
package/dist/chunk-CY2BHCA5.js
DELETED