claudeup 4.10.0 → 4.10.2
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 +1 -1
- package/src/services/claude-cli.js +8 -4
- package/src/services/claude-cli.ts +12 -4
- package/src/ui/App.js +39 -3
- package/src/ui/App.tsx +52 -2
package/package.json
CHANGED
|
@@ -53,9 +53,8 @@ async function execClaude(args, timeoutMs = 30000) {
|
|
|
53
53
|
* Handles enabling + version tracking + cache copy in one shot.
|
|
54
54
|
*
|
|
55
55
|
* If the install fails because the plugin is "not found in marketplace",
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
* the local marketplace clone.
|
|
56
|
+
* recovers the marketplace registry (fixes stale "directory" sources),
|
|
57
|
+
* triggers a marketplace update, and retries once.
|
|
59
58
|
*/
|
|
60
59
|
export async function installPlugin(pluginId, scope = "user") {
|
|
61
60
|
try {
|
|
@@ -64,10 +63,13 @@ export async function installPlugin(pluginId, scope = "user") {
|
|
|
64
63
|
catch (error) {
|
|
65
64
|
const msg = error instanceof Error ? error.message : String(error);
|
|
66
65
|
if (msg.includes("not found in marketplace")) {
|
|
67
|
-
// Local marketplace clone is stale — update and retry
|
|
68
66
|
const parts = pluginId.split("@");
|
|
69
67
|
const marketplace = parts[1];
|
|
70
68
|
if (marketplace) {
|
|
69
|
+
// Fix known_marketplaces.json first (stale "directory" → "github"),
|
|
70
|
+
// then update, then retry
|
|
71
|
+
const { recoverMarketplaceSettings } = await import("./claude-settings.js");
|
|
72
|
+
await recoverMarketplaceSettings();
|
|
71
73
|
await updateMarketplace(marketplace);
|
|
72
74
|
await execClaude([
|
|
73
75
|
"plugin",
|
|
@@ -136,6 +138,8 @@ export async function updatePlugin(pluginId, scope = "user") {
|
|
|
136
138
|
const parts = pluginId.split("@");
|
|
137
139
|
const marketplace = parts[1];
|
|
138
140
|
if (marketplace) {
|
|
141
|
+
const { recoverMarketplaceSettings } = await import("./claude-settings.js");
|
|
142
|
+
await recoverMarketplaceSettings();
|
|
139
143
|
await updateMarketplace(marketplace);
|
|
140
144
|
await execClaude(["plugin", "install", pluginId, "--scope", scope], 60000);
|
|
141
145
|
return;
|
|
@@ -70,9 +70,8 @@ async function execClaude(args: string[], timeoutMs = 30000): Promise<string> {
|
|
|
70
70
|
* Handles enabling + version tracking + cache copy in one shot.
|
|
71
71
|
*
|
|
72
72
|
* If the install fails because the plugin is "not found in marketplace",
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
* the local marketplace clone.
|
|
73
|
+
* recovers the marketplace registry (fixes stale "directory" sources),
|
|
74
|
+
* triggers a marketplace update, and retries once.
|
|
76
75
|
*/
|
|
77
76
|
export async function installPlugin(
|
|
78
77
|
pluginId: string,
|
|
@@ -84,10 +83,15 @@ export async function installPlugin(
|
|
|
84
83
|
const msg =
|
|
85
84
|
error instanceof Error ? error.message : String(error);
|
|
86
85
|
if (msg.includes("not found in marketplace")) {
|
|
87
|
-
// Local marketplace clone is stale — update and retry
|
|
88
86
|
const parts = pluginId.split("@");
|
|
89
87
|
const marketplace = parts[1];
|
|
90
88
|
if (marketplace) {
|
|
89
|
+
// Fix known_marketplaces.json first (stale "directory" → "github"),
|
|
90
|
+
// then update, then retry
|
|
91
|
+
const { recoverMarketplaceSettings } = await import(
|
|
92
|
+
"./claude-settings.js"
|
|
93
|
+
);
|
|
94
|
+
await recoverMarketplaceSettings();
|
|
91
95
|
await updateMarketplace(marketplace);
|
|
92
96
|
await execClaude([
|
|
93
97
|
"plugin",
|
|
@@ -173,6 +177,10 @@ export async function updatePlugin(
|
|
|
173
177
|
const parts = pluginId.split("@");
|
|
174
178
|
const marketplace = parts[1];
|
|
175
179
|
if (marketplace) {
|
|
180
|
+
const { recoverMarketplaceSettings } = await import(
|
|
181
|
+
"./claude-settings.js"
|
|
182
|
+
);
|
|
183
|
+
await recoverMarketplaceSettings();
|
|
176
184
|
await updateMarketplace(marketplace);
|
|
177
185
|
await execClaude(
|
|
178
186
|
["plugin", "install", pluginId, "--scope", scope],
|
package/src/ui/App.js
CHANGED
|
@@ -7,7 +7,7 @@ import { DimensionsProvider, useDimensions, } from "./state/DimensionsContext.js
|
|
|
7
7
|
import { ModalContainer } from "./components/modals/index.js";
|
|
8
8
|
import { PluginsScreen, McpScreen, McpRegistryScreen, SettingsScreen, CliToolsScreen, ModelSelectorScreen, ProfilesScreen, SkillsScreen, } from "./screens/index.js";
|
|
9
9
|
import { repairAllMarketplaces } from "../services/local-marketplace.js";
|
|
10
|
-
import { migrateMarketplaceRename } from "../services/claude-settings.js";
|
|
10
|
+
import { migrateMarketplaceRename, recoverMarketplaceSettings, } from "../services/claude-settings.js";
|
|
11
11
|
import { checkForUpdates, getCurrentVersion, } from "../services/version-check.js";
|
|
12
12
|
import { useKeyboardHandler } from "./hooks/useKeyboardHandler.js";
|
|
13
13
|
import { ProgressBar } from "./components/layout/ProgressBar.js";
|
|
@@ -166,7 +166,7 @@ MCP Servers
|
|
|
166
166
|
function UpdateBanner({ result }) {
|
|
167
167
|
if (!result.updateAvailable)
|
|
168
168
|
return null;
|
|
169
|
-
return (_jsxs("box", { paddingLeft: 1, paddingRight: 1, children: [_jsx("text", { bg: "yellow", fg: "black", children: _jsx("strong", { children: " UPDATE " }) }), _jsxs("text", { fg: "yellow", children: [" ", "v", result.currentVersion, " \u2192 v", result.latestVersion] }), _jsx("text", { fg: "gray", children: " Run: " }), _jsx("text", { fg: "cyan", children: "
|
|
169
|
+
return (_jsxs("box", { paddingLeft: 1, paddingRight: 1, children: [_jsx("text", { bg: "yellow", fg: "black", children: _jsx("strong", { children: " UPDATE " }) }), _jsxs("text", { fg: "yellow", children: [" ", "v", result.currentVersion, " \u2192 v", result.latestVersion] }), _jsx("text", { fg: "gray", children: " Run: " }), _jsx("text", { fg: "cyan", children: "claudeup update" })] }));
|
|
170
170
|
}
|
|
171
171
|
/**
|
|
172
172
|
* ProgressIndicator Component
|
|
@@ -179,6 +179,14 @@ function AppContentInner({ showDebug, onDebugToggle, updateInfo, onExit, }) {
|
|
|
179
179
|
const { state, dispatch } = useApp();
|
|
180
180
|
const { progress } = state;
|
|
181
181
|
const dimensions = useDimensions();
|
|
182
|
+
const [recoveryReport, setRecoveryReport] = useState(null);
|
|
183
|
+
// Auto-dismiss recovery banner after 5 seconds
|
|
184
|
+
useEffect(() => {
|
|
185
|
+
if (!recoveryReport)
|
|
186
|
+
return;
|
|
187
|
+
const timer = setTimeout(() => setRecoveryReport(null), 5000);
|
|
188
|
+
return () => clearTimeout(timer);
|
|
189
|
+
}, [recoveryReport]);
|
|
182
190
|
// Auto-refresh marketplaces on startup
|
|
183
191
|
useEffect(() => {
|
|
184
192
|
const noRefresh = process.argv.includes("--no-refresh");
|
|
@@ -190,6 +198,34 @@ function AppContentInner({ showDebug, onDebugToggle, updateInfo, onExit, }) {
|
|
|
190
198
|
});
|
|
191
199
|
// Migrate old marketplace names → magus (idempotent), then repair plugin.json files
|
|
192
200
|
migrateMarketplaceRename().catch(() => { }); // non-blocking, best-effort
|
|
201
|
+
// Recover stale marketplace registry entries (e.g. "directory" → "github")
|
|
202
|
+
recoverMarketplaceSettings()
|
|
203
|
+
.then(async (recovery) => {
|
|
204
|
+
const parts = [];
|
|
205
|
+
if (recovery.reregistered.length > 0) {
|
|
206
|
+
// Update the marketplace clone now that the source is fixed
|
|
207
|
+
const { updateMarketplace } = await import("../services/claude-cli.js");
|
|
208
|
+
for (const mp of recovery.reregistered) {
|
|
209
|
+
try {
|
|
210
|
+
await updateMarketplace(mp);
|
|
211
|
+
parts.push(`${mp} refreshed`);
|
|
212
|
+
}
|
|
213
|
+
catch {
|
|
214
|
+
parts.push(`${mp} (update failed)`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
if (recovery.enabledAutoUpdate.length > 0) {
|
|
219
|
+
parts.push(`auto-update: ${recovery.enabledAutoUpdate.join(", ")}`);
|
|
220
|
+
}
|
|
221
|
+
if (recovery.removed.length > 0) {
|
|
222
|
+
parts.push(`removed: ${recovery.removed.join(", ")}`);
|
|
223
|
+
}
|
|
224
|
+
if (parts.length > 0) {
|
|
225
|
+
setRecoveryReport(parts.join(" | "));
|
|
226
|
+
}
|
|
227
|
+
})
|
|
228
|
+
.catch(() => { }); // non-fatal
|
|
193
229
|
repairAllMarketplaces()
|
|
194
230
|
.then(async () => {
|
|
195
231
|
dispatch({ type: "HIDE_PROGRESS" });
|
|
@@ -199,7 +235,7 @@ function AppContentInner({ showDebug, onDebugToggle, updateInfo, onExit, }) {
|
|
|
199
235
|
dispatch({ type: "HIDE_PROGRESS" });
|
|
200
236
|
});
|
|
201
237
|
}, [dispatch]);
|
|
202
|
-
return (_jsxs("box", { flexDirection: "column", height: dimensions.terminalHeight, children: [updateInfo?.updateAvailable && _jsx(UpdateBanner, { result: updateInfo }), showDebug && (_jsx("box", { paddingLeft: 1, paddingRight: 1, children: _jsxs("text", { fg: "#888888", children: ["DEBUG: ", dimensions.terminalWidth, "x", dimensions.terminalHeight, " | content=", dimensions.contentHeight, " | screen=", state.currentRoute.screen] }) })), progress && _jsx(ProgressIndicator, { ...progress }), _jsx("box", { flexDirection: "column", height: dimensions.contentHeight, paddingLeft: 1, paddingRight: 1, children: _jsx(Router, {}) }), _jsx(GlobalKeyHandler, { onDebugToggle: onDebugToggle, onExit: onExit }), _jsx(ModalContainer, {})] }));
|
|
238
|
+
return (_jsxs("box", { flexDirection: "column", height: dimensions.terminalHeight, children: [updateInfo?.updateAvailable && _jsx(UpdateBanner, { result: updateInfo }), recoveryReport && (_jsx("box", { paddingLeft: 1, paddingRight: 1, children: _jsxs("text", { fg: "green", children: ["\u2713 Fixed: ", recoveryReport] }) })), showDebug && (_jsx("box", { paddingLeft: 1, paddingRight: 1, children: _jsxs("text", { fg: "#888888", children: ["DEBUG: ", dimensions.terminalWidth, "x", dimensions.terminalHeight, " | content=", dimensions.contentHeight, " | screen=", state.currentRoute.screen] }) })), progress && _jsx(ProgressIndicator, { ...progress }), _jsx("box", { flexDirection: "column", height: dimensions.contentHeight, paddingLeft: 1, paddingRight: 1, children: _jsx(Router, {}) }), _jsx(GlobalKeyHandler, { onDebugToggle: onDebugToggle, onExit: onExit }), _jsx(ModalContainer, {})] }));
|
|
203
239
|
}
|
|
204
240
|
function AppContent({ onExit }) {
|
|
205
241
|
const { state } = useApp();
|
package/src/ui/App.tsx
CHANGED
|
@@ -24,7 +24,10 @@ import {
|
|
|
24
24
|
} from "./screens/index.js";
|
|
25
25
|
import type { Screen } from "./state/types.js";
|
|
26
26
|
import { repairAllMarketplaces } from "../services/local-marketplace.js";
|
|
27
|
-
import {
|
|
27
|
+
import {
|
|
28
|
+
migrateMarketplaceRename,
|
|
29
|
+
recoverMarketplaceSettings,
|
|
30
|
+
} from "../services/claude-settings.js";
|
|
28
31
|
import {
|
|
29
32
|
checkForUpdates,
|
|
30
33
|
getCurrentVersion,
|
|
@@ -213,7 +216,7 @@ function UpdateBanner({ result }: { result: VersionCheckResult }) {
|
|
|
213
216
|
v{result.currentVersion} → v{result.latestVersion}
|
|
214
217
|
</text>
|
|
215
218
|
<text fg="gray"> Run: </text>
|
|
216
|
-
<text fg="cyan">
|
|
219
|
+
<text fg="cyan">claudeup update</text>
|
|
217
220
|
</box>
|
|
218
221
|
);
|
|
219
222
|
}
|
|
@@ -258,6 +261,14 @@ function AppContentInner({
|
|
|
258
261
|
const { state, dispatch } = useApp();
|
|
259
262
|
const { progress } = state;
|
|
260
263
|
const dimensions = useDimensions();
|
|
264
|
+
const [recoveryReport, setRecoveryReport] = useState<string | null>(null);
|
|
265
|
+
|
|
266
|
+
// Auto-dismiss recovery banner after 5 seconds
|
|
267
|
+
useEffect(() => {
|
|
268
|
+
if (!recoveryReport) return;
|
|
269
|
+
const timer = setTimeout(() => setRecoveryReport(null), 5000);
|
|
270
|
+
return () => clearTimeout(timer);
|
|
271
|
+
}, [recoveryReport]);
|
|
261
272
|
|
|
262
273
|
// Auto-refresh marketplaces on startup
|
|
263
274
|
useEffect(() => {
|
|
@@ -272,6 +283,40 @@ function AppContentInner({
|
|
|
272
283
|
// Migrate old marketplace names → magus (idempotent), then repair plugin.json files
|
|
273
284
|
migrateMarketplaceRename().catch(() => {}); // non-blocking, best-effort
|
|
274
285
|
|
|
286
|
+
// Recover stale marketplace registry entries (e.g. "directory" → "github")
|
|
287
|
+
recoverMarketplaceSettings()
|
|
288
|
+
.then(async (recovery) => {
|
|
289
|
+
const parts: string[] = [];
|
|
290
|
+
if (recovery.reregistered.length > 0) {
|
|
291
|
+
// Update the marketplace clone now that the source is fixed
|
|
292
|
+
const { updateMarketplace } = await import(
|
|
293
|
+
"../services/claude-cli.js"
|
|
294
|
+
);
|
|
295
|
+
for (const mp of recovery.reregistered) {
|
|
296
|
+
try {
|
|
297
|
+
await updateMarketplace(mp);
|
|
298
|
+
parts.push(`${mp} refreshed`);
|
|
299
|
+
} catch {
|
|
300
|
+
parts.push(`${mp} (update failed)`);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
if (recovery.enabledAutoUpdate.length > 0) {
|
|
305
|
+
parts.push(
|
|
306
|
+
`auto-update: ${recovery.enabledAutoUpdate.join(", ")}`,
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
if (recovery.removed.length > 0) {
|
|
310
|
+
parts.push(
|
|
311
|
+
`removed: ${recovery.removed.join(", ")}`,
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
if (parts.length > 0) {
|
|
315
|
+
setRecoveryReport(parts.join(" | "));
|
|
316
|
+
}
|
|
317
|
+
})
|
|
318
|
+
.catch(() => {}); // non-fatal
|
|
319
|
+
|
|
275
320
|
repairAllMarketplaces()
|
|
276
321
|
.then(async () => {
|
|
277
322
|
dispatch({ type: "HIDE_PROGRESS" });
|
|
@@ -285,6 +330,11 @@ function AppContentInner({
|
|
|
285
330
|
return (
|
|
286
331
|
<box flexDirection="column" height={dimensions.terminalHeight}>
|
|
287
332
|
{updateInfo?.updateAvailable && <UpdateBanner result={updateInfo} />}
|
|
333
|
+
{recoveryReport && (
|
|
334
|
+
<box paddingLeft={1} paddingRight={1}>
|
|
335
|
+
<text fg="green">✓ Fixed: {recoveryReport}</text>
|
|
336
|
+
</box>
|
|
337
|
+
)}
|
|
288
338
|
{showDebug && (
|
|
289
339
|
<box paddingLeft={1} paddingRight={1}>
|
|
290
340
|
<text fg="#888888">
|