claude-autopm 2.7.0 → 2.8.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/README.md +307 -56
- package/autopm/.claude/.env +158 -0
- package/autopm/.claude/settings.local.json +9 -0
- package/bin/autopm.js +11 -2
- package/bin/commands/epic.js +23 -3
- package/bin/commands/plugin.js +395 -0
- package/bin/commands/team.js +184 -10
- package/install/install.js +223 -4
- package/lib/cli/commands/issue.js +360 -20
- package/lib/plugins/PluginManager.js +1328 -0
- package/lib/plugins/PluginManager.old.js +400 -0
- package/lib/providers/AzureDevOpsProvider.js +575 -0
- package/lib/providers/GitHubProvider.js +475 -0
- package/lib/services/EpicService.js +1092 -3
- package/lib/services/IssueService.js +991 -0
- package/package.json +9 -1
- package/scripts/publish-plugins.sh +166 -0
- package/autopm/.claude/agents/cloud/README.md +0 -55
- package/autopm/.claude/agents/cloud/aws-cloud-architect.md +0 -521
- package/autopm/.claude/agents/cloud/azure-cloud-architect.md +0 -436
- package/autopm/.claude/agents/cloud/gcp-cloud-architect.md +0 -385
- package/autopm/.claude/agents/cloud/gcp-cloud-functions-engineer.md +0 -306
- package/autopm/.claude/agents/cloud/gemini-api-expert.md +0 -880
- package/autopm/.claude/agents/cloud/kubernetes-orchestrator.md +0 -566
- package/autopm/.claude/agents/cloud/openai-python-expert.md +0 -1087
- package/autopm/.claude/agents/cloud/terraform-infrastructure-expert.md +0 -454
- package/autopm/.claude/agents/core/agent-manager.md +0 -296
- package/autopm/.claude/agents/core/code-analyzer.md +0 -131
- package/autopm/.claude/agents/core/file-analyzer.md +0 -162
- package/autopm/.claude/agents/core/test-runner.md +0 -200
- package/autopm/.claude/agents/data/airflow-orchestration-expert.md +0 -52
- package/autopm/.claude/agents/data/kedro-pipeline-expert.md +0 -50
- package/autopm/.claude/agents/data/langgraph-workflow-expert.md +0 -520
- package/autopm/.claude/agents/databases/README.md +0 -50
- package/autopm/.claude/agents/databases/bigquery-expert.md +0 -392
- package/autopm/.claude/agents/databases/cosmosdb-expert.md +0 -368
- package/autopm/.claude/agents/databases/mongodb-expert.md +0 -398
- package/autopm/.claude/agents/databases/postgresql-expert.md +0 -321
- package/autopm/.claude/agents/databases/redis-expert.md +0 -52
- package/autopm/.claude/agents/devops/README.md +0 -52
- package/autopm/.claude/agents/devops/azure-devops-specialist.md +0 -308
- package/autopm/.claude/agents/devops/docker-containerization-expert.md +0 -298
- package/autopm/.claude/agents/devops/github-operations-specialist.md +0 -335
- package/autopm/.claude/agents/devops/mcp-context-manager.md +0 -319
- package/autopm/.claude/agents/devops/observability-engineer.md +0 -574
- package/autopm/.claude/agents/devops/ssh-operations-expert.md +0 -1093
- package/autopm/.claude/agents/devops/traefik-proxy-expert.md +0 -444
- package/autopm/.claude/agents/frameworks/README.md +0 -64
- package/autopm/.claude/agents/frameworks/e2e-test-engineer.md +0 -360
- package/autopm/.claude/agents/frameworks/nats-messaging-expert.md +0 -254
- package/autopm/.claude/agents/frameworks/react-frontend-engineer.md +0 -217
- package/autopm/.claude/agents/frameworks/react-ui-expert.md +0 -226
- package/autopm/.claude/agents/frameworks/tailwindcss-expert.md +0 -770
- package/autopm/.claude/agents/frameworks/ux-design-expert.md +0 -244
- package/autopm/.claude/agents/integration/message-queue-engineer.md +0 -794
- package/autopm/.claude/agents/languages/README.md +0 -50
- package/autopm/.claude/agents/languages/bash-scripting-expert.md +0 -541
- package/autopm/.claude/agents/languages/javascript-frontend-engineer.md +0 -197
- package/autopm/.claude/agents/languages/nodejs-backend-engineer.md +0 -226
- package/autopm/.claude/agents/languages/python-backend-engineer.md +0 -214
- package/autopm/.claude/agents/languages/python-backend-expert.md +0 -289
- package/autopm/.claude/agents/testing/frontend-testing-engineer.md +0 -395
- package/autopm/.claude/commands/ai/langgraph-workflow.md +0 -65
- package/autopm/.claude/commands/ai/openai-chat.md +0 -65
- package/autopm/.claude/commands/azure/COMMANDS.md +0 -107
- package/autopm/.claude/commands/azure/COMMAND_MAPPING.md +0 -252
- package/autopm/.claude/commands/azure/INTEGRATION_FIX.md +0 -103
- package/autopm/.claude/commands/azure/README.md +0 -246
- package/autopm/.claude/commands/azure/active-work.md +0 -198
- package/autopm/.claude/commands/azure/aliases.md +0 -143
- package/autopm/.claude/commands/azure/blocked-items.md +0 -287
- package/autopm/.claude/commands/azure/clean.md +0 -93
- package/autopm/.claude/commands/azure/docs-query.md +0 -48
- package/autopm/.claude/commands/azure/feature-decompose.md +0 -380
- package/autopm/.claude/commands/azure/feature-list.md +0 -61
- package/autopm/.claude/commands/azure/feature-new.md +0 -115
- package/autopm/.claude/commands/azure/feature-show.md +0 -205
- package/autopm/.claude/commands/azure/feature-start.md +0 -130
- package/autopm/.claude/commands/azure/fix-integration-example.md +0 -93
- package/autopm/.claude/commands/azure/help.md +0 -150
- package/autopm/.claude/commands/azure/import-us.md +0 -269
- package/autopm/.claude/commands/azure/init.md +0 -211
- package/autopm/.claude/commands/azure/next-task.md +0 -262
- package/autopm/.claude/commands/azure/search.md +0 -160
- package/autopm/.claude/commands/azure/sprint-status.md +0 -235
- package/autopm/.claude/commands/azure/standup.md +0 -260
- package/autopm/.claude/commands/azure/sync-all.md +0 -99
- package/autopm/.claude/commands/azure/task-analyze.md +0 -186
- package/autopm/.claude/commands/azure/task-close.md +0 -329
- package/autopm/.claude/commands/azure/task-edit.md +0 -145
- package/autopm/.claude/commands/azure/task-list.md +0 -263
- package/autopm/.claude/commands/azure/task-new.md +0 -84
- package/autopm/.claude/commands/azure/task-reopen.md +0 -79
- package/autopm/.claude/commands/azure/task-show.md +0 -126
- package/autopm/.claude/commands/azure/task-start.md +0 -301
- package/autopm/.claude/commands/azure/task-status.md +0 -65
- package/autopm/.claude/commands/azure/task-sync.md +0 -67
- package/autopm/.claude/commands/azure/us-edit.md +0 -164
- package/autopm/.claude/commands/azure/us-list.md +0 -202
- package/autopm/.claude/commands/azure/us-new.md +0 -265
- package/autopm/.claude/commands/azure/us-parse.md +0 -253
- package/autopm/.claude/commands/azure/us-show.md +0 -188
- package/autopm/.claude/commands/azure/us-status.md +0 -320
- package/autopm/.claude/commands/azure/validate.md +0 -86
- package/autopm/.claude/commands/azure/work-item-sync.md +0 -47
- package/autopm/.claude/commands/cloud/infra-deploy.md +0 -38
- package/autopm/.claude/commands/github/workflow-create.md +0 -42
- package/autopm/.claude/commands/infrastructure/ssh-security.md +0 -65
- package/autopm/.claude/commands/infrastructure/traefik-setup.md +0 -65
- package/autopm/.claude/commands/kubernetes/deploy.md +0 -37
- package/autopm/.claude/commands/playwright/test-scaffold.md +0 -38
- package/autopm/.claude/commands/pm/blocked.md +0 -28
- package/autopm/.claude/commands/pm/clean.md +0 -119
- package/autopm/.claude/commands/pm/context-create.md +0 -136
- package/autopm/.claude/commands/pm/context-prime.md +0 -170
- package/autopm/.claude/commands/pm/context-update.md +0 -292
- package/autopm/.claude/commands/pm/context.md +0 -28
- package/autopm/.claude/commands/pm/epic-close.md +0 -86
- package/autopm/.claude/commands/pm/epic-decompose.md +0 -370
- package/autopm/.claude/commands/pm/epic-edit.md +0 -83
- package/autopm/.claude/commands/pm/epic-list.md +0 -30
- package/autopm/.claude/commands/pm/epic-merge.md +0 -222
- package/autopm/.claude/commands/pm/epic-oneshot.md +0 -119
- package/autopm/.claude/commands/pm/epic-refresh.md +0 -119
- package/autopm/.claude/commands/pm/epic-show.md +0 -28
- package/autopm/.claude/commands/pm/epic-split.md +0 -120
- package/autopm/.claude/commands/pm/epic-start.md +0 -195
- package/autopm/.claude/commands/pm/epic-status.md +0 -28
- package/autopm/.claude/commands/pm/epic-sync-modular.md +0 -338
- package/autopm/.claude/commands/pm/epic-sync-original.md +0 -473
- package/autopm/.claude/commands/pm/epic-sync.md +0 -486
- package/autopm/.claude/commands/pm/help.md +0 -28
- package/autopm/.claude/commands/pm/import.md +0 -115
- package/autopm/.claude/commands/pm/in-progress.md +0 -28
- package/autopm/.claude/commands/pm/init.md +0 -28
- package/autopm/.claude/commands/pm/issue-analyze.md +0 -202
- package/autopm/.claude/commands/pm/issue-close.md +0 -119
- package/autopm/.claude/commands/pm/issue-edit.md +0 -93
- package/autopm/.claude/commands/pm/issue-reopen.md +0 -87
- package/autopm/.claude/commands/pm/issue-show.md +0 -41
- package/autopm/.claude/commands/pm/issue-start.md +0 -234
- package/autopm/.claude/commands/pm/issue-status.md +0 -95
- package/autopm/.claude/commands/pm/issue-sync.md +0 -411
- package/autopm/.claude/commands/pm/next.md +0 -28
- package/autopm/.claude/commands/pm/prd-edit.md +0 -82
- package/autopm/.claude/commands/pm/prd-list.md +0 -28
- package/autopm/.claude/commands/pm/prd-new.md +0 -55
- package/autopm/.claude/commands/pm/prd-parse.md +0 -42
- package/autopm/.claude/commands/pm/prd-status.md +0 -28
- package/autopm/.claude/commands/pm/search.md +0 -28
- package/autopm/.claude/commands/pm/standup.md +0 -28
- package/autopm/.claude/commands/pm/status.md +0 -28
- package/autopm/.claude/commands/pm/sync.md +0 -99
- package/autopm/.claude/commands/pm/test-reference-update.md +0 -151
- package/autopm/.claude/commands/pm/validate.md +0 -28
- package/autopm/.claude/commands/pm/what-next.md +0 -28
- package/autopm/.claude/commands/python/api-scaffold.md +0 -50
- package/autopm/.claude/commands/python/docs-query.md +0 -48
- package/autopm/.claude/commands/react/app-scaffold.md +0 -50
- package/autopm/.claude/commands/testing/prime.md +0 -314
- package/autopm/.claude/commands/testing/run.md +0 -125
- package/autopm/.claude/commands/ui/bootstrap-scaffold.md +0 -65
- package/autopm/.claude/commands/ui/tailwind-system.md +0 -64
- package/autopm/.claude/rules/ai-integration-patterns.md +0 -219
- package/autopm/.claude/rules/ci-cd-kubernetes-strategy.md +0 -25
- package/autopm/.claude/rules/database-management-strategy.md +0 -17
- package/autopm/.claude/rules/database-pipeline.md +0 -94
- package/autopm/.claude/rules/devops-troubleshooting-playbook.md +0 -450
- package/autopm/.claude/rules/docker-first-development.md +0 -404
- package/autopm/.claude/rules/infrastructure-pipeline.md +0 -128
- package/autopm/.claude/rules/performance-guidelines.md +0 -403
- package/autopm/.claude/rules/ui-development-standards.md +0 -281
- package/autopm/.claude/rules/ui-framework-rules.md +0 -151
- package/autopm/.claude/rules/ux-design-rules.md +0 -209
- package/autopm/.claude/rules/visual-testing.md +0 -223
- package/autopm/.claude/scripts/azure/README.md +0 -192
- package/autopm/.claude/scripts/azure/active-work.js +0 -524
- package/autopm/.claude/scripts/azure/active-work.sh +0 -20
- package/autopm/.claude/scripts/azure/blocked.js +0 -520
- package/autopm/.claude/scripts/azure/blocked.sh +0 -20
- package/autopm/.claude/scripts/azure/daily.js +0 -533
- package/autopm/.claude/scripts/azure/daily.sh +0 -20
- package/autopm/.claude/scripts/azure/dashboard.js +0 -970
- package/autopm/.claude/scripts/azure/dashboard.sh +0 -20
- package/autopm/.claude/scripts/azure/feature-list.js +0 -254
- package/autopm/.claude/scripts/azure/feature-list.sh +0 -20
- package/autopm/.claude/scripts/azure/feature-show.js +0 -7
- package/autopm/.claude/scripts/azure/feature-show.sh +0 -20
- package/autopm/.claude/scripts/azure/feature-status.js +0 -604
- package/autopm/.claude/scripts/azure/feature-status.sh +0 -20
- package/autopm/.claude/scripts/azure/help.js +0 -342
- package/autopm/.claude/scripts/azure/help.sh +0 -20
- package/autopm/.claude/scripts/azure/next-task.js +0 -508
- package/autopm/.claude/scripts/azure/next-task.sh +0 -20
- package/autopm/.claude/scripts/azure/search.js +0 -469
- package/autopm/.claude/scripts/azure/search.sh +0 -20
- package/autopm/.claude/scripts/azure/setup.js +0 -745
- package/autopm/.claude/scripts/azure/setup.sh +0 -20
- package/autopm/.claude/scripts/azure/sprint-report.js +0 -1012
- package/autopm/.claude/scripts/azure/sprint-report.sh +0 -20
- package/autopm/.claude/scripts/azure/sync.js +0 -563
- package/autopm/.claude/scripts/azure/sync.sh +0 -20
- package/autopm/.claude/scripts/azure/us-list.js +0 -210
- package/autopm/.claude/scripts/azure/us-list.sh +0 -20
- package/autopm/.claude/scripts/azure/us-status.js +0 -238
- package/autopm/.claude/scripts/azure/us-status.sh +0 -20
- package/autopm/.claude/scripts/azure/validate.js +0 -626
- package/autopm/.claude/scripts/azure/validate.sh +0 -20
- package/autopm/.claude/scripts/azure/wrapper-template.sh +0 -20
- package/autopm/.claude/scripts/github/dependency-tracker.js +0 -554
- package/autopm/.claude/scripts/github/dependency-validator.js +0 -545
- package/autopm/.claude/scripts/github/dependency-visualizer.js +0 -477
- package/autopm/.claude/scripts/pm/analytics.js +0 -425
- package/autopm/.claude/scripts/pm/blocked.js +0 -164
- package/autopm/.claude/scripts/pm/blocked.sh +0 -78
- package/autopm/.claude/scripts/pm/clean.js +0 -464
- package/autopm/.claude/scripts/pm/context-create.js +0 -216
- package/autopm/.claude/scripts/pm/context-prime.js +0 -335
- package/autopm/.claude/scripts/pm/context-update.js +0 -344
- package/autopm/.claude/scripts/pm/context.js +0 -338
- package/autopm/.claude/scripts/pm/epic-close.js +0 -347
- package/autopm/.claude/scripts/pm/epic-edit.js +0 -382
- package/autopm/.claude/scripts/pm/epic-list.js +0 -273
- package/autopm/.claude/scripts/pm/epic-list.sh +0 -109
- package/autopm/.claude/scripts/pm/epic-show.js +0 -291
- package/autopm/.claude/scripts/pm/epic-show.sh +0 -105
- package/autopm/.claude/scripts/pm/epic-split.js +0 -522
- package/autopm/.claude/scripts/pm/epic-start/epic-start.js +0 -183
- package/autopm/.claude/scripts/pm/epic-start/epic-start.sh +0 -94
- package/autopm/.claude/scripts/pm/epic-status.js +0 -291
- package/autopm/.claude/scripts/pm/epic-status.sh +0 -104
- package/autopm/.claude/scripts/pm/epic-sync/README.md +0 -208
- package/autopm/.claude/scripts/pm/epic-sync/create-epic-issue.sh +0 -77
- package/autopm/.claude/scripts/pm/epic-sync/create-task-issues.sh +0 -86
- package/autopm/.claude/scripts/pm/epic-sync/update-epic-file.sh +0 -79
- package/autopm/.claude/scripts/pm/epic-sync/update-references.sh +0 -89
- package/autopm/.claude/scripts/pm/epic-sync.sh +0 -137
- package/autopm/.claude/scripts/pm/help.js +0 -92
- package/autopm/.claude/scripts/pm/help.sh +0 -90
- package/autopm/.claude/scripts/pm/in-progress.js +0 -178
- package/autopm/.claude/scripts/pm/in-progress.sh +0 -93
- package/autopm/.claude/scripts/pm/init.js +0 -321
- package/autopm/.claude/scripts/pm/init.sh +0 -178
- package/autopm/.claude/scripts/pm/issue-close.js +0 -232
- package/autopm/.claude/scripts/pm/issue-edit.js +0 -310
- package/autopm/.claude/scripts/pm/issue-show.js +0 -272
- package/autopm/.claude/scripts/pm/issue-start.js +0 -181
- package/autopm/.claude/scripts/pm/issue-sync/format-comment.sh +0 -468
- package/autopm/.claude/scripts/pm/issue-sync/gather-updates.sh +0 -460
- package/autopm/.claude/scripts/pm/issue-sync/post-comment.sh +0 -330
- package/autopm/.claude/scripts/pm/issue-sync/preflight-validation.sh +0 -348
- package/autopm/.claude/scripts/pm/issue-sync/update-frontmatter.sh +0 -387
- package/autopm/.claude/scripts/pm/lib/README.md +0 -85
- package/autopm/.claude/scripts/pm/lib/epic-discovery.js +0 -119
- package/autopm/.claude/scripts/pm/lib/logger.js +0 -78
- package/autopm/.claude/scripts/pm/next.js +0 -189
- package/autopm/.claude/scripts/pm/next.sh +0 -72
- package/autopm/.claude/scripts/pm/optimize.js +0 -407
- package/autopm/.claude/scripts/pm/pr-create.js +0 -337
- package/autopm/.claude/scripts/pm/pr-list.js +0 -257
- package/autopm/.claude/scripts/pm/prd-list.js +0 -242
- package/autopm/.claude/scripts/pm/prd-list.sh +0 -103
- package/autopm/.claude/scripts/pm/prd-new.js +0 -684
- package/autopm/.claude/scripts/pm/prd-parse.js +0 -547
- package/autopm/.claude/scripts/pm/prd-status.js +0 -152
- package/autopm/.claude/scripts/pm/prd-status.sh +0 -63
- package/autopm/.claude/scripts/pm/release.js +0 -460
- package/autopm/.claude/scripts/pm/search.js +0 -192
- package/autopm/.claude/scripts/pm/search.sh +0 -89
- package/autopm/.claude/scripts/pm/standup.js +0 -362
- package/autopm/.claude/scripts/pm/standup.sh +0 -95
- package/autopm/.claude/scripts/pm/status.js +0 -148
- package/autopm/.claude/scripts/pm/status.sh +0 -59
- package/autopm/.claude/scripts/pm/sync-batch.js +0 -337
- package/autopm/.claude/scripts/pm/sync.js +0 -343
- package/autopm/.claude/scripts/pm/template-list.js +0 -141
- package/autopm/.claude/scripts/pm/template-new.js +0 -366
- package/autopm/.claude/scripts/pm/validate.js +0 -274
- package/autopm/.claude/scripts/pm/validate.sh +0 -106
- package/autopm/.claude/scripts/pm/what-next.js +0 -660
- package/bin/node/azure-feature-show.js +0 -7
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PluginManager - Manages ClaudeAutoPM plugins
|
|
3
|
+
*
|
|
4
|
+
* Responsibilities:
|
|
5
|
+
* - Discover installed plugins in node_modules
|
|
6
|
+
* - Load and validate plugin metadata
|
|
7
|
+
* - Install/uninstall plugin agents
|
|
8
|
+
* - Maintain plugin registry
|
|
9
|
+
*
|
|
10
|
+
* @module lib/plugins/PluginManager
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const fs = require('fs-extra');
|
|
14
|
+
const path = require('path');
|
|
15
|
+
const os = require('os');
|
|
16
|
+
|
|
17
|
+
class PluginManager {
|
|
18
|
+
constructor(options = {}) {
|
|
19
|
+
this.projectRoot = options.projectRoot || process.cwd();
|
|
20
|
+
this.pluginsDir = options.pluginsDir || path.join(os.homedir(), '.claudeautopm', 'plugins');
|
|
21
|
+
this.registryPath = path.join(this.pluginsDir, 'registry.json');
|
|
22
|
+
|
|
23
|
+
// Ensure plugins directory exists
|
|
24
|
+
fs.ensureDirSync(this.pluginsDir);
|
|
25
|
+
|
|
26
|
+
// Load or initialize registry
|
|
27
|
+
this.registry = this.loadRegistry();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Load plugin registry from disk
|
|
32
|
+
* @returns {Object} Plugin registry
|
|
33
|
+
*/
|
|
34
|
+
loadRegistry() {
|
|
35
|
+
if (fs.existsSync(this.registryPath)) {
|
|
36
|
+
try {
|
|
37
|
+
return JSON.parse(fs.readFileSync(this.registryPath, 'utf-8'));
|
|
38
|
+
} catch (error) {
|
|
39
|
+
console.warn('Warning: Failed to load plugin registry, creating new one');
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Default registry structure
|
|
44
|
+
return {
|
|
45
|
+
version: '1.0.0',
|
|
46
|
+
installed: [],
|
|
47
|
+
enabled: [],
|
|
48
|
+
lastUpdate: new Date().toISOString()
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Save plugin registry to disk
|
|
54
|
+
*/
|
|
55
|
+
saveRegistry() {
|
|
56
|
+
this.registry.lastUpdate = new Date().toISOString();
|
|
57
|
+
fs.writeFileSync(
|
|
58
|
+
this.registryPath,
|
|
59
|
+
JSON.stringify(this.registry, null, 2),
|
|
60
|
+
'utf-8'
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Get plugin installation path in node_modules
|
|
66
|
+
* @param {string} pluginName - Plugin name (e.g., 'plugin-cloud')
|
|
67
|
+
* @returns {string} Full path to plugin directory
|
|
68
|
+
*/
|
|
69
|
+
getPluginPath(pluginName) {
|
|
70
|
+
// Check local node_modules first
|
|
71
|
+
const localPath = path.join(this.projectRoot, 'node_modules', '@claudeautopm', pluginName);
|
|
72
|
+
if (fs.existsSync(localPath)) {
|
|
73
|
+
return localPath;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Check global node_modules
|
|
77
|
+
const { execSync } = require('child_process');
|
|
78
|
+
try {
|
|
79
|
+
const globalModules = execSync('npm root -g', { encoding: 'utf-8' }).trim();
|
|
80
|
+
const globalPath = path.join(globalModules, '@claudeautopm', pluginName);
|
|
81
|
+
if (fs.existsSync(globalPath)) {
|
|
82
|
+
return globalPath;
|
|
83
|
+
}
|
|
84
|
+
} catch (error) {
|
|
85
|
+
// Fall through
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
throw new Error(`Plugin not found: ${pluginName}`);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Discover all installed plugins
|
|
93
|
+
* Scans both local and global node_modules/@claudeautopm/plugin-*
|
|
94
|
+
* @returns {Array<Object>} Array of plugin metadata
|
|
95
|
+
*/
|
|
96
|
+
async discoverPlugins() {
|
|
97
|
+
const plugins = [];
|
|
98
|
+
const scannedPaths = new Set();
|
|
99
|
+
|
|
100
|
+
// Scan local node_modules
|
|
101
|
+
const localModules = path.join(this.projectRoot, 'node_modules', '@claudeautopm');
|
|
102
|
+
if (fs.existsSync(localModules)) {
|
|
103
|
+
const dirs = fs.readdirSync(localModules);
|
|
104
|
+
for (const dir of dirs) {
|
|
105
|
+
if (dir.startsWith('plugin-')) {
|
|
106
|
+
const pluginPath = path.join(localModules, dir);
|
|
107
|
+
scannedPaths.add(pluginPath);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Scan global node_modules
|
|
113
|
+
try {
|
|
114
|
+
const { execSync } = require('child_process');
|
|
115
|
+
const globalModules = execSync('npm root -g', { encoding: 'utf-8' }).trim();
|
|
116
|
+
const globalClaudeAutopm = path.join(globalModules, '@claudeautopm');
|
|
117
|
+
|
|
118
|
+
if (fs.existsSync(globalClaudeAutopm)) {
|
|
119
|
+
const dirs = fs.readdirSync(globalClaudeAutopm);
|
|
120
|
+
for (const dir of dirs) {
|
|
121
|
+
if (dir.startsWith('plugin-')) {
|
|
122
|
+
const pluginPath = path.join(globalClaudeAutopm, dir);
|
|
123
|
+
scannedPaths.add(pluginPath);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
} catch (error) {
|
|
128
|
+
// Global modules not accessible, skip
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Load metadata for each discovered plugin
|
|
132
|
+
for (const pluginPath of scannedPaths) {
|
|
133
|
+
try {
|
|
134
|
+
const pluginName = path.basename(pluginPath);
|
|
135
|
+
const metadata = await this.loadPluginMetadata(pluginName);
|
|
136
|
+
if (metadata) {
|
|
137
|
+
plugins.push(metadata);
|
|
138
|
+
}
|
|
139
|
+
} catch (error) {
|
|
140
|
+
console.warn(`Warning: Failed to load plugin metadata from ${pluginPath}: ${error.message}`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return plugins;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Load plugin metadata from plugin.json
|
|
149
|
+
* @param {string} pluginName - Plugin name (e.g., 'plugin-cloud')
|
|
150
|
+
* @returns {Object} Plugin metadata
|
|
151
|
+
*/
|
|
152
|
+
async loadPluginMetadata(pluginName) {
|
|
153
|
+
const pluginPath = this.getPluginPath(pluginName);
|
|
154
|
+
const metadataPath = path.join(pluginPath, 'plugin.json');
|
|
155
|
+
|
|
156
|
+
if (!fs.existsSync(metadataPath)) {
|
|
157
|
+
throw new Error(`Plugin metadata not found: ${metadataPath}`);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const metadata = JSON.parse(fs.readFileSync(metadataPath, 'utf-8'));
|
|
161
|
+
|
|
162
|
+
// Validate metadata
|
|
163
|
+
this.validateMetadata(metadata);
|
|
164
|
+
|
|
165
|
+
// Add computed properties
|
|
166
|
+
metadata.path = pluginPath;
|
|
167
|
+
metadata.pluginName = pluginName;
|
|
168
|
+
|
|
169
|
+
return metadata;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Validate plugin metadata schema
|
|
174
|
+
* @param {Object} metadata - Plugin metadata to validate
|
|
175
|
+
* @throws {Error} If metadata is invalid
|
|
176
|
+
*/
|
|
177
|
+
validateMetadata(metadata) {
|
|
178
|
+
const required = ['name', 'version', 'displayName', 'description', 'category', 'agents'];
|
|
179
|
+
|
|
180
|
+
for (const field of required) {
|
|
181
|
+
if (!metadata[field]) {
|
|
182
|
+
throw new Error(`Plugin metadata missing required field: ${field}`);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (!Array.isArray(metadata.agents)) {
|
|
187
|
+
throw new Error('Plugin metadata "agents" must be an array');
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Validate each agent
|
|
191
|
+
for (const agent of metadata.agents) {
|
|
192
|
+
if (!agent.name || !agent.file || !agent.description) {
|
|
193
|
+
throw new Error('Agent metadata must have name, file, and description');
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Install plugin agents to .claude/agents/
|
|
200
|
+
* @param {string} pluginName - Plugin name (e.g., 'plugin-cloud')
|
|
201
|
+
* @returns {Object} Installation result
|
|
202
|
+
*/
|
|
203
|
+
async installPlugin(pluginName) {
|
|
204
|
+
const metadata = await this.loadPluginMetadata(pluginName);
|
|
205
|
+
const pluginPath = this.getPluginPath(pluginName);
|
|
206
|
+
const targetDir = path.join(this.projectRoot, '.claude', 'agents', metadata.category);
|
|
207
|
+
|
|
208
|
+
// Create category directory
|
|
209
|
+
fs.ensureDirSync(targetDir);
|
|
210
|
+
|
|
211
|
+
const installedAgents = [];
|
|
212
|
+
|
|
213
|
+
// Copy agents
|
|
214
|
+
for (const agent of metadata.agents) {
|
|
215
|
+
const sourcePath = path.join(pluginPath, agent.file);
|
|
216
|
+
const targetPath = path.join(targetDir, path.basename(agent.file));
|
|
217
|
+
|
|
218
|
+
if (!fs.existsSync(sourcePath)) {
|
|
219
|
+
console.warn(`Warning: Agent file not found: ${sourcePath}`);
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
fs.copyFileSync(sourcePath, targetPath);
|
|
224
|
+
installedAgents.push({
|
|
225
|
+
name: agent.name,
|
|
226
|
+
file: targetPath,
|
|
227
|
+
description: agent.description
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Update registry
|
|
232
|
+
if (!this.registry.installed.includes(pluginName)) {
|
|
233
|
+
this.registry.installed.push(pluginName);
|
|
234
|
+
}
|
|
235
|
+
if (!this.registry.enabled.includes(pluginName)) {
|
|
236
|
+
this.registry.enabled.push(pluginName);
|
|
237
|
+
}
|
|
238
|
+
this.saveRegistry();
|
|
239
|
+
|
|
240
|
+
return {
|
|
241
|
+
success: true,
|
|
242
|
+
pluginName,
|
|
243
|
+
displayName: metadata.displayName,
|
|
244
|
+
category: metadata.category,
|
|
245
|
+
agentsInstalled: installedAgents.length,
|
|
246
|
+
agents: installedAgents
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Uninstall plugin - remove agents and update registry
|
|
252
|
+
* @param {string} pluginName - Plugin name (e.g., 'plugin-cloud')
|
|
253
|
+
* @returns {Object} Uninstallation result
|
|
254
|
+
*/
|
|
255
|
+
async uninstallPlugin(pluginName) {
|
|
256
|
+
const metadata = await this.loadPluginMetadata(pluginName);
|
|
257
|
+
const targetDir = path.join(this.projectRoot, '.claude', 'agents', metadata.category);
|
|
258
|
+
|
|
259
|
+
const removedAgents = [];
|
|
260
|
+
|
|
261
|
+
// Remove agents
|
|
262
|
+
for (const agent of metadata.agents) {
|
|
263
|
+
const targetPath = path.join(targetDir, path.basename(agent.file));
|
|
264
|
+
if (fs.existsSync(targetPath)) {
|
|
265
|
+
fs.unlinkSync(targetPath);
|
|
266
|
+
removedAgents.push(agent.name);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Remove empty category directory
|
|
271
|
+
if (fs.existsSync(targetDir) && fs.readdirSync(targetDir).length === 0) {
|
|
272
|
+
fs.rmdirSync(targetDir);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Update registry
|
|
276
|
+
this.registry.installed = this.registry.installed.filter(p => p !== pluginName);
|
|
277
|
+
this.registry.enabled = this.registry.enabled.filter(p => p !== pluginName);
|
|
278
|
+
this.saveRegistry();
|
|
279
|
+
|
|
280
|
+
return {
|
|
281
|
+
success: true,
|
|
282
|
+
pluginName,
|
|
283
|
+
agentsRemoved: removedAgents.length,
|
|
284
|
+
agents: removedAgents
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Get list of installed plugins
|
|
290
|
+
* @returns {Array<string>} Array of plugin names
|
|
291
|
+
*/
|
|
292
|
+
getInstalledPlugins() {
|
|
293
|
+
return this.registry.installed;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Get list of enabled plugins
|
|
298
|
+
* @returns {Array<string>} Array of plugin names
|
|
299
|
+
*/
|
|
300
|
+
getEnabledPlugins() {
|
|
301
|
+
return this.registry.enabled;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Enable plugin
|
|
306
|
+
* @param {string} pluginName - Plugin name
|
|
307
|
+
*/
|
|
308
|
+
enablePlugin(pluginName) {
|
|
309
|
+
if (!this.registry.installed.includes(pluginName)) {
|
|
310
|
+
throw new Error(`Plugin not installed: ${pluginName}`);
|
|
311
|
+
}
|
|
312
|
+
if (!this.registry.enabled.includes(pluginName)) {
|
|
313
|
+
this.registry.enabled.push(pluginName);
|
|
314
|
+
this.saveRegistry();
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Disable plugin
|
|
320
|
+
* @param {string} pluginName - Plugin name
|
|
321
|
+
*/
|
|
322
|
+
disablePlugin(pluginName) {
|
|
323
|
+
this.registry.enabled = this.registry.enabled.filter(p => p !== pluginName);
|
|
324
|
+
this.saveRegistry();
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Check if plugin is installed
|
|
329
|
+
* @param {string} pluginName - Plugin name
|
|
330
|
+
* @returns {boolean} True if installed
|
|
331
|
+
*/
|
|
332
|
+
isInstalled(pluginName) {
|
|
333
|
+
return this.registry.installed.includes(pluginName);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Check if plugin is enabled
|
|
338
|
+
* @param {string} pluginName - Plugin name
|
|
339
|
+
* @returns {boolean} True if enabled
|
|
340
|
+
*/
|
|
341
|
+
isEnabled(pluginName) {
|
|
342
|
+
return this.registry.enabled.includes(pluginName);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Search plugins by keyword
|
|
347
|
+
* @param {string} keyword - Search keyword
|
|
348
|
+
* @returns {Array<Object>} Matching plugins
|
|
349
|
+
*/
|
|
350
|
+
async searchPlugins(keyword) {
|
|
351
|
+
const allPlugins = await this.discoverPlugins();
|
|
352
|
+
const lowerKeyword = keyword.toLowerCase();
|
|
353
|
+
|
|
354
|
+
return allPlugins.filter(plugin => {
|
|
355
|
+
// Search in name
|
|
356
|
+
if (plugin.name.toLowerCase().includes(lowerKeyword)) {
|
|
357
|
+
return true;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// Search in display name
|
|
361
|
+
if (plugin.displayName.toLowerCase().includes(lowerKeyword)) {
|
|
362
|
+
return true;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Search in description
|
|
366
|
+
if (plugin.description.toLowerCase().includes(lowerKeyword)) {
|
|
367
|
+
return true;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// Search in keywords
|
|
371
|
+
if (plugin.keywords && plugin.keywords.some(k => k.toLowerCase().includes(lowerKeyword))) {
|
|
372
|
+
return true;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// Search in agent names
|
|
376
|
+
if (plugin.agents.some(a => a.name.toLowerCase().includes(lowerKeyword))) {
|
|
377
|
+
return true;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
return false;
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Get plugin info
|
|
386
|
+
* @param {string} pluginName - Plugin name
|
|
387
|
+
* @returns {Object} Plugin metadata with status
|
|
388
|
+
*/
|
|
389
|
+
async getPluginInfo(pluginName) {
|
|
390
|
+
const metadata = await this.loadPluginMetadata(pluginName);
|
|
391
|
+
|
|
392
|
+
return {
|
|
393
|
+
...metadata,
|
|
394
|
+
installed: this.isInstalled(pluginName),
|
|
395
|
+
enabled: this.isEnabled(pluginName)
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
module.exports = PluginManager;
|