@mycelish/cli 0.1.0 → 0.2.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/__tests__/mcp-server.test.d.ts +2 -0
- package/dist/__tests__/mcp-server.test.d.ts.map +1 -0
- package/dist/__tests__/mcp-server.test.js +60 -0
- package/dist/__tests__/mcp-server.test.js.map +1 -0
- package/dist/__tests__/unified-item-state.integration.test.d.ts +7 -0
- package/dist/__tests__/unified-item-state.integration.test.d.ts.map +1 -0
- package/dist/__tests__/unified-item-state.integration.test.js +217 -0
- package/dist/__tests__/unified-item-state.integration.test.js.map +1 -0
- package/dist/commands/add.d.ts.map +1 -1
- package/dist/commands/add.js +9 -0
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/disable.d.ts +8 -6
- package/dist/commands/disable.d.ts.map +1 -1
- package/dist/commands/disable.js +143 -136
- package/dist/commands/disable.js.map +1 -1
- package/dist/commands/disable.test.js +117 -23
- package/dist/commands/disable.test.js.map +1 -1
- package/dist/commands/doctor.d.ts +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +1 -1
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/enable.d.ts +8 -6
- package/dist/commands/enable.d.ts.map +1 -1
- package/dist/commands/enable.js +128 -133
- package/dist/commands/enable.js.map +1 -1
- package/dist/commands/enable.test.js +192 -24
- package/dist/commands/enable.test.js.map +1 -1
- package/dist/commands/health-checks/index.d.ts +2 -1
- package/dist/commands/health-checks/index.d.ts.map +1 -1
- package/dist/commands/health-checks/index.js +2 -1
- package/dist/commands/health-checks/index.js.map +1 -1
- package/dist/commands/health-checks/mcp-check.d.ts +5 -1
- package/dist/commands/health-checks/mcp-check.d.ts.map +1 -1
- package/dist/commands/health-checks/mcp-check.js +32 -1
- package/dist/commands/health-checks/mcp-check.js.map +1 -1
- package/dist/commands/health-checks/plugin-takeover-check.d.ts +15 -0
- package/dist/commands/health-checks/plugin-takeover-check.d.ts.map +1 -0
- package/dist/commands/health-checks/plugin-takeover-check.js +274 -0
- package/dist/commands/health-checks/plugin-takeover-check.js.map +1 -0
- package/dist/commands/health-checks/runner.d.ts.map +1 -1
- package/dist/commands/health-checks/runner.js +18 -0
- package/dist/commands/health-checks/runner.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +33 -0
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/mcp.d.ts +9 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +17 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/migrate.d.ts.map +1 -1
- package/dist/commands/migrate.js +51 -0
- package/dist/commands/migrate.js.map +1 -1
- package/dist/commands/preset.test.js +7 -3
- package/dist/commands/preset.test.js.map +1 -1
- package/dist/commands/remove.d.ts +25 -23
- package/dist/commands/remove.d.ts.map +1 -1
- package/dist/commands/remove.js +118 -247
- package/dist/commands/remove.js.map +1 -1
- package/dist/commands/remove.test.js +152 -78
- package/dist/commands/remove.test.js.map +1 -1
- package/dist/commands/report.d.ts +8 -0
- package/dist/commands/report.d.ts.map +1 -0
- package/dist/commands/report.js +149 -0
- package/dist/commands/report.js.map +1 -0
- package/dist/commands/report.test.d.ts +2 -0
- package/dist/commands/report.test.d.ts.map +1 -0
- package/dist/commands/report.test.js +23 -0
- package/dist/commands/report.test.js.map +1 -0
- package/dist/commands/status.d.ts +9 -4
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +81 -10
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/status.test.js +92 -0
- package/dist/commands/status.test.js.map +1 -1
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +138 -7
- package/dist/commands/sync.js.map +1 -1
- package/dist/commands/sync.test.js +91 -6
- package/dist/commands/sync.test.js.map +1 -1
- package/dist/core/adapter-base.d.ts +2 -0
- package/dist/core/adapter-base.d.ts.map +1 -1
- package/dist/core/adapter-base.js +2 -1
- package/dist/core/adapter-base.js.map +1 -1
- package/dist/core/auto-adapter.d.ts.map +1 -1
- package/dist/core/auto-adapter.js +58 -3
- package/dist/core/auto-adapter.js.map +1 -1
- package/dist/core/auto-adapter.test.js +155 -0
- package/dist/core/auto-adapter.test.js.map +1 -1
- package/dist/core/config-merger.d.ts +6 -5
- package/dist/core/config-merger.d.ts.map +1 -1
- package/dist/core/config-merger.js +119 -136
- package/dist/core/config-merger.js.map +1 -1
- package/dist/core/config-merger.test.d.ts +1 -1
- package/dist/core/config-merger.test.js +72 -88
- package/dist/core/config-merger.test.js.map +1 -1
- package/dist/core/file-syncer.d.ts +33 -0
- package/dist/core/file-syncer.d.ts.map +1 -0
- package/dist/core/file-syncer.js +138 -0
- package/dist/core/file-syncer.js.map +1 -0
- package/dist/core/file-syncer.test.d.ts +2 -0
- package/dist/core/file-syncer.test.d.ts.map +1 -0
- package/dist/core/file-syncer.test.js +131 -0
- package/dist/core/file-syncer.test.js.map +1 -0
- package/dist/core/global-tracer.d.ts +4 -0
- package/dist/core/global-tracer.d.ts.map +1 -0
- package/dist/core/global-tracer.js +36 -0
- package/dist/core/global-tracer.js.map +1 -0
- package/dist/core/item-loader.d.ts +18 -0
- package/dist/core/item-loader.d.ts.map +1 -0
- package/dist/core/item-loader.js +40 -0
- package/dist/core/item-loader.js.map +1 -0
- package/dist/core/item-loader.test.d.ts +2 -0
- package/dist/core/item-loader.test.d.ts.map +1 -0
- package/dist/core/item-loader.test.js +52 -0
- package/dist/core/item-loader.test.js.map +1 -0
- package/dist/core/manifest-migrator.d.ts +15 -0
- package/dist/core/manifest-migrator.d.ts.map +1 -0
- package/dist/core/manifest-migrator.js +38 -0
- package/dist/core/manifest-migrator.js.map +1 -0
- package/dist/core/manifest-migrator.test.d.ts +2 -0
- package/dist/core/manifest-migrator.test.d.ts.map +1 -0
- package/dist/core/manifest-migrator.test.js +53 -0
- package/dist/core/manifest-migrator.test.js.map +1 -0
- package/dist/core/manifest-state.d.ts +117 -0
- package/dist/core/manifest-state.d.ts.map +1 -0
- package/dist/core/manifest-state.js +218 -0
- package/dist/core/manifest-state.js.map +1 -0
- package/dist/core/manifest-state.test.d.ts +2 -0
- package/dist/core/manifest-state.test.d.ts.map +1 -0
- package/dist/core/manifest-state.test.js +130 -0
- package/dist/core/manifest-state.test.js.map +1 -0
- package/dist/core/marketplace-registry.d.ts +0 -1
- package/dist/core/marketplace-registry.d.ts.map +1 -1
- package/dist/core/marketplace-registry.js +0 -16
- package/dist/core/marketplace-registry.js.map +1 -1
- package/dist/core/marketplace-registry.test.js +1 -14
- package/dist/core/marketplace-registry.test.js.map +1 -1
- package/dist/core/mcp-injector.d.ts +2 -2
- package/dist/core/mcp-injector.d.ts.map +1 -1
- package/dist/core/mcp-injector.js +6 -6
- package/dist/core/mcp-injector.js.map +1 -1
- package/dist/core/mcp-injector.test.js +33 -26
- package/dist/core/mcp-injector.test.js.map +1 -1
- package/dist/core/mcp-registry.js +1 -1
- package/dist/core/mcp-registry.js.map +1 -1
- package/dist/core/mcp-registry.test.js +1 -1
- package/dist/core/mcp-registry.test.js.map +1 -1
- package/dist/core/memory-scoper.test.js +2 -13
- package/dist/core/memory-scoper.test.js.map +1 -1
- package/dist/core/migrator/executor.js +2 -2
- package/dist/core/migrator/executor.js.map +1 -1
- package/dist/core/plugin-state.d.ts +7 -0
- package/dist/core/plugin-state.d.ts.map +1 -0
- package/dist/core/plugin-state.js +88 -0
- package/dist/core/plugin-state.js.map +1 -0
- package/dist/core/plugin-takeover.d.ts +50 -0
- package/dist/core/plugin-takeover.d.ts.map +1 -0
- package/dist/core/plugin-takeover.js +263 -0
- package/dist/core/plugin-takeover.js.map +1 -0
- package/dist/core/plugin-takeover.test.d.ts +2 -0
- package/dist/core/plugin-takeover.test.d.ts.map +1 -0
- package/dist/core/plugin-takeover.test.js +243 -0
- package/dist/core/plugin-takeover.test.js.map +1 -0
- package/dist/core/self-register.d.ts +5 -0
- package/dist/core/self-register.d.ts.map +1 -0
- package/dist/core/self-register.js +43 -0
- package/dist/core/self-register.js.map +1 -0
- package/dist/core/self-register.test.d.ts +2 -0
- package/dist/core/self-register.test.d.ts.map +1 -0
- package/dist/core/self-register.test.js +77 -0
- package/dist/core/self-register.test.js.map +1 -0
- package/dist/core/smart-memory.d.ts +5 -5
- package/dist/core/smart-memory.d.ts.map +1 -1
- package/dist/core/smart-memory.js +1 -10
- package/dist/core/smart-memory.js.map +1 -1
- package/dist/core/smart-memory.test.js +3 -30
- package/dist/core/smart-memory.test.js.map +1 -1
- package/dist/core/state-verifier.d.ts +36 -0
- package/dist/core/state-verifier.d.ts.map +1 -0
- package/dist/core/state-verifier.js +159 -0
- package/dist/core/state-verifier.js.map +1 -0
- package/dist/core/state-verifier.test.d.ts +2 -0
- package/dist/core/state-verifier.test.d.ts.map +1 -0
- package/dist/core/state-verifier.test.js +188 -0
- package/dist/core/state-verifier.test.js.map +1 -0
- package/dist/core/symlink-manager.d.ts +1 -1
- package/dist/core/symlink-manager.d.ts.map +1 -1
- package/dist/core/symlink-manager.js +1 -1
- package/dist/core/symlink-manager.js.map +1 -1
- package/dist/core/symlink-manager.test.js +4 -4
- package/dist/core/symlink-manager.test.js.map +1 -1
- package/dist/core/sync-writer.d.ts +2 -1
- package/dist/core/sync-writer.d.ts.map +1 -1
- package/dist/core/sync-writer.js +108 -22
- package/dist/core/sync-writer.js.map +1 -1
- package/dist/core/sync-writer.test.js +31 -0
- package/dist/core/sync-writer.test.js.map +1 -1
- package/dist/core/tool-adapter.d.ts.map +1 -1
- package/dist/core/tool-adapter.js +45 -6
- package/dist/core/tool-adapter.js.map +1 -1
- package/dist/core/trace-store.d.ts +36 -0
- package/dist/core/trace-store.d.ts.map +1 -0
- package/dist/core/trace-store.js +145 -0
- package/dist/core/trace-store.js.map +1 -0
- package/dist/core/trace-store.test.d.ts +2 -0
- package/dist/core/trace-store.test.d.ts.map +1 -0
- package/dist/core/trace-store.test.js +102 -0
- package/dist/core/trace-store.test.js.map +1 -0
- package/dist/core/tracer.d.ts +27 -0
- package/dist/core/tracer.d.ts.map +1 -0
- package/dist/core/tracer.js +62 -0
- package/dist/core/tracer.js.map +1 -0
- package/dist/core/tracer.test.d.ts +2 -0
- package/dist/core/tracer.test.d.ts.map +1 -0
- package/dist/core/tracer.test.js +54 -0
- package/dist/core/tracer.test.js.map +1 -0
- package/dist/core/watcher.d.ts.map +1 -1
- package/dist/core/watcher.js +9 -2
- package/dist/core/watcher.js.map +1 -1
- package/dist/core/watcher.test.js +9 -0
- package/dist/core/watcher.test.js.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/prompts.d.ts +3 -0
- package/dist/mcp/prompts.d.ts.map +1 -0
- package/dist/mcp/prompts.js +40 -0
- package/dist/mcp/prompts.js.map +1 -0
- package/dist/mcp/resources.d.ts +6 -0
- package/dist/mcp/resources.d.ts.map +1 -0
- package/dist/mcp/resources.js +24 -0
- package/dist/mcp/resources.js.map +1 -0
- package/dist/mcp/server.d.ts +7 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +27 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/server.test.d.ts +2 -0
- package/dist/mcp/server.test.d.ts.map +1 -0
- package/dist/mcp/server.test.js +9 -0
- package/dist/mcp/server.test.js.map +1 -0
- package/dist/mcp/tools/config-tools.d.ts +3 -0
- package/dist/mcp/tools/config-tools.d.ts.map +1 -0
- package/dist/mcp/tools/config-tools.js +80 -0
- package/dist/mcp/tools/config-tools.js.map +1 -0
- package/dist/mcp/tools/config-tools.test.d.ts +2 -0
- package/dist/mcp/tools/config-tools.test.d.ts.map +1 -0
- package/dist/mcp/tools/config-tools.test.js +207 -0
- package/dist/mcp/tools/config-tools.test.js.map +1 -0
- package/dist/mcp/tools/item-tools.d.ts +3 -0
- package/dist/mcp/tools/item-tools.d.ts.map +1 -0
- package/dist/mcp/tools/item-tools.js +95 -0
- package/dist/mcp/tools/item-tools.js.map +1 -0
- package/dist/mcp/tools/item-tools.test.d.ts +2 -0
- package/dist/mcp/tools/item-tools.test.d.ts.map +1 -0
- package/dist/mcp/tools/item-tools.test.js +184 -0
- package/dist/mcp/tools/item-tools.test.js.map +1 -0
- package/dist/mcp/tools/marketplace-tools.d.ts +3 -0
- package/dist/mcp/tools/marketplace-tools.d.ts.map +1 -0
- package/dist/mcp/tools/marketplace-tools.js +35 -0
- package/dist/mcp/tools/marketplace-tools.js.map +1 -0
- package/dist/mcp/tools/marketplace-tools.test.d.ts +2 -0
- package/dist/mcp/tools/marketplace-tools.test.d.ts.map +1 -0
- package/dist/mcp/tools/marketplace-tools.test.js +48 -0
- package/dist/mcp/tools/marketplace-tools.test.js.map +1 -0
- package/dist/mcp/tools/memory-tools.d.ts +3 -0
- package/dist/mcp/tools/memory-tools.d.ts.map +1 -0
- package/dist/mcp/tools/memory-tools.js +68 -0
- package/dist/mcp/tools/memory-tools.js.map +1 -0
- package/dist/mcp/tools/memory-tools.test.d.ts +2 -0
- package/dist/mcp/tools/memory-tools.test.d.ts.map +1 -0
- package/dist/mcp/tools/memory-tools.test.js +144 -0
- package/dist/mcp/tools/memory-tools.test.js.map +1 -0
- package/dist/mcp/tools/observe-tools.d.ts +3 -0
- package/dist/mcp/tools/observe-tools.d.ts.map +1 -0
- package/dist/mcp/tools/observe-tools.js +37 -0
- package/dist/mcp/tools/observe-tools.js.map +1 -0
- package/dist/mcp/tools/observe-tools.test.d.ts +2 -0
- package/dist/mcp/tools/observe-tools.test.d.ts.map +1 -0
- package/dist/mcp/tools/observe-tools.test.js +71 -0
- package/dist/mcp/tools/observe-tools.test.js.map +1 -0
- package/dist/routes/plugins.d.ts.map +1 -1
- package/dist/routes/plugins.js +63 -37
- package/dist/routes/plugins.js.map +1 -1
- package/dist/routes/plugins.test.d.ts +2 -0
- package/dist/routes/plugins.test.d.ts.map +1 -0
- package/dist/routes/plugins.test.js +56 -0
- package/dist/routes/plugins.test.js.map +1 -0
- package/dist/routes/remove.d.ts.map +1 -1
- package/dist/routes/remove.js +6 -15
- package/dist/routes/remove.js.map +1 -1
- package/dist/routes/state.d.ts.map +1 -1
- package/dist/routes/state.js +35 -70
- package/dist/routes/state.js.map +1 -1
- package/dist/routes/sync.d.ts.map +1 -1
- package/dist/routes/sync.js +10 -3
- package/dist/routes/sync.js.map +1 -1
- package/package.json +6 -2
package/dist/commands/disable.js
CHANGED
|
@@ -1,182 +1,186 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Disable Command Module
|
|
3
3
|
*
|
|
4
|
-
* Disable a skill or
|
|
5
|
-
* - mycelium disable <name> # Disable
|
|
6
|
-
* - mycelium disable <name> --global # Disable
|
|
7
|
-
* - mycelium disable <name> --tool <id> # Disable
|
|
4
|
+
* Disable a skill, MCP, hook, or memory item globally or for a specific tool:
|
|
5
|
+
* - mycelium disable <name> # Disable item at project level
|
|
6
|
+
* - mycelium disable <name> --global # Disable item globally
|
|
7
|
+
* - mycelium disable <name> --tool <id> # Disable item for specific tool only
|
|
8
8
|
*/
|
|
9
9
|
import { Command } from "commander";
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
// Helper Functions
|
|
16
|
-
// ============================================================================
|
|
17
|
-
/**
|
|
18
|
-
* Load manifest from a path
|
|
19
|
-
*/
|
|
20
|
-
async function loadManifest(manifestDir) {
|
|
21
|
-
const manifestPath = path.join(manifestDir, "manifest.yaml");
|
|
22
|
-
try {
|
|
23
|
-
const content = await fs.readFile(manifestPath, "utf-8");
|
|
24
|
-
return yamlParse(content);
|
|
25
|
-
}
|
|
26
|
-
catch {
|
|
27
|
-
return null;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Save manifest to a path
|
|
32
|
-
*/
|
|
33
|
-
async function saveManifest(manifestDir, manifest) {
|
|
34
|
-
const manifestPath = path.join(manifestDir, "manifest.yaml");
|
|
35
|
-
const content = yamlStringify(manifest);
|
|
36
|
-
await fs.writeFile(manifestPath, content, "utf-8");
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Check if a tool ID is valid
|
|
40
|
-
*/
|
|
41
|
-
function isValidToolId(toolId) {
|
|
42
|
-
return toolId in TOOL_REGISTRY;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Find what type an item is (skill or MCP)
|
|
46
|
-
*/
|
|
47
|
-
function findItemType(manifest, name) {
|
|
48
|
-
if (manifest.skills && name in manifest.skills) {
|
|
49
|
-
return { type: "skill", config: manifest.skills[name] };
|
|
50
|
-
}
|
|
51
|
-
if (manifest.mcps && name in manifest.mcps) {
|
|
52
|
-
return { type: "mcp", config: manifest.mcps[name] };
|
|
53
|
-
}
|
|
54
|
-
return null;
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Check if item is already disabled (globally or for a specific tool)
|
|
58
|
-
*/
|
|
59
|
-
function isAlreadyDisabled(config, tool) {
|
|
60
|
-
if (tool) {
|
|
61
|
-
// Check tool-specific disablement
|
|
62
|
-
if (config.excludeTools?.includes(tool)) {
|
|
63
|
-
return true;
|
|
64
|
-
}
|
|
65
|
-
// If tools array exists and doesn't include this tool, it's effectively disabled
|
|
66
|
-
if (config.tools && !config.tools.includes(tool)) {
|
|
67
|
-
return true;
|
|
68
|
-
}
|
|
69
|
-
return false;
|
|
70
|
-
}
|
|
71
|
-
// Check global disablement
|
|
72
|
-
return config.enabled === false;
|
|
73
|
-
}
|
|
10
|
+
import { ALL_TOOL_IDS } from "@mycelish/core";
|
|
11
|
+
import { getTracer } from "../core/global-tracer.js";
|
|
12
|
+
import { loadStateManifest, saveStateManifest, ensureItem, findItemType, setItemInManifest, isValidToolId, resolveManifestDir, } from "../core/manifest-state.js";
|
|
13
|
+
import { getAllPluginsForComponent, setPluginEnabled, syncPluginSymlinks } from "../core/plugin-takeover.js";
|
|
14
|
+
import { scanPluginComponents } from "../core/plugin-scanner.js";
|
|
74
15
|
// ============================================================================
|
|
75
16
|
// Core Disable Function
|
|
76
17
|
// ============================================================================
|
|
77
18
|
/**
|
|
78
|
-
* Disable a skill or
|
|
19
|
+
* Disable a skill, MCP, hook, or memory item
|
|
79
20
|
*/
|
|
80
21
|
export async function disableSkillOrMcp(options) {
|
|
81
22
|
const { name, tool, global: isGlobal } = options;
|
|
23
|
+
const tracer = getTracer();
|
|
24
|
+
const log = tracer.createTrace("disable");
|
|
25
|
+
log.info({ scope: "manifest", op: "disable", msg: `Disabling ${name}`, item: name, tool });
|
|
82
26
|
// Validate tool if provided
|
|
83
27
|
if (tool && !isValidToolId(tool)) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
error: `Invalid tool: ${tool}. Supported tools: ${ALL_TOOL_IDS.join(", ")}`,
|
|
88
|
-
};
|
|
28
|
+
const error = `Invalid tool: ${tool}. Supported tools: ${ALL_TOOL_IDS.join(", ")}`;
|
|
29
|
+
log.error({ scope: "manifest", op: "disable", msg: error, item: name, error });
|
|
30
|
+
return { success: false, name, error };
|
|
89
31
|
}
|
|
90
|
-
|
|
91
|
-
const
|
|
92
|
-
? options.globalPath || expandPath("~/.mycelium")
|
|
93
|
-
: options.projectPath || path.join(process.cwd(), ".mycelium");
|
|
94
|
-
// Load manifest
|
|
95
|
-
const manifest = await loadManifest(manifestDir);
|
|
32
|
+
const manifestDir = resolveManifestDir(options);
|
|
33
|
+
const manifest = await loadStateManifest(manifestDir);
|
|
96
34
|
if (!manifest) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
error: `Could not load manifest from ${manifestDir}`,
|
|
101
|
-
};
|
|
35
|
+
const error = `Could not load manifest from ${manifestDir}`;
|
|
36
|
+
log.error({ scope: "manifest", op: "disable", msg: error, item: name, error });
|
|
37
|
+
return { success: false, name, error };
|
|
102
38
|
}
|
|
103
|
-
//
|
|
104
|
-
const
|
|
105
|
-
if (
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
39
|
+
// Pre-fetch matching plugins (used for type detection and takeover)
|
|
40
|
+
const matchingPlugins = !tool ? await getAllPluginsForComponent(name) : [];
|
|
41
|
+
// Detect type from plugin cache if available (agents/commands shouldn't default to "skill")
|
|
42
|
+
let typeHint;
|
|
43
|
+
for (const p of matchingPlugins) {
|
|
44
|
+
const components = await scanPluginComponents(p.cachePath, p.plugin, p.marketplace);
|
|
45
|
+
const match = components.find(c => c.name === name);
|
|
46
|
+
if (match) {
|
|
47
|
+
typeHint = match.type;
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// Detect MCP type from config files (mcps.yaml)
|
|
52
|
+
if (!typeHint) {
|
|
53
|
+
const { loadGlobalConfig } = await import("../core/config-merger.js");
|
|
54
|
+
const globalConfig = await loadGlobalConfig();
|
|
55
|
+
if (globalConfig.mcps?.[name])
|
|
56
|
+
typeHint = "mcp";
|
|
57
|
+
}
|
|
58
|
+
// Find or auto-register item
|
|
59
|
+
const { type, config, autoRegistered } = ensureItem(manifest, name, "enabled", typeHint);
|
|
60
|
+
if (autoRegistered) {
|
|
61
|
+
log.info({ scope: "manifest", op: "disable", msg: `Auto-registered '${name}' as ${type} in manifest`, item: name });
|
|
111
62
|
}
|
|
112
|
-
const { type, config } = item;
|
|
113
63
|
const level = isGlobal ? "global" : "project";
|
|
114
64
|
// Check if already disabled
|
|
115
65
|
if (isAlreadyDisabled(config, tool)) {
|
|
116
66
|
const toolMsg = tool ? ` for ${tool}` : "";
|
|
117
|
-
return {
|
|
118
|
-
success: true,
|
|
119
|
-
name,
|
|
120
|
-
type,
|
|
121
|
-
level,
|
|
122
|
-
tool,
|
|
123
|
-
alreadyDisabled: true,
|
|
124
|
-
message: `${type} '${name}' is already disabled${toolMsg}`,
|
|
125
|
-
};
|
|
67
|
+
return { success: true, name, type, level, tool, alreadyDisabled: true, message: `${type} '${name}' is already disabled${toolMsg}` };
|
|
126
68
|
}
|
|
127
|
-
//
|
|
69
|
+
// Apply disable
|
|
128
70
|
if (tool) {
|
|
129
|
-
|
|
130
|
-
// Add to excludeTools
|
|
131
|
-
if (!config.excludeTools) {
|
|
71
|
+
if (!config.excludeTools)
|
|
132
72
|
config.excludeTools = [];
|
|
133
|
-
|
|
134
|
-
if (!config.excludeTools.includes(tool)) {
|
|
73
|
+
if (!config.excludeTools.includes(tool))
|
|
135
74
|
config.excludeTools.push(tool);
|
|
136
|
-
}
|
|
137
|
-
// Remove from tools array if present
|
|
138
75
|
if (config.tools) {
|
|
139
76
|
config.tools = config.tools.filter((t) => t !== tool);
|
|
140
77
|
}
|
|
141
|
-
// Remove from enabledTools if present
|
|
142
78
|
if (config.enabledTools) {
|
|
143
79
|
config.enabledTools = config.enabledTools.filter((t) => t !== tool);
|
|
144
80
|
}
|
|
145
81
|
}
|
|
146
82
|
else {
|
|
147
|
-
|
|
148
|
-
config.enabled = false;
|
|
83
|
+
config.state = "disabled";
|
|
149
84
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
85
|
+
setItemInManifest(manifest, name, type, config);
|
|
86
|
+
await saveStateManifest(manifestDir, manifest);
|
|
87
|
+
// Remove MCP from tool configs immediately
|
|
88
|
+
if (type === "mcp") {
|
|
89
|
+
const { getAdapter } = await import("../core/tool-adapter.js");
|
|
90
|
+
const toolIds = tool ? [tool] : ALL_TOOL_IDS;
|
|
91
|
+
for (const tid of toolIds) {
|
|
92
|
+
try {
|
|
93
|
+
await getAdapter(tid).remove(name);
|
|
94
|
+
}
|
|
95
|
+
catch { /* tool may not be installed */ }
|
|
96
|
+
}
|
|
155
97
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
98
|
+
// Plugin takeover: if disabling any component that belongs to a Claude Code plugin,
|
|
99
|
+
// take over ALL enabled plugins containing it so Mycelium manages their skills.
|
|
100
|
+
let pluginTakeover = false;
|
|
101
|
+
if (!tool && matchingPlugins.length > 0) {
|
|
102
|
+
for (const pluginInfo of matchingPlugins) {
|
|
103
|
+
// Scan all component types from plugin cache
|
|
104
|
+
const allPluginComponents = await scanPluginComponents(pluginInfo.cachePath, pluginInfo.plugin, pluginInfo.marketplace);
|
|
105
|
+
const allComponentNames = allPluginComponents.map(c => c.name);
|
|
106
|
+
// Collect all disabled items from ALL sections for this plugin
|
|
107
|
+
const disabledItems = [];
|
|
108
|
+
const allPluginItemNames = new Set([...pluginInfo.allSkills, ...allComponentNames]);
|
|
109
|
+
for (const itemName of allPluginItemNames) {
|
|
110
|
+
const found = findItemType(manifest, itemName);
|
|
111
|
+
if (found?.config.state === "disabled")
|
|
112
|
+
disabledItems.push(itemName);
|
|
113
|
+
}
|
|
114
|
+
// Include the current item being disabled
|
|
115
|
+
if (allPluginItemNames.has(name) && !disabledItems.includes(name)) {
|
|
116
|
+
disabledItems.push(name);
|
|
117
|
+
}
|
|
118
|
+
// Disable plugin in Claude Code settings
|
|
119
|
+
await setPluginEnabled(pluginInfo.pluginId, false);
|
|
120
|
+
// Register plugin in takenOverPlugins with all component types
|
|
121
|
+
if (!manifest.takenOverPlugins)
|
|
122
|
+
manifest.takenOverPlugins = {};
|
|
123
|
+
manifest.takenOverPlugins[pluginInfo.pluginId] = {
|
|
124
|
+
version: pluginInfo.version,
|
|
125
|
+
cachePath: pluginInfo.cachePath,
|
|
126
|
+
allSkills: pluginInfo.allSkills,
|
|
127
|
+
allComponents: allComponentNames,
|
|
128
|
+
};
|
|
129
|
+
// Register all plugin components in manifest with pluginOrigin
|
|
130
|
+
const pluginOrigin = { pluginId: pluginInfo.pluginId, cachePath: pluginInfo.cachePath };
|
|
131
|
+
for (const comp of allPluginComponents) {
|
|
132
|
+
const sectionKey = comp.type === "skill" ? "skills" : comp.type === "agent" ? "agents" : comp.type === "command" ? "commands" : comp.type === "hook" ? "hooks" : null;
|
|
133
|
+
if (!sectionKey)
|
|
134
|
+
continue;
|
|
135
|
+
if (!manifest[sectionKey])
|
|
136
|
+
manifest[sectionKey] = {};
|
|
137
|
+
const section = manifest[sectionKey];
|
|
138
|
+
const existing = section[comp.name] ?? { state: "enabled" };
|
|
139
|
+
existing.pluginOrigin = pluginOrigin;
|
|
140
|
+
section[comp.name] = existing;
|
|
141
|
+
}
|
|
142
|
+
// Also register skills from pluginInfo.allSkills (fallback when cache scan returns partial/empty)
|
|
143
|
+
if (!manifest.skills)
|
|
144
|
+
manifest.skills = {};
|
|
145
|
+
for (const skillName of pluginInfo.allSkills) {
|
|
146
|
+
const existing = manifest.skills[skillName] ?? { state: "enabled" };
|
|
147
|
+
if (!existing.pluginOrigin)
|
|
148
|
+
existing.pluginOrigin = pluginOrigin;
|
|
149
|
+
manifest.skills[skillName] = existing;
|
|
150
|
+
}
|
|
151
|
+
log.info({ scope: "plugin", op: "takeover", msg: `Took over plugin: ${pluginInfo.pluginId}`, item: pluginInfo.pluginId, itemType: typeHint });
|
|
152
|
+
}
|
|
153
|
+
await saveStateManifest(manifestDir, manifest);
|
|
154
|
+
// Sync symlinks declaratively — single source of truth
|
|
155
|
+
await syncPluginSymlinks(manifestDir);
|
|
156
|
+
pluginTakeover = true;
|
|
157
|
+
}
|
|
158
|
+
// If the item belongs to an already-taken-over plugin, syncPluginSymlinks
|
|
159
|
+
// wasn't called above (matchingPlugins is empty for already-disabled plugins).
|
|
160
|
+
// Re-sync to remove the newly disabled item's symlink.
|
|
161
|
+
if (!pluginTakeover && !tool && manifest.takenOverPlugins && Object.keys(manifest.takenOverPlugins).length > 0) {
|
|
162
|
+
await syncPluginSymlinks(manifestDir);
|
|
160
163
|
}
|
|
161
|
-
// Save manifest
|
|
162
|
-
await saveManifest(manifestDir, manifest);
|
|
163
|
-
// Build success message
|
|
164
164
|
const toolMsg = tool ? ` for ${tool}` : "";
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
tool
|
|
171
|
-
|
|
172
|
-
|
|
165
|
+
log.info({ scope: "manifest", op: "disable", msg: `${type} '${name}' disabled${toolMsg}`, item: name, tool });
|
|
166
|
+
return { success: true, name, type, level, tool, pluginTakeover, message: `${type} '${name}' disabled${toolMsg}` };
|
|
167
|
+
}
|
|
168
|
+
function isAlreadyDisabled(config, tool) {
|
|
169
|
+
if (tool) {
|
|
170
|
+
if (config.excludeTools?.includes(tool))
|
|
171
|
+
return true;
|
|
172
|
+
if (config.tools && !config.tools.includes(tool))
|
|
173
|
+
return true;
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
return config.state === "disabled";
|
|
173
177
|
}
|
|
174
178
|
// ============================================================================
|
|
175
179
|
// Commander.js Command
|
|
176
180
|
// ============================================================================
|
|
177
181
|
export const disableCommand = new Command("disable")
|
|
178
|
-
.description("Disable a skill or
|
|
179
|
-
.argument("<name>", "Name of the
|
|
182
|
+
.description("Disable a skill, MCP, hook, or memory item")
|
|
183
|
+
.argument("<name>", "Name of the item to disable")
|
|
180
184
|
.option("-t, --tool <tool>", "Disable only for a specific tool")
|
|
181
185
|
.option("-g, --global", "Disable in global configuration (~/.mycelium/)")
|
|
182
186
|
.action(async (name, options) => {
|
|
@@ -191,6 +195,9 @@ export const disableCommand = new Command("disable")
|
|
|
191
195
|
}
|
|
192
196
|
else {
|
|
193
197
|
console.log(`\u2713 ${result.message}`);
|
|
198
|
+
if (result.pluginTakeover) {
|
|
199
|
+
console.log(` [experimental] Plugin takeover: plugin disabled in Claude Code, skills now managed by Mycelium`);
|
|
200
|
+
}
|
|
194
201
|
}
|
|
195
202
|
}
|
|
196
203
|
else {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"disable.js","sourceRoot":"","sources":["../../src/commands/disable.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,
|
|
1
|
+
{"version":3,"file":"disable.js","sourceRoot":"","sources":["../../src/commands/disable.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,17 +2,17 @@
|
|
|
2
2
|
* Tests for disable command module
|
|
3
3
|
* Tests written FIRST following TDD
|
|
4
4
|
*/
|
|
5
|
-
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
5
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
|
|
6
6
|
import * as fs from "node:fs/promises";
|
|
7
7
|
import * as path from "node:path";
|
|
8
8
|
import * as os from "node:os";
|
|
9
9
|
import { parse as yamlParse, stringify as yamlStringify } from "yaml";
|
|
10
|
-
// Import the module under test (doesn't exist yet - tests will fail)
|
|
11
10
|
import { disableSkillOrMcp, } from "./disable.js";
|
|
11
|
+
import * as pluginTakeover from "../core/plugin-takeover.js";
|
|
12
12
|
describe("Disable Command", () => {
|
|
13
13
|
let tempDir;
|
|
14
14
|
let globalMyceliumPath;
|
|
15
|
-
// Sample manifest configuration
|
|
15
|
+
// Sample manifest configuration using state instead of enabled
|
|
16
16
|
const sampleManifest = {
|
|
17
17
|
version: "1.0",
|
|
18
18
|
tools: {
|
|
@@ -25,33 +25,42 @@ describe("Disable Command", () => {
|
|
|
25
25
|
},
|
|
26
26
|
skills: {
|
|
27
27
|
superpowers: {
|
|
28
|
-
|
|
28
|
+
state: "enabled",
|
|
29
29
|
},
|
|
30
30
|
"disabled-skill": {
|
|
31
|
-
|
|
31
|
+
state: "disabled",
|
|
32
32
|
},
|
|
33
33
|
"tool-specific-skill": {
|
|
34
|
-
|
|
34
|
+
state: "enabled",
|
|
35
35
|
tools: ["claude-code", "codex"],
|
|
36
36
|
},
|
|
37
37
|
},
|
|
38
38
|
mcps: {
|
|
39
39
|
"whark-trading": {
|
|
40
|
-
|
|
40
|
+
state: "enabled",
|
|
41
41
|
},
|
|
42
42
|
"disabled-mcp": {
|
|
43
|
-
|
|
43
|
+
state: "disabled",
|
|
44
44
|
},
|
|
45
45
|
"tool-specific-mcp": {
|
|
46
|
-
|
|
46
|
+
state: "enabled",
|
|
47
47
|
tools: ["claude-code", "codex"],
|
|
48
48
|
},
|
|
49
49
|
},
|
|
50
|
+
hooks: {
|
|
51
|
+
"pre-commit": {
|
|
52
|
+
state: "enabled",
|
|
53
|
+
source: "project",
|
|
54
|
+
},
|
|
55
|
+
"disabled-hook": {
|
|
56
|
+
state: "disabled",
|
|
57
|
+
source: "global",
|
|
58
|
+
},
|
|
59
|
+
},
|
|
50
60
|
memory: {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
personal: { sync_to: ["openclaw"], path: "global/memory/personal/", files: [] },
|
|
61
|
+
"shared-context": {
|
|
62
|
+
state: "enabled",
|
|
63
|
+
source: "global",
|
|
55
64
|
},
|
|
56
65
|
},
|
|
57
66
|
};
|
|
@@ -80,7 +89,7 @@ describe("Disable Command", () => {
|
|
|
80
89
|
// Verify manifest was updated
|
|
81
90
|
const manifestContent = await fs.readFile(path.join(globalMyceliumPath, "manifest.yaml"), "utf-8");
|
|
82
91
|
const updatedManifest = yamlParse(manifestContent);
|
|
83
|
-
expect(updatedManifest.skills["superpowers"].
|
|
92
|
+
expect(updatedManifest.skills["superpowers"].state).toBe("disabled");
|
|
84
93
|
});
|
|
85
94
|
it("disables MCP globally", async () => {
|
|
86
95
|
const options = {
|
|
@@ -94,7 +103,7 @@ describe("Disable Command", () => {
|
|
|
94
103
|
// Verify manifest was updated
|
|
95
104
|
const manifestContent = await fs.readFile(path.join(globalMyceliumPath, "manifest.yaml"), "utf-8");
|
|
96
105
|
const updatedManifest = yamlParse(manifestContent);
|
|
97
|
-
expect(updatedManifest.mcps["whark-trading"].
|
|
106
|
+
expect(updatedManifest.mcps["whark-trading"].state).toBe("disabled");
|
|
98
107
|
});
|
|
99
108
|
});
|
|
100
109
|
describe("tool-specific disabling", () => {
|
|
@@ -147,7 +156,7 @@ describe("Disable Command", () => {
|
|
|
147
156
|
await disableSkillOrMcp(options);
|
|
148
157
|
const manifestContent = await fs.readFile(path.join(globalMyceliumPath, "manifest.yaml"), "utf-8");
|
|
149
158
|
const updatedManifest = yamlParse(manifestContent);
|
|
150
|
-
expect(updatedManifest.skills["superpowers"].
|
|
159
|
+
expect(updatedManifest.skills["superpowers"].state).toBe("disabled");
|
|
151
160
|
});
|
|
152
161
|
it("preserves other manifest settings when updating", async () => {
|
|
153
162
|
const options = {
|
|
@@ -161,8 +170,8 @@ describe("Disable Command", () => {
|
|
|
161
170
|
// Other settings should be preserved
|
|
162
171
|
expect(updatedManifest.version).toBe("1.0");
|
|
163
172
|
expect(updatedManifest.tools["claude-code"].enabled).toBe(true);
|
|
164
|
-
expect(updatedManifest.skills["disabled-skill"].
|
|
165
|
-
expect(updatedManifest.mcps["whark-trading"].
|
|
173
|
+
expect(updatedManifest.skills["disabled-skill"].state).toBe("disabled");
|
|
174
|
+
expect(updatedManifest.mcps["whark-trading"].state).toBe("enabled");
|
|
166
175
|
});
|
|
167
176
|
});
|
|
168
177
|
describe("success messages", () => {
|
|
@@ -233,7 +242,7 @@ describe("Disable Command", () => {
|
|
|
233
242
|
const projectManifest = {
|
|
234
243
|
version: "1.0",
|
|
235
244
|
skills: {
|
|
236
|
-
"project-skill": {
|
|
245
|
+
"project-skill": { state: "enabled" },
|
|
237
246
|
},
|
|
238
247
|
mcps: {},
|
|
239
248
|
};
|
|
@@ -249,7 +258,48 @@ describe("Disable Command", () => {
|
|
|
249
258
|
// Verify project manifest was updated
|
|
250
259
|
const manifestContent = await fs.readFile(path.join(projectPath, "manifest.yaml"), "utf-8");
|
|
251
260
|
const updatedManifest = yamlParse(manifestContent);
|
|
252
|
-
expect(updatedManifest.skills["project-skill"].
|
|
261
|
+
expect(updatedManifest.skills["project-skill"].state).toBe("disabled");
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
describe("hook and memory disabling", () => {
|
|
265
|
+
it("disables a hook globally", async () => {
|
|
266
|
+
const options = {
|
|
267
|
+
name: "pre-commit",
|
|
268
|
+
global: true,
|
|
269
|
+
globalPath: globalMyceliumPath,
|
|
270
|
+
};
|
|
271
|
+
const result = await disableSkillOrMcp(options);
|
|
272
|
+
expect(result.success).toBe(true);
|
|
273
|
+
expect(result.type).toBe("hook");
|
|
274
|
+
// Verify manifest was updated
|
|
275
|
+
const manifestContent = await fs.readFile(path.join(globalMyceliumPath, "manifest.yaml"), "utf-8");
|
|
276
|
+
const updatedManifest = yamlParse(manifestContent);
|
|
277
|
+
expect(updatedManifest.hooks["pre-commit"].state).toBe("disabled");
|
|
278
|
+
});
|
|
279
|
+
it("handles already disabled hook case", async () => {
|
|
280
|
+
const options = {
|
|
281
|
+
name: "disabled-hook",
|
|
282
|
+
global: true,
|
|
283
|
+
globalPath: globalMyceliumPath,
|
|
284
|
+
};
|
|
285
|
+
const result = await disableSkillOrMcp(options);
|
|
286
|
+
expect(result.success).toBe(true);
|
|
287
|
+
expect(result.alreadyDisabled).toBe(true);
|
|
288
|
+
expect(result.type).toBe("hook");
|
|
289
|
+
});
|
|
290
|
+
it("disables a memory item globally", async () => {
|
|
291
|
+
const options = {
|
|
292
|
+
name: "shared-context",
|
|
293
|
+
global: true,
|
|
294
|
+
globalPath: globalMyceliumPath,
|
|
295
|
+
};
|
|
296
|
+
const result = await disableSkillOrMcp(options);
|
|
297
|
+
expect(result.success).toBe(true);
|
|
298
|
+
expect(result.type).toBe("memory");
|
|
299
|
+
// Verify manifest was updated
|
|
300
|
+
const manifestContent = await fs.readFile(path.join(globalMyceliumPath, "manifest.yaml"), "utf-8");
|
|
301
|
+
const updatedManifest = yamlParse(manifestContent);
|
|
302
|
+
expect(updatedManifest.memory["shared-context"].state).toBe("disabled");
|
|
253
303
|
});
|
|
254
304
|
});
|
|
255
305
|
describe("error handling", () => {
|
|
@@ -263,15 +313,15 @@ describe("Disable Command", () => {
|
|
|
263
313
|
expect(result.success).toBe(false);
|
|
264
314
|
expect(result.error).toContain("manifest");
|
|
265
315
|
});
|
|
266
|
-
it("
|
|
316
|
+
it("auto-registers unknown item as skill and disables it", async () => {
|
|
267
317
|
const options = {
|
|
268
318
|
name: "non-existent-skill",
|
|
269
319
|
global: true,
|
|
270
320
|
globalPath: globalMyceliumPath,
|
|
271
321
|
};
|
|
272
322
|
const result = await disableSkillOrMcp(options);
|
|
273
|
-
expect(result.success).toBe(
|
|
274
|
-
expect(result.
|
|
323
|
+
expect(result.success).toBe(true);
|
|
324
|
+
expect(result.type).toBe("skill");
|
|
275
325
|
});
|
|
276
326
|
it("returns error for invalid tool name", async () => {
|
|
277
327
|
const options = {
|
|
@@ -285,6 +335,50 @@ describe("Disable Command", () => {
|
|
|
285
335
|
expect(result.error).toContain("Invalid tool");
|
|
286
336
|
});
|
|
287
337
|
});
|
|
338
|
+
describe("plugin takeover integration", () => {
|
|
339
|
+
it("triggers takeover when disabling a plugin skill", async () => {
|
|
340
|
+
const spy = vi.spyOn(pluginTakeover, "getAllPluginsForComponent").mockResolvedValue([{
|
|
341
|
+
pluginId: "my-plugin@skillsmp",
|
|
342
|
+
marketplace: "skillsmp",
|
|
343
|
+
plugin: "my-plugin",
|
|
344
|
+
version: "1.0.0",
|
|
345
|
+
cachePath: "/fake/cache/path",
|
|
346
|
+
allSkills: ["superpowers", "bonus-skill"],
|
|
347
|
+
enabledSkills: ["superpowers", "bonus-skill"],
|
|
348
|
+
}]);
|
|
349
|
+
const setEnabledSpy = vi.spyOn(pluginTakeover, "setPluginEnabled").mockResolvedValue(undefined);
|
|
350
|
+
const syncSpy = vi.spyOn(pluginTakeover, "syncPluginSymlinks").mockResolvedValue({ created: ["bonus-skill"], removed: [] });
|
|
351
|
+
const result = await disableSkillOrMcp({
|
|
352
|
+
name: "superpowers",
|
|
353
|
+
global: true,
|
|
354
|
+
globalPath: globalMyceliumPath,
|
|
355
|
+
});
|
|
356
|
+
expect(result.success).toBe(true);
|
|
357
|
+
expect(result.pluginTakeover).toBe(true);
|
|
358
|
+
expect(spy).toHaveBeenCalledWith("superpowers");
|
|
359
|
+
expect(setEnabledSpy).toHaveBeenCalledWith("my-plugin@skillsmp", false);
|
|
360
|
+
expect(syncSpy).toHaveBeenCalled();
|
|
361
|
+
// Verify manifest has takenOverPlugins
|
|
362
|
+
const manifest = yamlParse(await fs.readFile(path.join(globalMyceliumPath, "manifest.yaml"), "utf-8"));
|
|
363
|
+
expect(manifest.takenOverPlugins?.["my-plugin@skillsmp"]).toBeDefined();
|
|
364
|
+
expect(manifest.skills?.["superpowers"]?.pluginOrigin?.pluginId).toBe("my-plugin@skillsmp");
|
|
365
|
+
spy.mockRestore();
|
|
366
|
+
setEnabledSpy.mockRestore();
|
|
367
|
+
syncSpy.mockRestore();
|
|
368
|
+
});
|
|
369
|
+
it("does NOT trigger takeover for non-plugin skills", async () => {
|
|
370
|
+
const spy = vi.spyOn(pluginTakeover, "getAllPluginsForComponent").mockResolvedValue([]);
|
|
371
|
+
const result = await disableSkillOrMcp({
|
|
372
|
+
name: "superpowers",
|
|
373
|
+
global: true,
|
|
374
|
+
globalPath: globalMyceliumPath,
|
|
375
|
+
});
|
|
376
|
+
expect(result.success).toBe(true);
|
|
377
|
+
expect(result.pluginTakeover).toBeFalsy();
|
|
378
|
+
expect(spy).toHaveBeenCalledWith("superpowers");
|
|
379
|
+
spy.mockRestore();
|
|
380
|
+
});
|
|
381
|
+
});
|
|
288
382
|
});
|
|
289
383
|
});
|
|
290
384
|
//# sourceMappingURL=disable.test.js.map
|