magus-cli 7.11.4 → 7.11.6
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/package.json +4 -4
- package/src/__tests__/deprecated-remove-all-profiles.test.ts +171 -0
- package/src/__tests__/mcp-registry-install-screen.test.tsx +732 -0
- package/src/__tests__/mcp-registry-install.test.ts +551 -0
- package/src/__tests__/mcp-registry-screen-debounce.test.tsx +195 -0
- package/src/__tests__/mcp-registry-screen.test.ts +209 -0
- package/src/__tests__/not-installed-answer-wrong-scope.test.ts +46 -0
- package/src/__tests__/update-removes-deprecated-other-profiles.test.ts +401 -0
- package/src/cli/update.ts +14 -2
- package/src/services/active-closure.ts +12 -2
- package/src/services/claude-cli.ts +12 -1
- package/src/services/mcp-registry.ts +150 -0
- package/src/services/profile-state.ts +2 -12
- package/src/services/resolver.ts +31 -0
- package/src/services/update-engine.ts +146 -12
- package/src/services/update-plan.ts +42 -2
- package/src/ui/keymap.ts +1 -0
- package/src/ui/renderers/mcpRenderers.tsx +6 -1
- package/src/ui/screens/McpRegistryScreen.tsx +146 -26
- package/src/ui/screens/PluginsScreen.tsx +24 -38
|
@@ -9,14 +9,8 @@ import {
|
|
|
9
9
|
type PluginScope,
|
|
10
10
|
addMarketplace as cliAddMarketplace,
|
|
11
11
|
repairPlugin as cliRepairPlugin,
|
|
12
|
-
isNotInstalledAnswer,
|
|
13
|
-
uninstallPluginViaCli,
|
|
14
12
|
} from "../../services/claude-cli.js";
|
|
15
|
-
import {
|
|
16
|
-
readInheritedRegistryRows,
|
|
17
|
-
readSettings,
|
|
18
|
-
setMcpEnvVar,
|
|
19
|
-
} from "../../services/claude-settings.js";
|
|
13
|
+
import { readSettings, setMcpEnvVar } from "../../services/claude-settings.js";
|
|
20
14
|
import { clearContentDriftCache } from "../../services/content-drift.js";
|
|
21
15
|
import { missingPluginEnvVars } from "../../services/plugin-env-needs.js";
|
|
22
16
|
import {
|
|
@@ -49,6 +43,7 @@ import {
|
|
|
49
43
|
applyPlugins,
|
|
50
44
|
installPluginInScope,
|
|
51
45
|
pluginNeedsWork,
|
|
46
|
+
removeDeprecatedPlugin,
|
|
52
47
|
uninstallPluginInScope,
|
|
53
48
|
updatePluginInScope,
|
|
54
49
|
} from "../../services/update-engine.js";
|
|
@@ -176,6 +171,14 @@ export function PluginsScreen() {
|
|
|
176
171
|
const [requiredBy, setRequiredBy] = useState<
|
|
177
172
|
Readonly<Record<string, readonly string[]>>
|
|
178
173
|
>({});
|
|
174
|
+
/**
|
|
175
|
+
* Every plugin any profile lists — the same set `magus update` plans with,
|
|
176
|
+
* so a deprecated plugin only another profile keeps is a `remove` row here
|
|
177
|
+
* and a removal there.
|
|
178
|
+
*/
|
|
179
|
+
const [listedByProfiles, setListedByProfiles] = useState<readonly string[]>(
|
|
180
|
+
[],
|
|
181
|
+
);
|
|
179
182
|
|
|
180
183
|
// Fetch data (always fetches all scopes). Only the most recently started
|
|
181
184
|
// load may touch the screen.
|
|
@@ -209,6 +212,7 @@ export function PluginsScreen() {
|
|
|
209
212
|
setPins(active?.closure.plugins ?? null);
|
|
210
213
|
setActiveProfileId(active?.profileId ?? null);
|
|
211
214
|
setRequiredBy(required);
|
|
215
|
+
setListedByProfiles(active?.listedByProfiles ?? []);
|
|
212
216
|
|
|
213
217
|
// Which catalogs answered, and which only appeared to. Read straight
|
|
214
218
|
// after the fetch, while the record still describes this attempt.
|
|
@@ -300,9 +304,14 @@ export function PluginsScreen() {
|
|
|
300
304
|
const statuses = useMemo(
|
|
301
305
|
(): Map<string, PluginUpdateItem> =>
|
|
302
306
|
shownPlugins
|
|
303
|
-
? classifyPluginRows(
|
|
307
|
+
? classifyPluginRows(
|
|
308
|
+
shownPlugins,
|
|
309
|
+
pins ?? {},
|
|
310
|
+
requiredBy,
|
|
311
|
+
listedByProfiles,
|
|
312
|
+
)
|
|
304
313
|
: new Map(),
|
|
305
|
-
[shownPlugins, pins, requiredBy],
|
|
314
|
+
[shownPlugins, pins, requiredBy, listedByProfiles],
|
|
306
315
|
);
|
|
307
316
|
|
|
308
317
|
/**
|
|
@@ -1265,39 +1274,16 @@ export function PluginsScreen() {
|
|
|
1265
1274
|
return;
|
|
1266
1275
|
}
|
|
1267
1276
|
|
|
1268
|
-
//
|
|
1269
|
-
//
|
|
1270
|
-
|
|
1277
|
+
// An orphan the plan keeps rather than removes — it moved, another plugin
|
|
1278
|
+
// still requires it, or its marketplace was not read — and the user asked
|
|
1279
|
+
// for it gone. The engine uninstalls everywhere, drops it from every
|
|
1280
|
+
// profile and renders the active one again, so the row does not come back.
|
|
1271
1281
|
try {
|
|
1272
|
-
|
|
1273
|
-
const
|
|
1274
|
-
for (const scope of scopes) {
|
|
1275
|
-
try {
|
|
1276
|
-
modal.loading(
|
|
1277
|
-
`Removing ${plugin.name} from ${scope}…\nclaude plugin uninstall ${plugin.id} --scope ${scope}`,
|
|
1278
|
-
);
|
|
1279
|
-
await uninstallPluginViaCli(plugin.id, scope, state.projectPath);
|
|
1280
|
-
} catch (error) {
|
|
1281
|
-
if (!isNotInstalledAnswer(error)) problems.push(error);
|
|
1282
|
-
}
|
|
1283
|
-
}
|
|
1284
|
-
// A folder of the same repository may hold the install this one only
|
|
1285
|
-
// shows: the CLI removes it only when run from that folder.
|
|
1286
|
-
const inherited = await readInheritedRegistryRows(
|
|
1282
|
+
modal.loading(`Removing ${plugin.name}…`);
|
|
1283
|
+
const { problems } = await removeDeprecatedPlugin(
|
|
1287
1284
|
plugin.id,
|
|
1288
1285
|
state.projectPath || process.cwd(),
|
|
1289
1286
|
);
|
|
1290
|
-
for (const row of inherited) {
|
|
1291
|
-
if (!row.projectPath) continue;
|
|
1292
|
-
try {
|
|
1293
|
-
modal.loading(
|
|
1294
|
-
`Removing ${plugin.name} from the repository's main folder, which this folder shares…\nclaude plugin uninstall ${plugin.id} --scope ${row.scope}`,
|
|
1295
|
-
);
|
|
1296
|
-
await uninstallPluginViaCli(plugin.id, row.scope, row.projectPath);
|
|
1297
|
-
} catch (error) {
|
|
1298
|
-
problems.push(error);
|
|
1299
|
-
}
|
|
1300
|
-
}
|
|
1301
1287
|
|
|
1302
1288
|
modal.hideModal();
|
|
1303
1289
|
fetchData();
|