muonroi-cli 1.7.0 → 1.7.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/dist/src/generated/version.d.ts +1 -1
- package/dist/src/generated/version.js +1 -1
- package/dist/src/utils/install-manager.d.ts +29 -0
- package/dist/src/utils/install-manager.js +106 -0
- package/dist/src/utils/update-checker.js +2 -2
- package/dist/src/utils/update-checker.test.js +17 -4
- package/package.json +1 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const PACKAGE_VERSION = "1.7.
|
|
1
|
+
export declare const PACKAGE_VERSION = "1.7.1";
|
|
2
2
|
export declare const PACKAGE_DESCRIPTION = "BYOK AI coding agent with multi-model council debate, role-based routing, and auto-compact.";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// AUTO-GENERATED by scripts/sync-version.cjs. DO NOT EDIT BY HAND.
|
|
2
2
|
// Sourced from package.json at build time so it survives bun --compile bundling.
|
|
3
|
-
export const PACKAGE_VERSION = "1.7.
|
|
3
|
+
export const PACKAGE_VERSION = "1.7.1";
|
|
4
4
|
export const PACKAGE_DESCRIPTION = "BYOK AI coding agent with multi-model council debate, role-based routing, and auto-compact.";
|
|
5
5
|
//# sourceMappingURL=version.js.map
|
|
@@ -51,6 +51,35 @@ export declare function saveScriptInstallMetadata(metadata: ScriptInstallMetadat
|
|
|
51
51
|
export declare function getScriptInstallContext(homeDir?: string): ScriptInstallContext | null;
|
|
52
52
|
export declare function fetchLatestReleaseVersion(): Promise<string | null>;
|
|
53
53
|
export declare function parseChecksumsFile(contents: string): Map<string, string>;
|
|
54
|
+
/**
|
|
55
|
+
* How this muonroi-cli was installed. Drives which update path the built-in
|
|
56
|
+
* `/update` flow takes:
|
|
57
|
+
* - "script" → install.sh-managed; runScriptManagedUpdate replaces the binary.
|
|
58
|
+
* - "bun-global" → `bun add -g muonroi-cli`; update via bun.
|
|
59
|
+
* - "npm-global" → `npm install -g muonroi-cli`; update via npm.
|
|
60
|
+
* - "compiled" → standalone single-file binary; re-download / rebuild.
|
|
61
|
+
* - "dev-link" → linked/source build run from a git checkout (bun link,
|
|
62
|
+
* symlinked global bin, or `bun run src/index.ts`); rebuild dist.
|
|
63
|
+
* - "unknown" → can't tell; fall back to generic guidance.
|
|
64
|
+
*/
|
|
65
|
+
export type InstallMethod = "script" | "bun-global" | "npm-global" | "compiled" | "dev-link" | "unknown";
|
|
66
|
+
/**
|
|
67
|
+
* Detect how the running muonroi-cli was installed by inspecting the location
|
|
68
|
+
* of this module on disk plus the runtime. Pure path inspection — no I/O beyond
|
|
69
|
+
* the install.json check, so it is safe to call on the hot path.
|
|
70
|
+
*/
|
|
71
|
+
export declare function detectInstallMethod(homeDir?: string): InstallMethod;
|
|
72
|
+
/** Package-manager command that updates muonroi-cli for the given method, or null. */
|
|
73
|
+
export declare function getUpdateCommandForMethod(method: InstallMethod): string | null;
|
|
74
|
+
/**
|
|
75
|
+
* Top-level update entry point. Routes to the script-managed updater for
|
|
76
|
+
* install.sh installs, and returns the correct package-manager command for
|
|
77
|
+
* bun/npm global installs (rather than the misleading "reinstall via install.sh"
|
|
78
|
+
* dead-end). We do NOT auto-spawn the package manager: on Windows overwriting the
|
|
79
|
+
* files of the live process is unreliable, so we hand the user an exact command
|
|
80
|
+
* to run from a fresh terminal.
|
|
81
|
+
*/
|
|
82
|
+
export declare function runManagedUpdate(currentVersion: string): Promise<ScriptUpdateRunResult>;
|
|
54
83
|
export declare function runScriptManagedUpdate(currentVersion: string): Promise<ScriptUpdateRunResult>;
|
|
55
84
|
export declare function buildScriptUninstallPlan(options?: ScriptUninstallOptions, homeDir?: string): ScriptUninstallPlan | null;
|
|
56
85
|
export declare function runScriptManagedUninstall(options?: ScriptUninstallOptions): Promise<ScriptUpdateRunResult>;
|
|
@@ -6,6 +6,7 @@ import path from "path";
|
|
|
6
6
|
import readline from "readline";
|
|
7
7
|
import semverGt from "semver/functions/gt.js";
|
|
8
8
|
import semverValid from "semver/functions/valid.js";
|
|
9
|
+
import { fileURLToPath } from "url";
|
|
9
10
|
export const GITHUB_REPO = "muonroi/muonroi-cli";
|
|
10
11
|
export const RELEASES_API = `https://api.github.com/repos/${GITHUB_REPO}/releases`;
|
|
11
12
|
export const SCRIPT_INSTALL_METHOD = "script";
|
|
@@ -99,6 +100,111 @@ export function parseChecksumsFile(contents) {
|
|
|
99
100
|
}
|
|
100
101
|
return result;
|
|
101
102
|
}
|
|
103
|
+
/** Absolute filesystem path of THIS module, normalized to forward slashes. */
|
|
104
|
+
function runningModulePath() {
|
|
105
|
+
try {
|
|
106
|
+
return fileURLToPath(import.meta.url).replace(/\\/g, "/");
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return (process.argv[1] ?? "").replace(/\\/g, "/");
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/** Walk up from `startDir` looking for a `.git` entry; return the repo root or null. */
|
|
113
|
+
function findGitRoot(startDir) {
|
|
114
|
+
let dir = startDir;
|
|
115
|
+
for (let i = 0; i < 30 && dir; i++) {
|
|
116
|
+
if (fs.existsSync(path.join(dir, ".git")))
|
|
117
|
+
return dir;
|
|
118
|
+
const parent = path.dirname(dir);
|
|
119
|
+
if (parent === dir)
|
|
120
|
+
break;
|
|
121
|
+
dir = parent;
|
|
122
|
+
}
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Detect how the running muonroi-cli was installed by inspecting the location
|
|
127
|
+
* of this module on disk plus the runtime. Pure path inspection — no I/O beyond
|
|
128
|
+
* the install.json check, so it is safe to call on the hot path.
|
|
129
|
+
*/
|
|
130
|
+
export function detectInstallMethod(homeDir = os.homedir()) {
|
|
131
|
+
if (loadScriptInstallMetadata(homeDir))
|
|
132
|
+
return "script";
|
|
133
|
+
const modPath = runningModulePath();
|
|
134
|
+
const importUrl = (import.meta.url || "").replace(/\\/g, "/");
|
|
135
|
+
// Bun single-file compiled executable embeds modules under a virtual root
|
|
136
|
+
// (e.g. "/$bunfs/" or "/~BUN/"), so the module path is not a real fs path.
|
|
137
|
+
if (importUrl.includes("/$bunfs/") || importUrl.includes("/~BUN/") || modPath.includes("/$bunfs/")) {
|
|
138
|
+
return "compiled";
|
|
139
|
+
}
|
|
140
|
+
// Bun's global install root: ~/.bun/install/global/node_modules/muonroi-cli/...
|
|
141
|
+
if (modPath.includes("/.bun/install/global/"))
|
|
142
|
+
return "bun-global";
|
|
143
|
+
if (/\/node_modules\/muonroi-cli\//.test(modPath)) {
|
|
144
|
+
return modPath.includes("/.bun/") ? "bun-global" : "npm-global";
|
|
145
|
+
}
|
|
146
|
+
// Not under node_modules and not launched by node/bun → standalone binary.
|
|
147
|
+
const exeBase = ((process.execPath || "").replace(/\\/g, "/").split("/").pop() ?? "").toLowerCase();
|
|
148
|
+
if (!modPath.includes("/node_modules/") && !/^(node|bun)(\.exe)?$/.test(exeBase)) {
|
|
149
|
+
return "compiled";
|
|
150
|
+
}
|
|
151
|
+
// Linked/source build run from a git checkout (e.g. `bun link`, a symlinked
|
|
152
|
+
// global bin pointing at the repo, or `bun run src/index.ts`). The "update"
|
|
153
|
+
// here is a rebuild, not a package-manager swap.
|
|
154
|
+
if (modPath && !modPath.includes("/node_modules/") && findGitRoot(path.dirname(modPath))) {
|
|
155
|
+
return "dev-link";
|
|
156
|
+
}
|
|
157
|
+
return "unknown";
|
|
158
|
+
}
|
|
159
|
+
/** Package-manager command that updates muonroi-cli for the given method, or null. */
|
|
160
|
+
export function getUpdateCommandForMethod(method) {
|
|
161
|
+
switch (method) {
|
|
162
|
+
case "bun-global":
|
|
163
|
+
return "bun add -g muonroi-cli@latest";
|
|
164
|
+
case "npm-global":
|
|
165
|
+
return "npm install -g muonroi-cli@latest";
|
|
166
|
+
default:
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Top-level update entry point. Routes to the script-managed updater for
|
|
172
|
+
* install.sh installs, and returns the correct package-manager command for
|
|
173
|
+
* bun/npm global installs (rather than the misleading "reinstall via install.sh"
|
|
174
|
+
* dead-end). We do NOT auto-spawn the package manager: on Windows overwriting the
|
|
175
|
+
* files of the live process is unreliable, so we hand the user an exact command
|
|
176
|
+
* to run from a fresh terminal.
|
|
177
|
+
*/
|
|
178
|
+
export async function runManagedUpdate(currentVersion) {
|
|
179
|
+
const method = detectInstallMethod();
|
|
180
|
+
if (method === "script")
|
|
181
|
+
return runScriptManagedUpdate(currentVersion);
|
|
182
|
+
const cmd = getUpdateCommandForMethod(method);
|
|
183
|
+
if (cmd) {
|
|
184
|
+
const pm = method === "bun-global" ? "bun" : "npm";
|
|
185
|
+
return {
|
|
186
|
+
success: true,
|
|
187
|
+
output: `Installed via ${pm} (global package). To update, run this in a fresh terminal:\n\n ${cmd}\n\nThen restart muonroi-cli.`,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
if (method === "compiled") {
|
|
191
|
+
const target = getReleaseTargetForPlatform();
|
|
192
|
+
const asset = target?.assetName ?? "the release asset for your platform";
|
|
193
|
+
return {
|
|
194
|
+
success: true,
|
|
195
|
+
output: `Standalone binary install. Download the latest ${asset} from https://github.com/${GITHUB_REPO}/releases/latest and replace the current binary, or rebuild from source.`,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
if (method === "dev-link") {
|
|
199
|
+
const root = findGitRoot(path.dirname(runningModulePath()));
|
|
200
|
+
const target = root ?? "the muonroi-cli checkout";
|
|
201
|
+
return {
|
|
202
|
+
success: true,
|
|
203
|
+
output: `Running a linked/source build from ${target}. To update, rebuild it:\n\n git -C "${target}" pull && bun install && bun run build\n\nThen restart muonroi-cli. (If you also use the compiled muonroi-cli-dev binary, rebuild that separately.)`,
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
return notScriptManaged("update");
|
|
207
|
+
}
|
|
102
208
|
export async function runScriptManagedUpdate(currentVersion) {
|
|
103
209
|
const context = getScriptInstallContext();
|
|
104
210
|
if (!context)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import semverGt from "semver/functions/gt.js";
|
|
2
2
|
import semverValid from "semver/functions/valid.js";
|
|
3
|
-
import { fetchLatestReleaseVersion,
|
|
3
|
+
import { fetchLatestReleaseVersion, runManagedUpdate } from "./install-manager.js";
|
|
4
4
|
export async function checkForUpdate(currentVersion) {
|
|
5
5
|
try {
|
|
6
6
|
const latestVersion = await fetchLatestReleaseVersion();
|
|
@@ -17,6 +17,6 @@ export async function checkForUpdate(currentVersion) {
|
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
export function runUpdate(currentVersion) {
|
|
20
|
-
return
|
|
20
|
+
return runManagedUpdate(currentVersion);
|
|
21
21
|
}
|
|
22
22
|
//# sourceMappingURL=update-checker.js.map
|
|
@@ -95,12 +95,12 @@ describe("checkForUpdate", () => {
|
|
|
95
95
|
});
|
|
96
96
|
});
|
|
97
97
|
describe("runUpdate", () => {
|
|
98
|
-
it("returns success when the
|
|
98
|
+
it("returns success when the managed updater succeeds", async () => {
|
|
99
99
|
vi.doMock("./install-manager", async () => {
|
|
100
100
|
const actual = await vi.importActual("./install-manager");
|
|
101
101
|
return {
|
|
102
102
|
...actual,
|
|
103
|
-
|
|
103
|
+
runManagedUpdate: vi.fn().mockResolvedValue({ success: true, output: "Updated to muonroi-cli 2.0.0." }),
|
|
104
104
|
};
|
|
105
105
|
});
|
|
106
106
|
const { runUpdate } = await importModule();
|
|
@@ -108,12 +108,12 @@ describe("runUpdate", () => {
|
|
|
108
108
|
expect(result.success).toBe(true);
|
|
109
109
|
expect(result.output).toContain("Updated");
|
|
110
110
|
});
|
|
111
|
-
it("returns failure when the
|
|
111
|
+
it("returns failure when the managed updater fails", async () => {
|
|
112
112
|
vi.doMock("./install-manager", async () => {
|
|
113
113
|
const actual = await vi.importActual("./install-manager");
|
|
114
114
|
return {
|
|
115
115
|
...actual,
|
|
116
|
-
|
|
116
|
+
runManagedUpdate: vi.fn().mockResolvedValue({ success: false, output: "permission denied" }),
|
|
117
117
|
};
|
|
118
118
|
});
|
|
119
119
|
const { runUpdate } = await importModule();
|
|
@@ -122,4 +122,17 @@ describe("runUpdate", () => {
|
|
|
122
122
|
expect(result.output).toContain("permission denied");
|
|
123
123
|
});
|
|
124
124
|
});
|
|
125
|
+
describe("getUpdateCommandForMethod", () => {
|
|
126
|
+
it("maps bun/npm global installs to the right update command", async () => {
|
|
127
|
+
const { getUpdateCommandForMethod } = await import("./install-manager.js");
|
|
128
|
+
expect(getUpdateCommandForMethod("bun-global")).toBe("bun add -g muonroi-cli@latest");
|
|
129
|
+
expect(getUpdateCommandForMethod("npm-global")).toBe("npm install -g muonroi-cli@latest");
|
|
130
|
+
});
|
|
131
|
+
it("returns null for methods without a package-manager command", async () => {
|
|
132
|
+
const { getUpdateCommandForMethod } = await import("./install-manager.js");
|
|
133
|
+
expect(getUpdateCommandForMethod("script")).toBeNull();
|
|
134
|
+
expect(getUpdateCommandForMethod("compiled")).toBeNull();
|
|
135
|
+
expect(getUpdateCommandForMethod("unknown")).toBeNull();
|
|
136
|
+
});
|
|
137
|
+
});
|
|
125
138
|
//# sourceMappingURL=update-checker.test.js.map
|