@mycelish/cli 0.1.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/LICENSE +21 -0
- package/dist/__tests__/init-auto.test.d.ts +2 -0
- package/dist/__tests__/init-auto.test.d.ts.map +1 -0
- package/dist/__tests__/init-auto.test.js +60 -0
- package/dist/__tests__/init-auto.test.js.map +1 -0
- package/dist/commands/add.d.ts +20 -0
- package/dist/commands/add.d.ts.map +1 -0
- package/dist/commands/add.js +99 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/add.test.d.ts +25 -0
- package/dist/commands/add.test.d.ts.map +1 -0
- package/dist/commands/add.test.js +574 -0
- package/dist/commands/add.test.js.map +1 -0
- package/dist/commands/disable.d.ts +33 -0
- package/dist/commands/disable.d.ts.map +1 -0
- package/dist/commands/disable.js +201 -0
- package/dist/commands/disable.js.map +1 -0
- package/dist/commands/disable.test.d.ts +6 -0
- package/dist/commands/disable.test.d.ts.map +1 -0
- package/dist/commands/disable.test.js +290 -0
- package/dist/commands/disable.test.js.map +1 -0
- package/dist/commands/doctor.d.ts +11 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +33 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/doctor.test.d.ts +17 -0
- package/dist/commands/doctor.test.d.ts.map +1 -0
- package/dist/commands/doctor.test.js +691 -0
- package/dist/commands/doctor.test.js.map +1 -0
- package/dist/commands/enable.d.ts +33 -0
- package/dist/commands/enable.d.ts.map +1 -0
- package/dist/commands/enable.js +199 -0
- package/dist/commands/enable.js.map +1 -0
- package/dist/commands/enable.test.d.ts +6 -0
- package/dist/commands/enable.test.d.ts.map +1 -0
- package/dist/commands/enable.test.js +301 -0
- package/dist/commands/enable.test.js.map +1 -0
- package/dist/commands/health-checks/config-check.d.ts +34 -0
- package/dist/commands/health-checks/config-check.d.ts.map +1 -0
- package/dist/commands/health-checks/config-check.js +267 -0
- package/dist/commands/health-checks/config-check.js.map +1 -0
- package/dist/commands/health-checks/formatter.d.ts +13 -0
- package/dist/commands/health-checks/formatter.d.ts.map +1 -0
- package/dist/commands/health-checks/formatter.js +72 -0
- package/dist/commands/health-checks/formatter.js.map +1 -0
- package/dist/commands/health-checks/index.d.ts +8 -0
- package/dist/commands/health-checks/index.d.ts.map +1 -0
- package/dist/commands/health-checks/index.js +7 -0
- package/dist/commands/health-checks/index.js.map +1 -0
- package/dist/commands/health-checks/mcp-check.d.ts +9 -0
- package/dist/commands/health-checks/mcp-check.d.ts.map +1 -0
- package/dist/commands/health-checks/mcp-check.js +37 -0
- package/dist/commands/health-checks/mcp-check.js.map +1 -0
- package/dist/commands/health-checks/memory-check.d.ts +15 -0
- package/dist/commands/health-checks/memory-check.d.ts.map +1 -0
- package/dist/commands/health-checks/memory-check.js +92 -0
- package/dist/commands/health-checks/memory-check.js.map +1 -0
- package/dist/commands/health-checks/runner.d.ts +9 -0
- package/dist/commands/health-checks/runner.d.ts.map +1 -0
- package/dist/commands/health-checks/runner.js +74 -0
- package/dist/commands/health-checks/runner.js.map +1 -0
- package/dist/commands/health-checks/tool-version-check.d.ts +9 -0
- package/dist/commands/health-checks/tool-version-check.d.ts.map +1 -0
- package/dist/commands/health-checks/tool-version-check.js +35 -0
- package/dist/commands/health-checks/tool-version-check.js.map +1 -0
- package/dist/commands/health-checks/types.d.ts +16 -0
- package/dist/commands/health-checks/types.d.ts.map +1 -0
- package/dist/commands/health-checks/types.js +2 -0
- package/dist/commands/health-checks/types.js.map +1 -0
- package/dist/commands/init.d.ts +120 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +436 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/init.test.d.ts +16 -0
- package/dist/commands/init.test.d.ts.map +1 -0
- package/dist/commands/init.test.js +286 -0
- package/dist/commands/init.test.js.map +1 -0
- package/dist/commands/marketplace.d.ts +13 -0
- package/dist/commands/marketplace.d.ts.map +1 -0
- package/dist/commands/marketplace.js +85 -0
- package/dist/commands/marketplace.js.map +1 -0
- package/dist/commands/marketplace.test.d.ts +2 -0
- package/dist/commands/marketplace.test.d.ts.map +1 -0
- package/dist/commands/marketplace.test.js +78 -0
- package/dist/commands/marketplace.test.js.map +1 -0
- package/dist/commands/migrate.d.ts +15 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +179 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/migrate.test.d.ts +2 -0
- package/dist/commands/migrate.test.d.ts.map +1 -0
- package/dist/commands/migrate.test.js +109 -0
- package/dist/commands/migrate.test.js.map +1 -0
- package/dist/commands/preset.d.ts +11 -0
- package/dist/commands/preset.d.ts.map +1 -0
- package/dist/commands/preset.js +99 -0
- package/dist/commands/preset.js.map +1 -0
- package/dist/commands/preset.test.d.ts +2 -0
- package/dist/commands/preset.test.d.ts.map +1 -0
- package/dist/commands/preset.test.js +106 -0
- package/dist/commands/preset.test.js.map +1 -0
- package/dist/commands/remote.d.ts +9 -0
- package/dist/commands/remote.d.ts.map +1 -0
- package/dist/commands/remote.js +212 -0
- package/dist/commands/remote.js.map +1 -0
- package/dist/commands/remote.test.d.ts +2 -0
- package/dist/commands/remote.test.d.ts.map +1 -0
- package/dist/commands/remote.test.js +125 -0
- package/dist/commands/remote.test.js.map +1 -0
- package/dist/commands/remove.d.ts +34 -0
- package/dist/commands/remove.d.ts.map +1 -0
- package/dist/commands/remove.js +296 -0
- package/dist/commands/remove.js.map +1 -0
- package/dist/commands/remove.test.d.ts +2 -0
- package/dist/commands/remove.test.d.ts.map +1 -0
- package/dist/commands/remove.test.js +109 -0
- package/dist/commands/remove.test.js.map +1 -0
- package/dist/commands/serve.d.ts +3 -0
- package/dist/commands/serve.d.ts.map +1 -0
- package/dist/commands/serve.js +29 -0
- package/dist/commands/serve.js.map +1 -0
- package/dist/commands/serve.test.d.ts +2 -0
- package/dist/commands/serve.test.d.ts.map +1 -0
- package/dist/commands/serve.test.js +74 -0
- package/dist/commands/serve.test.js.map +1 -0
- package/dist/commands/status.d.ts +49 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +272 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/status.test.d.ts +11 -0
- package/dist/commands/status.test.d.ts.map +1 -0
- package/dist/commands/status.test.js +334 -0
- package/dist/commands/status.test.js.map +1 -0
- package/dist/commands/sync.d.ts +38 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +286 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/commands/sync.test.d.ts +6 -0
- package/dist/commands/sync.test.d.ts.map +1 -0
- package/dist/commands/sync.test.js +341 -0
- package/dist/commands/sync.test.js.map +1 -0
- package/dist/commands/teams.d.ts +18 -0
- package/dist/commands/teams.d.ts.map +1 -0
- package/dist/commands/teams.js +68 -0
- package/dist/commands/teams.js.map +1 -0
- package/dist/commands/teams.test.d.ts +2 -0
- package/dist/commands/teams.test.d.ts.map +1 -0
- package/dist/commands/teams.test.js +94 -0
- package/dist/commands/teams.test.js.map +1 -0
- package/dist/core/adapter-base.d.ts +51 -0
- package/dist/core/adapter-base.d.ts.map +1 -0
- package/dist/core/adapter-base.js +89 -0
- package/dist/core/adapter-base.js.map +1 -0
- package/dist/core/add-helpers.d.ts +55 -0
- package/dist/core/add-helpers.d.ts.map +1 -0
- package/dist/core/add-helpers.js +273 -0
- package/dist/core/add-helpers.js.map +1 -0
- package/dist/core/agent-teams.d.ts +10 -0
- package/dist/core/agent-teams.d.ts.map +1 -0
- package/dist/core/agent-teams.js +40 -0
- package/dist/core/agent-teams.js.map +1 -0
- package/dist/core/agent-teams.test.d.ts +2 -0
- package/dist/core/agent-teams.test.d.ts.map +1 -0
- package/dist/core/agent-teams.test.js +64 -0
- package/dist/core/agent-teams.test.js.map +1 -0
- package/dist/core/auto-adapter.d.ts +27 -0
- package/dist/core/auto-adapter.d.ts.map +1 -0
- package/dist/core/auto-adapter.js +324 -0
- package/dist/core/auto-adapter.js.map +1 -0
- package/dist/core/auto-adapter.test.d.ts +2 -0
- package/dist/core/auto-adapter.test.d.ts.map +1 -0
- package/dist/core/auto-adapter.test.js +125 -0
- package/dist/core/auto-adapter.test.js.map +1 -0
- package/dist/core/config-merger.d.ts +33 -0
- package/dist/core/config-merger.d.ts.map +1 -0
- package/dist/core/config-merger.js +238 -0
- package/dist/core/config-merger.js.map +1 -0
- package/dist/core/config-merger.test.d.ts +10 -0
- package/dist/core/config-merger.test.d.ts.map +1 -0
- package/dist/core/config-merger.test.js +406 -0
- package/dist/core/config-merger.test.js.map +1 -0
- package/dist/core/conflict-detector.d.ts +23 -0
- package/dist/core/conflict-detector.d.ts.map +1 -0
- package/dist/core/conflict-detector.js +58 -0
- package/dist/core/conflict-detector.js.map +1 -0
- package/dist/core/conflict-detector.test.d.ts +2 -0
- package/dist/core/conflict-detector.test.d.ts.map +1 -0
- package/dist/core/conflict-detector.test.js +40 -0
- package/dist/core/conflict-detector.test.js.map +1 -0
- package/dist/core/env-template.d.ts +22 -0
- package/dist/core/env-template.d.ts.map +1 -0
- package/dist/core/env-template.js +125 -0
- package/dist/core/env-template.js.map +1 -0
- package/dist/core/env-template.test.d.ts +2 -0
- package/dist/core/env-template.test.d.ts.map +1 -0
- package/dist/core/env-template.test.js +145 -0
- package/dist/core/env-template.test.js.map +1 -0
- package/dist/core/fs-helpers.d.ts +8 -0
- package/dist/core/fs-helpers.d.ts.map +1 -0
- package/dist/core/fs-helpers.js +26 -0
- package/dist/core/fs-helpers.js.map +1 -0
- package/dist/core/fs-helpers.test.d.ts +2 -0
- package/dist/core/fs-helpers.test.d.ts.map +1 -0
- package/dist/core/fs-helpers.test.js +51 -0
- package/dist/core/fs-helpers.test.js.map +1 -0
- package/dist/core/machine-overrides.d.ts +13 -0
- package/dist/core/machine-overrides.d.ts.map +1 -0
- package/dist/core/machine-overrides.js +155 -0
- package/dist/core/machine-overrides.js.map +1 -0
- package/dist/core/machine-overrides.test.d.ts +2 -0
- package/dist/core/machine-overrides.test.d.ts.map +1 -0
- package/dist/core/machine-overrides.test.js +160 -0
- package/dist/core/machine-overrides.test.js.map +1 -0
- package/dist/core/marketplace-registry.d.ts +14 -0
- package/dist/core/marketplace-registry.d.ts.map +1 -0
- package/dist/core/marketplace-registry.js +215 -0
- package/dist/core/marketplace-registry.js.map +1 -0
- package/dist/core/marketplace-registry.test.d.ts +2 -0
- package/dist/core/marketplace-registry.test.d.ts.map +1 -0
- package/dist/core/marketplace-registry.test.js +232 -0
- package/dist/core/marketplace-registry.test.js.map +1 -0
- package/dist/core/marketplace-sources.d.ts +39 -0
- package/dist/core/marketplace-sources.d.ts.map +1 -0
- package/dist/core/marketplace-sources.js +199 -0
- package/dist/core/marketplace-sources.js.map +1 -0
- package/dist/core/marketplace.d.ts +18 -0
- package/dist/core/marketplace.d.ts.map +1 -0
- package/dist/core/marketplace.js +211 -0
- package/dist/core/marketplace.js.map +1 -0
- package/dist/core/marketplace.test.d.ts +2 -0
- package/dist/core/marketplace.test.d.ts.map +1 -0
- package/dist/core/marketplace.test.js +177 -0
- package/dist/core/marketplace.test.js.map +1 -0
- package/dist/core/mcp-injector.d.ts +43 -0
- package/dist/core/mcp-injector.d.ts.map +1 -0
- package/dist/core/mcp-injector.js +164 -0
- package/dist/core/mcp-injector.js.map +1 -0
- package/dist/core/mcp-injector.test.d.ts +6 -0
- package/dist/core/mcp-injector.test.d.ts.map +1 -0
- package/dist/core/mcp-injector.test.js +315 -0
- package/dist/core/mcp-injector.test.js.map +1 -0
- package/dist/core/mcp-registry.d.ts +17 -0
- package/dist/core/mcp-registry.d.ts.map +1 -0
- package/dist/core/mcp-registry.js +52 -0
- package/dist/core/mcp-registry.js.map +1 -0
- package/dist/core/mcp-registry.test.d.ts +2 -0
- package/dist/core/mcp-registry.test.d.ts.map +1 -0
- package/dist/core/mcp-registry.test.js +78 -0
- package/dist/core/mcp-registry.test.js.map +1 -0
- package/dist/core/mcp-router.d.ts +21 -0
- package/dist/core/mcp-router.d.ts.map +1 -0
- package/dist/core/mcp-router.js +67 -0
- package/dist/core/mcp-router.js.map +1 -0
- package/dist/core/mcp-router.test.d.ts +2 -0
- package/dist/core/mcp-router.test.d.ts.map +1 -0
- package/dist/core/mcp-router.test.js +40 -0
- package/dist/core/mcp-router.test.js.map +1 -0
- package/dist/core/memory-scoper.d.ts +43 -0
- package/dist/core/memory-scoper.d.ts.map +1 -0
- package/dist/core/memory-scoper.js +165 -0
- package/dist/core/memory-scoper.js.map +1 -0
- package/dist/core/memory-scoper.test.d.ts +6 -0
- package/dist/core/memory-scoper.test.d.ts.map +1 -0
- package/dist/core/memory-scoper.test.js +467 -0
- package/dist/core/memory-scoper.test.js.map +1 -0
- package/dist/core/migrator/executor.d.ts +9 -0
- package/dist/core/migrator/executor.d.ts.map +1 -0
- package/dist/core/migrator/executor.js +233 -0
- package/dist/core/migrator/executor.js.map +1 -0
- package/dist/core/migrator/index.d.ts +8 -0
- package/dist/core/migrator/index.d.ts.map +1 -0
- package/dist/core/migrator/index.js +12 -0
- package/dist/core/migrator/index.js.map +1 -0
- package/dist/core/migrator/manifest.d.ts +8 -0
- package/dist/core/migrator/manifest.d.ts.map +1 -0
- package/dist/core/migrator/manifest.js +83 -0
- package/dist/core/migrator/manifest.js.map +1 -0
- package/dist/core/migrator/planner.d.ts +6 -0
- package/dist/core/migrator/planner.d.ts.map +1 -0
- package/dist/core/migrator/planner.js +112 -0
- package/dist/core/migrator/planner.js.map +1 -0
- package/dist/core/migrator/scanners.d.ts +19 -0
- package/dist/core/migrator/scanners.d.ts.map +1 -0
- package/dist/core/migrator/scanners.js +612 -0
- package/dist/core/migrator/scanners.js.map +1 -0
- package/dist/core/migrator/scanners.test.d.ts +2 -0
- package/dist/core/migrator/scanners.test.d.ts.map +1 -0
- package/dist/core/migrator/scanners.test.js +257 -0
- package/dist/core/migrator/scanners.test.js.map +1 -0
- package/dist/core/migrator.test.d.ts +2 -0
- package/dist/core/migrator.test.d.ts.map +1 -0
- package/dist/core/migrator.test.js +451 -0
- package/dist/core/migrator.test.js.map +1 -0
- package/dist/core/plugin-scanner.d.ts +30 -0
- package/dist/core/plugin-scanner.d.ts.map +1 -0
- package/dist/core/plugin-scanner.js +174 -0
- package/dist/core/plugin-scanner.js.map +1 -0
- package/dist/core/plugin-scanner.test.d.ts +2 -0
- package/dist/core/plugin-scanner.test.d.ts.map +1 -0
- package/dist/core/plugin-scanner.test.js +279 -0
- package/dist/core/plugin-scanner.test.js.map +1 -0
- package/dist/core/presets.d.ts +55 -0
- package/dist/core/presets.d.ts.map +1 -0
- package/dist/core/presets.js +84 -0
- package/dist/core/presets.js.map +1 -0
- package/dist/core/presets.test.d.ts +2 -0
- package/dist/core/presets.test.d.ts.map +1 -0
- package/dist/core/presets.test.js +40 -0
- package/dist/core/presets.test.js.map +1 -0
- package/dist/core/skill-parser.d.ts +21 -0
- package/dist/core/skill-parser.d.ts.map +1 -0
- package/dist/core/skill-parser.js +53 -0
- package/dist/core/skill-parser.js.map +1 -0
- package/dist/core/skill-parser.test.d.ts +2 -0
- package/dist/core/skill-parser.test.d.ts.map +1 -0
- package/dist/core/skill-parser.test.js +83 -0
- package/dist/core/skill-parser.test.js.map +1 -0
- package/dist/core/smart-memory.d.ts +22 -0
- package/dist/core/smart-memory.d.ts.map +1 -0
- package/dist/core/smart-memory.js +72 -0
- package/dist/core/smart-memory.js.map +1 -0
- package/dist/core/smart-memory.test.d.ts +2 -0
- package/dist/core/smart-memory.test.d.ts.map +1 -0
- package/dist/core/smart-memory.test.js +114 -0
- package/dist/core/smart-memory.test.js.map +1 -0
- package/dist/core/snapshot.d.ts +6 -0
- package/dist/core/snapshot.d.ts.map +1 -0
- package/dist/core/snapshot.js +179 -0
- package/dist/core/snapshot.js.map +1 -0
- package/dist/core/snapshot.test.d.ts +2 -0
- package/dist/core/snapshot.test.d.ts.map +1 -0
- package/dist/core/snapshot.test.js +132 -0
- package/dist/core/snapshot.test.js.map +1 -0
- package/dist/core/symlink-manager.d.ts +78 -0
- package/dist/core/symlink-manager.d.ts.map +1 -0
- package/dist/core/symlink-manager.js +227 -0
- package/dist/core/symlink-manager.js.map +1 -0
- package/dist/core/symlink-manager.test.d.ts +8 -0
- package/dist/core/symlink-manager.test.d.ts.map +1 -0
- package/dist/core/symlink-manager.test.js +354 -0
- package/dist/core/symlink-manager.test.js.map +1 -0
- package/dist/core/sync-writer.d.ts +20 -0
- package/dist/core/sync-writer.d.ts.map +1 -0
- package/dist/core/sync-writer.js +150 -0
- package/dist/core/sync-writer.js.map +1 -0
- package/dist/core/sync-writer.test.d.ts +2 -0
- package/dist/core/sync-writer.test.d.ts.map +1 -0
- package/dist/core/sync-writer.test.js +134 -0
- package/dist/core/sync-writer.test.js.map +1 -0
- package/dist/core/toml-helpers.d.ts +9 -0
- package/dist/core/toml-helpers.d.ts.map +1 -0
- package/dist/core/toml-helpers.js +33 -0
- package/dist/core/toml-helpers.js.map +1 -0
- package/dist/core/tool-adapter.d.ts +24 -0
- package/dist/core/tool-adapter.d.ts.map +1 -0
- package/dist/core/tool-adapter.js +156 -0
- package/dist/core/tool-adapter.js.map +1 -0
- package/dist/core/tool-adapter.test.d.ts +2 -0
- package/dist/core/tool-adapter.test.d.ts.map +1 -0
- package/dist/core/tool-adapter.test.js +264 -0
- package/dist/core/tool-adapter.test.js.map +1 -0
- package/dist/core/tool-detector.d.ts +31 -0
- package/dist/core/tool-detector.d.ts.map +1 -0
- package/dist/core/tool-detector.js +67 -0
- package/dist/core/tool-detector.js.map +1 -0
- package/dist/core/tool-detector.test.d.ts +2 -0
- package/dist/core/tool-detector.test.d.ts.map +1 -0
- package/dist/core/tool-detector.test.js +126 -0
- package/dist/core/tool-detector.test.js.map +1 -0
- package/dist/core/watcher.d.ts +22 -0
- package/dist/core/watcher.d.ts.map +1 -0
- package/dist/core/watcher.js +68 -0
- package/dist/core/watcher.js.map +1 -0
- package/dist/core/watcher.test.d.ts +2 -0
- package/dist/core/watcher.test.d.ts.map +1 -0
- package/dist/core/watcher.test.js +26 -0
- package/dist/core/watcher.test.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -0
- package/dist/routes/async-handler.d.ts +6 -0
- package/dist/routes/async-handler.d.ts.map +1 -0
- package/dist/routes/async-handler.js +9 -0
- package/dist/routes/async-handler.js.map +1 -0
- package/dist/routes/marketplace.d.ts +3 -0
- package/dist/routes/marketplace.d.ts.map +1 -0
- package/dist/routes/marketplace.js +51 -0
- package/dist/routes/marketplace.js.map +1 -0
- package/dist/routes/migrate.d.ts +3 -0
- package/dist/routes/migrate.d.ts.map +1 -0
- package/dist/routes/migrate.js +22 -0
- package/dist/routes/migrate.js.map +1 -0
- package/dist/routes/plugin-map.d.ts +11 -0
- package/dist/routes/plugin-map.d.ts.map +1 -0
- package/dist/routes/plugin-map.js +37 -0
- package/dist/routes/plugin-map.js.map +1 -0
- package/dist/routes/plugins.d.ts +3 -0
- package/dist/routes/plugins.d.ts.map +1 -0
- package/dist/routes/plugins.js +51 -0
- package/dist/routes/plugins.js.map +1 -0
- package/dist/routes/remove.d.ts +3 -0
- package/dist/routes/remove.d.ts.map +1 -0
- package/dist/routes/remove.js +27 -0
- package/dist/routes/remove.js.map +1 -0
- package/dist/routes/state.d.ts +3 -0
- package/dist/routes/state.d.ts.map +1 -0
- package/dist/routes/state.js +177 -0
- package/dist/routes/state.js.map +1 -0
- package/dist/routes/sync.d.ts +3 -0
- package/dist/routes/sync.d.ts.map +1 -0
- package/dist/routes/sync.js +12 -0
- package/dist/routes/sync.js.map +1 -0
- package/dist/server.d.ts +4 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +59 -0
- package/dist/server.js.map +1 -0
- package/package.json +48 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Snapshot — create, restore, list, and delete config snapshots
|
|
3
|
+
*/
|
|
4
|
+
import * as fs from "node:fs/promises";
|
|
5
|
+
import * as path from "node:path";
|
|
6
|
+
import { mkdirp, MYCELIUM_HOME } from "./fs-helpers.js";
|
|
7
|
+
function getMyceliumDir() {
|
|
8
|
+
return MYCELIUM_HOME;
|
|
9
|
+
}
|
|
10
|
+
function getSnapshotsDir() {
|
|
11
|
+
return path.join(getMyceliumDir(), "snapshots");
|
|
12
|
+
}
|
|
13
|
+
/** Files to capture relative to getMyceliumDir() */
|
|
14
|
+
const SNAPSHOT_FILES = [
|
|
15
|
+
"global/mcps.yaml",
|
|
16
|
+
"global/hooks.yaml",
|
|
17
|
+
"migration-manifest.json",
|
|
18
|
+
"marketplaces.yaml",
|
|
19
|
+
];
|
|
20
|
+
const VALID_NAME = /^[a-zA-Z0-9-]+$/;
|
|
21
|
+
// ============================================================================
|
|
22
|
+
// Helpers
|
|
23
|
+
// ============================================================================
|
|
24
|
+
async function copyIfExists(src, dest) {
|
|
25
|
+
try {
|
|
26
|
+
await mkdirp(path.dirname(dest));
|
|
27
|
+
await fs.copyFile(src, dest);
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async function copyDirRecursive(src, dest) {
|
|
35
|
+
const files = [];
|
|
36
|
+
try {
|
|
37
|
+
const entries = await fs.readdir(src, { withFileTypes: true });
|
|
38
|
+
await mkdirp(dest);
|
|
39
|
+
for (const entry of entries) {
|
|
40
|
+
const srcPath = path.join(src, entry.name);
|
|
41
|
+
const destPath = path.join(dest, entry.name);
|
|
42
|
+
if (entry.isDirectory()) {
|
|
43
|
+
files.push(...(await copyDirRecursive(srcPath, destPath)));
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
await fs.copyFile(srcPath, destPath);
|
|
47
|
+
files.push(entry.name);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
// directory doesn't exist, skip
|
|
53
|
+
}
|
|
54
|
+
return files;
|
|
55
|
+
}
|
|
56
|
+
async function rmrf(dir) {
|
|
57
|
+
await fs.rm(dir, { recursive: true, force: true });
|
|
58
|
+
}
|
|
59
|
+
// ============================================================================
|
|
60
|
+
// Public API
|
|
61
|
+
// ============================================================================
|
|
62
|
+
export async function createSnapshot(name, description) {
|
|
63
|
+
if (!VALID_NAME.test(name)) {
|
|
64
|
+
throw new Error(`Invalid snapshot name "${name}": only alphanumeric characters and hyphens are allowed`);
|
|
65
|
+
}
|
|
66
|
+
const snapshotDir = path.join(getSnapshotsDir(), name);
|
|
67
|
+
// Check for duplicates
|
|
68
|
+
try {
|
|
69
|
+
await fs.access(snapshotDir);
|
|
70
|
+
throw new Error(`Snapshot "${name}" already exists`);
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
if (err.message.includes("already exists"))
|
|
74
|
+
throw err;
|
|
75
|
+
// ENOENT is expected
|
|
76
|
+
}
|
|
77
|
+
await mkdirp(snapshotDir);
|
|
78
|
+
const fileList = [];
|
|
79
|
+
// Copy individual files
|
|
80
|
+
for (const relPath of SNAPSHOT_FILES) {
|
|
81
|
+
const src = path.join(getMyceliumDir(), relPath);
|
|
82
|
+
const dest = path.join(snapshotDir, relPath);
|
|
83
|
+
if (await copyIfExists(src, dest)) {
|
|
84
|
+
fileList.push(relPath);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// Copy memory directory
|
|
88
|
+
const memoryFiles = await copyDirRecursive(path.join(getMyceliumDir(), "memory"), path.join(snapshotDir, "memory"));
|
|
89
|
+
for (const f of memoryFiles) {
|
|
90
|
+
fileList.push(`memory/${f}`);
|
|
91
|
+
}
|
|
92
|
+
// Read symlinks in global/skills/
|
|
93
|
+
const skillSymlinks = {};
|
|
94
|
+
const skillsDir = path.join(getMyceliumDir(), "global", "skills");
|
|
95
|
+
try {
|
|
96
|
+
const entries = await fs.readdir(skillsDir);
|
|
97
|
+
for (const entry of entries) {
|
|
98
|
+
const fullPath = path.join(skillsDir, entry);
|
|
99
|
+
try {
|
|
100
|
+
const target = await fs.readlink(fullPath);
|
|
101
|
+
skillSymlinks[entry] = target;
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
// Not a symlink, skip
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
// skills dir doesn't exist
|
|
110
|
+
}
|
|
111
|
+
const metadata = {
|
|
112
|
+
name,
|
|
113
|
+
createdAt: new Date().toISOString(),
|
|
114
|
+
description,
|
|
115
|
+
skillSymlinks,
|
|
116
|
+
fileList,
|
|
117
|
+
};
|
|
118
|
+
await fs.writeFile(path.join(snapshotDir, "metadata.json"), JSON.stringify(metadata, null, 2));
|
|
119
|
+
return metadata;
|
|
120
|
+
}
|
|
121
|
+
export async function restoreSnapshot(name) {
|
|
122
|
+
const snapshotDir = path.join(getSnapshotsDir(), name);
|
|
123
|
+
let raw;
|
|
124
|
+
try {
|
|
125
|
+
raw = await fs.readFile(path.join(snapshotDir, "metadata.json"), "utf-8");
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
throw new Error(`Snapshot "${name}" not found`);
|
|
129
|
+
}
|
|
130
|
+
const metadata = JSON.parse(raw);
|
|
131
|
+
// Remove current config files
|
|
132
|
+
for (const relPath of SNAPSHOT_FILES) {
|
|
133
|
+
await fs.rm(path.join(getMyceliumDir(), relPath), { force: true });
|
|
134
|
+
}
|
|
135
|
+
await rmrf(path.join(getMyceliumDir(), "memory"));
|
|
136
|
+
await rmrf(path.join(getMyceliumDir(), "global", "skills"));
|
|
137
|
+
// Restore files
|
|
138
|
+
for (const relPath of metadata.fileList) {
|
|
139
|
+
const src = path.join(snapshotDir, relPath);
|
|
140
|
+
const dest = path.join(getMyceliumDir(), relPath);
|
|
141
|
+
await copyIfExists(src, dest);
|
|
142
|
+
}
|
|
143
|
+
// Recreate symlinks
|
|
144
|
+
const skillsDir = path.join(getMyceliumDir(), "global", "skills");
|
|
145
|
+
await mkdirp(skillsDir);
|
|
146
|
+
for (const [linkName, target] of Object.entries(metadata.skillSymlinks)) {
|
|
147
|
+
await fs.symlink(target, path.join(skillsDir, linkName));
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
export async function listSnapshots() {
|
|
151
|
+
const results = [];
|
|
152
|
+
try {
|
|
153
|
+
const entries = await fs.readdir(getSnapshotsDir());
|
|
154
|
+
for (const entry of entries) {
|
|
155
|
+
try {
|
|
156
|
+
const raw = await fs.readFile(path.join(getSnapshotsDir(), entry, "metadata.json"), "utf-8");
|
|
157
|
+
results.push(JSON.parse(raw));
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
// skip invalid entries
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
// snapshots dir doesn't exist yet
|
|
166
|
+
}
|
|
167
|
+
return results.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
|
|
168
|
+
}
|
|
169
|
+
export async function deleteSnapshot(name) {
|
|
170
|
+
const snapshotDir = path.join(getSnapshotsDir(), name);
|
|
171
|
+
try {
|
|
172
|
+
await fs.access(snapshotDir);
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
throw new Error(`Snapshot "${name}" not found`);
|
|
176
|
+
}
|
|
177
|
+
await rmrf(snapshotDir);
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=snapshot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../src/core/snapshot.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot.test.d.ts","sourceRoot":"","sources":["../../src/core/snapshot.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the Snapshot module
|
|
3
|
+
*/
|
|
4
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
|
|
5
|
+
import * as fs from "node:fs/promises";
|
|
6
|
+
import * as path from "node:path";
|
|
7
|
+
import * as os from "node:os";
|
|
8
|
+
// We mock os.homedir to point to a temp directory so snapshot.ts operates in isolation
|
|
9
|
+
let tmpDir;
|
|
10
|
+
vi.mock("node:os", async () => {
|
|
11
|
+
const actual = await vi.importActual("node:os");
|
|
12
|
+
return {
|
|
13
|
+
...actual,
|
|
14
|
+
homedir: () => tmpDir,
|
|
15
|
+
};
|
|
16
|
+
});
|
|
17
|
+
// Mock fs-helpers to avoid MYCELIUM_HOME evaluation at import time (os.homedir() is undefined then)
|
|
18
|
+
vi.mock("./fs-helpers.js", async () => {
|
|
19
|
+
const fsp = await import("node:fs/promises");
|
|
20
|
+
const osMod = await import("node:os");
|
|
21
|
+
const pathMod = await import("node:path");
|
|
22
|
+
return {
|
|
23
|
+
mkdirp: (dir) => fsp.mkdir(dir, { recursive: true }),
|
|
24
|
+
get MYCELIUM_HOME() { return pathMod.join(osMod.homedir(), ".mycelium"); },
|
|
25
|
+
DEFAULT_PORT: 3378,
|
|
26
|
+
MEMORY_LINE_LIMIT: 200,
|
|
27
|
+
readFileIfExists: vi.fn(),
|
|
28
|
+
};
|
|
29
|
+
});
|
|
30
|
+
// Must import after mock setup
|
|
31
|
+
const { createSnapshot, restoreSnapshot, listSnapshots, deleteSnapshot } = await import("./snapshot.js");
|
|
32
|
+
async function setupMyceliumDir() {
|
|
33
|
+
const myceliumDir = path.join(tmpDir, ".mycelium");
|
|
34
|
+
await fs.mkdir(path.join(myceliumDir, "global", "skills"), { recursive: true });
|
|
35
|
+
await fs.mkdir(path.join(myceliumDir, "memory"), { recursive: true });
|
|
36
|
+
await fs.writeFile(path.join(myceliumDir, "global", "mcps.yaml"), "mcps:\n test: {}\n");
|
|
37
|
+
await fs.writeFile(path.join(myceliumDir, "global", "hooks.yaml"), "hooks: []\n");
|
|
38
|
+
await fs.writeFile(path.join(myceliumDir, "memory", "shared.md"), "# Shared memory\n");
|
|
39
|
+
await fs.writeFile(path.join(myceliumDir, "migration-manifest.json"), '{"version":"1","entries":[]}');
|
|
40
|
+
await fs.writeFile(path.join(myceliumDir, "marketplaces.yaml"), "sources: {}\n");
|
|
41
|
+
// Create a symlink in skills
|
|
42
|
+
const targetDir = path.join(tmpDir, "skill-target");
|
|
43
|
+
await fs.mkdir(targetDir, { recursive: true });
|
|
44
|
+
await fs.symlink(targetDir, path.join(myceliumDir, "global", "skills", "my-skill"));
|
|
45
|
+
return myceliumDir;
|
|
46
|
+
}
|
|
47
|
+
beforeEach(async () => {
|
|
48
|
+
tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "snapshot-test-"));
|
|
49
|
+
});
|
|
50
|
+
afterEach(async () => {
|
|
51
|
+
await fs.rm(tmpDir, { recursive: true, force: true });
|
|
52
|
+
});
|
|
53
|
+
describe("createSnapshot", () => {
|
|
54
|
+
it("captures files and symlink targets in metadata", async () => {
|
|
55
|
+
await setupMyceliumDir();
|
|
56
|
+
const meta = await createSnapshot("test-snap", "A test snapshot");
|
|
57
|
+
expect(meta.name).toBe("test-snap");
|
|
58
|
+
expect(meta.description).toBe("A test snapshot");
|
|
59
|
+
expect(meta.fileList).toContain("global/mcps.yaml");
|
|
60
|
+
expect(meta.fileList).toContain("memory/shared.md");
|
|
61
|
+
expect(meta.skillSymlinks["my-skill"]).toBeDefined();
|
|
62
|
+
// Verify metadata.json was written
|
|
63
|
+
const raw = await fs.readFile(path.join(tmpDir, ".mycelium", "snapshots", "test-snap", "metadata.json"), "utf-8");
|
|
64
|
+
const saved = JSON.parse(raw);
|
|
65
|
+
expect(saved.name).toBe("test-snap");
|
|
66
|
+
});
|
|
67
|
+
it("throws on duplicate name", async () => {
|
|
68
|
+
await setupMyceliumDir();
|
|
69
|
+
await createSnapshot("dup");
|
|
70
|
+
await expect(createSnapshot("dup")).rejects.toThrow("already exists");
|
|
71
|
+
});
|
|
72
|
+
it("throws on invalid name with spaces", async () => {
|
|
73
|
+
await setupMyceliumDir();
|
|
74
|
+
await expect(createSnapshot("bad name")).rejects.toThrow("Invalid snapshot name");
|
|
75
|
+
});
|
|
76
|
+
it("throws on invalid name with slashes", async () => {
|
|
77
|
+
await setupMyceliumDir();
|
|
78
|
+
await expect(createSnapshot("bad/name")).rejects.toThrow("Invalid snapshot name");
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
describe("restoreSnapshot", () => {
|
|
82
|
+
it("recreates files and symlinks", async () => {
|
|
83
|
+
const myceliumDir = await setupMyceliumDir();
|
|
84
|
+
await createSnapshot("restore-test");
|
|
85
|
+
// Delete the originals
|
|
86
|
+
await fs.rm(path.join(myceliumDir, "global", "mcps.yaml"));
|
|
87
|
+
await fs.rm(path.join(myceliumDir, "global", "skills", "my-skill"));
|
|
88
|
+
await fs.rm(path.join(myceliumDir, "memory"), { recursive: true });
|
|
89
|
+
await restoreSnapshot("restore-test");
|
|
90
|
+
// Verify restored
|
|
91
|
+
const mcps = await fs.readFile(path.join(myceliumDir, "global", "mcps.yaml"), "utf-8");
|
|
92
|
+
expect(mcps).toContain("mcps:");
|
|
93
|
+
const symlinkTarget = await fs.readlink(path.join(myceliumDir, "global", "skills", "my-skill"));
|
|
94
|
+
expect(symlinkTarget).toContain("skill-target");
|
|
95
|
+
});
|
|
96
|
+
it("throws on non-existent snapshot", async () => {
|
|
97
|
+
await setupMyceliumDir();
|
|
98
|
+
await expect(restoreSnapshot("nope")).rejects.toThrow("not found");
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
describe("listSnapshots", () => {
|
|
102
|
+
it("returns snapshots sorted by date descending", async () => {
|
|
103
|
+
await setupMyceliumDir();
|
|
104
|
+
await createSnapshot("first");
|
|
105
|
+
// Small delay to ensure different timestamps
|
|
106
|
+
await new Promise((r) => setTimeout(r, 10));
|
|
107
|
+
await createSnapshot("second");
|
|
108
|
+
const list = await listSnapshots();
|
|
109
|
+
expect(list).toHaveLength(2);
|
|
110
|
+
expect(list[0].name).toBe("second");
|
|
111
|
+
expect(list[1].name).toBe("first");
|
|
112
|
+
});
|
|
113
|
+
it("returns empty array when no snapshots exist", async () => {
|
|
114
|
+
await setupMyceliumDir();
|
|
115
|
+
const list = await listSnapshots();
|
|
116
|
+
expect(list).toEqual([]);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
describe("deleteSnapshot", () => {
|
|
120
|
+
it("removes snapshot directory", async () => {
|
|
121
|
+
await setupMyceliumDir();
|
|
122
|
+
await createSnapshot("to-delete");
|
|
123
|
+
await deleteSnapshot("to-delete");
|
|
124
|
+
const list = await listSnapshots();
|
|
125
|
+
expect(list).toHaveLength(0);
|
|
126
|
+
});
|
|
127
|
+
it("throws on non-existent snapshot", async () => {
|
|
128
|
+
await setupMyceliumDir();
|
|
129
|
+
await expect(deleteSnapshot("nope")).rejects.toThrow("not found");
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
//# sourceMappingURL=snapshot.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot.test.js","sourceRoot":"","sources":["../../src/core/snapshot.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Symlink Manager for Mycelium
|
|
3
|
+
*
|
|
4
|
+
* Handles creating, updating, and removing symlinks from the global
|
|
5
|
+
* skills directory to tool-specific directories.
|
|
6
|
+
*/
|
|
7
|
+
export interface CreateSymlinkResult {
|
|
8
|
+
success: boolean;
|
|
9
|
+
action: "created" | "updated" | "replaced" | "unchanged" | "error";
|
|
10
|
+
backupPath?: string;
|
|
11
|
+
error?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface RemoveSymlinkResult {
|
|
14
|
+
success: boolean;
|
|
15
|
+
existed: boolean;
|
|
16
|
+
error?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface SymlinkValidation {
|
|
19
|
+
valid: boolean;
|
|
20
|
+
exists?: boolean;
|
|
21
|
+
isSymlink?: boolean;
|
|
22
|
+
currentTarget?: string;
|
|
23
|
+
expectedTarget?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface SkillSymlinkStatus {
|
|
26
|
+
skillName: string;
|
|
27
|
+
skillPath: string;
|
|
28
|
+
symlinkPath: string;
|
|
29
|
+
exists: boolean;
|
|
30
|
+
valid: boolean;
|
|
31
|
+
currentTarget?: string;
|
|
32
|
+
}
|
|
33
|
+
export interface Skill {
|
|
34
|
+
name: string;
|
|
35
|
+
path: string;
|
|
36
|
+
manifest: {
|
|
37
|
+
name: string;
|
|
38
|
+
enabled?: boolean;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export interface SyncOptions {
|
|
42
|
+
removeOrphans?: boolean;
|
|
43
|
+
}
|
|
44
|
+
export interface SyncResult {
|
|
45
|
+
success: boolean;
|
|
46
|
+
created: string[];
|
|
47
|
+
updated: string[];
|
|
48
|
+
removed: string[];
|
|
49
|
+
unchanged: string[];
|
|
50
|
+
errors: Array<{
|
|
51
|
+
skill: string;
|
|
52
|
+
error: string;
|
|
53
|
+
}>;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Create a symlink from a skill source path to a tool directory location.
|
|
57
|
+
* Handles existing symlinks, files, and directories appropriately.
|
|
58
|
+
*/
|
|
59
|
+
export declare function createSkillSymlink(sourcePath: string, symlinkPath: string): Promise<CreateSymlinkResult>;
|
|
60
|
+
/**
|
|
61
|
+
* Remove a symlink. Only removes actual symlinks, not regular files/directories.
|
|
62
|
+
*/
|
|
63
|
+
export declare function removeSkillSymlink(symlinkPath: string): Promise<RemoveSymlinkResult>;
|
|
64
|
+
/**
|
|
65
|
+
* Check if a symlink exists and points to the expected target.
|
|
66
|
+
*/
|
|
67
|
+
export declare function isSymlinkValid(symlinkPath: string, expectedTarget: string): Promise<SymlinkValidation>;
|
|
68
|
+
/**
|
|
69
|
+
* Get the status of symlinks for a list of skills in a tool directory.
|
|
70
|
+
*/
|
|
71
|
+
export declare function getSymlinkStatus(skills: Skill[], toolSkillsDir: string): Promise<SkillSymlinkStatus[]>;
|
|
72
|
+
/**
|
|
73
|
+
* Sync all skills to a specific tool directory.
|
|
74
|
+
* Creates symlinks for enabled skills, removes symlinks for disabled skills,
|
|
75
|
+
* and optionally removes orphaned symlinks.
|
|
76
|
+
*/
|
|
77
|
+
export declare function syncSkillsToTool(skills: Skill[], toolSkillsDir: string, options?: SyncOptions): Promise<SyncResult>;
|
|
78
|
+
//# sourceMappingURL=symlink-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"symlink-manager.d.ts","sourceRoot":"","sources":["../../src/core/symlink-manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,UAAU,GAAG,WAAW,GAAG,OAAO,CAAC;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB,CAAC;CACH;AAED,MAAM,WAAW,WAAW;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjD;AAMD;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,mBAAmB,CAAC,CA4C9B;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,mBAAmB,CAAC,CA6B9B;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,iBAAiB,CAAC,CAgC5B;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,KAAK,EAAE,EACf,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAkB/B;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,KAAK,EAAE,EACf,aAAa,EAAE,MAAM,EACrB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,UAAU,CAAC,CAsFrB"}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Symlink Manager for Mycelium
|
|
3
|
+
*
|
|
4
|
+
* Handles creating, updating, and removing symlinks from the global
|
|
5
|
+
* skills directory to tool-specific directories.
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from "node:fs/promises";
|
|
8
|
+
import * as path from "node:path";
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// Core Functions
|
|
11
|
+
// ============================================================================
|
|
12
|
+
/**
|
|
13
|
+
* Create a symlink from a skill source path to a tool directory location.
|
|
14
|
+
* Handles existing symlinks, files, and directories appropriately.
|
|
15
|
+
*/
|
|
16
|
+
export async function createSkillSymlink(sourcePath, symlinkPath) {
|
|
17
|
+
try {
|
|
18
|
+
// Ensure parent directory exists
|
|
19
|
+
const parentDir = path.dirname(symlinkPath);
|
|
20
|
+
await fs.mkdir(parentDir, { recursive: true });
|
|
21
|
+
// Check if something exists at the symlink path
|
|
22
|
+
let stats;
|
|
23
|
+
try {
|
|
24
|
+
stats = await fs.lstat(symlinkPath);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// Path doesn't exist, create new symlink
|
|
28
|
+
await fs.symlink(sourcePath, symlinkPath);
|
|
29
|
+
return { success: true, action: "created" };
|
|
30
|
+
}
|
|
31
|
+
// Something exists at the path
|
|
32
|
+
if (stats.isSymbolicLink()) {
|
|
33
|
+
// Check if it points to the correct target
|
|
34
|
+
const currentTarget = await fs.readlink(symlinkPath);
|
|
35
|
+
if (currentTarget === sourcePath) {
|
|
36
|
+
return { success: true, action: "unchanged" };
|
|
37
|
+
}
|
|
38
|
+
// Update symlink to new target
|
|
39
|
+
await fs.unlink(symlinkPath);
|
|
40
|
+
await fs.symlink(sourcePath, symlinkPath);
|
|
41
|
+
return { success: true, action: "updated" };
|
|
42
|
+
}
|
|
43
|
+
// Not a symlink - backup and replace
|
|
44
|
+
const backupPath = `${symlinkPath}.backup.${Date.now()}`;
|
|
45
|
+
await fs.rename(symlinkPath, backupPath);
|
|
46
|
+
await fs.symlink(sourcePath, symlinkPath);
|
|
47
|
+
return { success: true, action: "replaced", backupPath };
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
return {
|
|
51
|
+
success: false,
|
|
52
|
+
action: "error",
|
|
53
|
+
error: error instanceof Error ? error.message : String(error),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Remove a symlink. Only removes actual symlinks, not regular files/directories.
|
|
59
|
+
*/
|
|
60
|
+
export async function removeSkillSymlink(symlinkPath) {
|
|
61
|
+
try {
|
|
62
|
+
// Check if path exists
|
|
63
|
+
let stats;
|
|
64
|
+
try {
|
|
65
|
+
stats = await fs.lstat(symlinkPath);
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
// Path doesn't exist
|
|
69
|
+
return { success: true, existed: false };
|
|
70
|
+
}
|
|
71
|
+
// Only remove if it's a symlink
|
|
72
|
+
if (!stats.isSymbolicLink()) {
|
|
73
|
+
return {
|
|
74
|
+
success: false,
|
|
75
|
+
existed: true,
|
|
76
|
+
error: `Path exists but is not a symlink: ${symlinkPath}`,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
await fs.unlink(symlinkPath);
|
|
80
|
+
return { success: true, existed: true };
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
return {
|
|
84
|
+
success: false,
|
|
85
|
+
existed: true,
|
|
86
|
+
error: error instanceof Error ? error.message : String(error),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Check if a symlink exists and points to the expected target.
|
|
92
|
+
*/
|
|
93
|
+
export async function isSymlinkValid(symlinkPath, expectedTarget) {
|
|
94
|
+
try {
|
|
95
|
+
// Check if path exists
|
|
96
|
+
let stats;
|
|
97
|
+
try {
|
|
98
|
+
stats = await fs.lstat(symlinkPath);
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return { valid: false, exists: false };
|
|
102
|
+
}
|
|
103
|
+
// Check if it's a symlink
|
|
104
|
+
if (!stats.isSymbolicLink()) {
|
|
105
|
+
return { valid: false, exists: true, isSymlink: false };
|
|
106
|
+
}
|
|
107
|
+
// Check if it points to the correct target
|
|
108
|
+
const currentTarget = await fs.readlink(symlinkPath);
|
|
109
|
+
if (currentTarget === expectedTarget) {
|
|
110
|
+
return { valid: true, currentTarget };
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
valid: false,
|
|
114
|
+
exists: true,
|
|
115
|
+
isSymlink: true,
|
|
116
|
+
currentTarget,
|
|
117
|
+
expectedTarget,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
return { valid: false };
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Get the status of symlinks for a list of skills in a tool directory.
|
|
126
|
+
*/
|
|
127
|
+
export async function getSymlinkStatus(skills, toolSkillsDir) {
|
|
128
|
+
const statuses = [];
|
|
129
|
+
for (const skill of skills) {
|
|
130
|
+
const symlinkPath = path.join(toolSkillsDir, skill.name);
|
|
131
|
+
const validation = await isSymlinkValid(symlinkPath, skill.path);
|
|
132
|
+
statuses.push({
|
|
133
|
+
skillName: skill.name,
|
|
134
|
+
skillPath: skill.path,
|
|
135
|
+
symlinkPath,
|
|
136
|
+
exists: validation.exists !== false,
|
|
137
|
+
valid: validation.valid,
|
|
138
|
+
currentTarget: validation.currentTarget,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
return statuses;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Sync all skills to a specific tool directory.
|
|
145
|
+
* Creates symlinks for enabled skills, removes symlinks for disabled skills,
|
|
146
|
+
* and optionally removes orphaned symlinks.
|
|
147
|
+
*/
|
|
148
|
+
export async function syncSkillsToTool(skills, toolSkillsDir, options = {}) {
|
|
149
|
+
const result = {
|
|
150
|
+
success: true,
|
|
151
|
+
created: [],
|
|
152
|
+
updated: [],
|
|
153
|
+
removed: [],
|
|
154
|
+
unchanged: [],
|
|
155
|
+
errors: [],
|
|
156
|
+
};
|
|
157
|
+
// Ensure tool skills directory exists
|
|
158
|
+
await fs.mkdir(toolSkillsDir, { recursive: true });
|
|
159
|
+
// Build set of skill names for orphan detection
|
|
160
|
+
const skillNames = new Set(skills.map((s) => s.name));
|
|
161
|
+
// Process each skill
|
|
162
|
+
for (const skill of skills) {
|
|
163
|
+
const symlinkPath = path.join(toolSkillsDir, skill.name);
|
|
164
|
+
const isEnabled = skill.manifest.enabled !== false;
|
|
165
|
+
if (isEnabled) {
|
|
166
|
+
// Create or update symlink
|
|
167
|
+
const createResult = await createSkillSymlink(skill.path, symlinkPath);
|
|
168
|
+
if (createResult.success) {
|
|
169
|
+
switch (createResult.action) {
|
|
170
|
+
case "created":
|
|
171
|
+
result.created.push(skill.name);
|
|
172
|
+
break;
|
|
173
|
+
case "updated":
|
|
174
|
+
case "replaced":
|
|
175
|
+
result.updated.push(skill.name);
|
|
176
|
+
break;
|
|
177
|
+
case "unchanged":
|
|
178
|
+
result.unchanged.push(skill.name);
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
result.success = false;
|
|
184
|
+
result.errors.push({ skill: skill.name, error: createResult.error || "Unknown error" });
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
// Remove symlink for disabled skill
|
|
189
|
+
const removeResult = await removeSkillSymlink(symlinkPath);
|
|
190
|
+
if (removeResult.existed) {
|
|
191
|
+
result.removed.push(skill.name);
|
|
192
|
+
}
|
|
193
|
+
if (!removeResult.success && removeResult.existed) {
|
|
194
|
+
result.errors.push({ skill: skill.name, error: removeResult.error || "Unknown error" });
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
// Handle orphaned symlinks
|
|
199
|
+
if (options.removeOrphans) {
|
|
200
|
+
try {
|
|
201
|
+
const entries = await fs.readdir(toolSkillsDir, { withFileTypes: true });
|
|
202
|
+
for (const entry of entries) {
|
|
203
|
+
// Skip if this is a known skill
|
|
204
|
+
if (skillNames.has(entry.name)) {
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
const entryPath = path.join(toolSkillsDir, entry.name);
|
|
208
|
+
// Only remove symlinks
|
|
209
|
+
try {
|
|
210
|
+
const stats = await fs.lstat(entryPath);
|
|
211
|
+
if (stats.isSymbolicLink()) {
|
|
212
|
+
await fs.unlink(entryPath);
|
|
213
|
+
result.removed.push(entry.name);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
catch {
|
|
217
|
+
// Ignore errors for individual entries
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
catch {
|
|
222
|
+
// Ignore errors reading directory
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return result;
|
|
226
|
+
}
|
|
227
|
+
//# sourceMappingURL=symlink-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"symlink-manager.js","sourceRoot":"","sources":["../../src/core/symlink-manager.ts"],"names":[],"mappings":"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"}
|