claude-autopm 2.8.9 → 2.11.1

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.
@@ -0,0 +1,182 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Plugin Manifest Generator
5
+ *
6
+ * Generates compressed plugin manifests for token-optimized CLAUDE.md
7
+ * Reduces plugin metadata from thousands of tokens to ~50 tokens per plugin
8
+ */
9
+
10
+ const fs = require('fs');
11
+ const path = require('path');
12
+
13
+ const CHARS_PER_TOKEN = 4;
14
+
15
+ function estimateTokens(text) {
16
+ const normalized = text.replace(/\s+/g, ' ').trim();
17
+ return Math.ceil(normalized.length / CHARS_PER_TOKEN);
18
+ }
19
+
20
+ /**
21
+ * Generate compressed manifest for a single plugin
22
+ */
23
+ function generatePluginManifest(pluginData, pluginId) {
24
+ const agentNames = (pluginData.agents || []).map(a => a.name).join('|');
25
+ const commandNames = (pluginData.commands || []).map(c => c.name).join('|');
26
+ const ruleCount = (pluginData.rules || []).length;
27
+
28
+ const manifest = `<plugin id="${pluginId}">
29
+ agents: ${agentNames || 'None'}
30
+ commands: ${commandNames || 'None'}
31
+ rules: ${ruleCount} files (on-demand)
32
+ 📖 .claude/plugins/${pluginId}/
33
+ </plugin>`;
34
+
35
+ return {
36
+ manifest,
37
+ tokens: estimateTokens(manifest),
38
+ stats: {
39
+ agents: pluginData.agents?.length || 0,
40
+ commands: pluginData.commands?.length || 0,
41
+ rules: ruleCount
42
+ }
43
+ };
44
+ }
45
+
46
+ /**
47
+ * Generate complete plugins section for CLAUDE.md
48
+ */
49
+ function generatePluginsSection(installedPlugins, packagesDir) {
50
+ const manifests = [];
51
+ const pluginList = [];
52
+ let totalTokens = 0;
53
+ let totalFiles = 0;
54
+
55
+ installedPlugins.forEach(pluginId => {
56
+ const pluginPath = path.join(packagesDir, `plugin-${pluginId}`, 'plugin.json');
57
+
58
+ if (!fs.existsSync(pluginPath)) {
59
+ console.warn(`⚠️ Plugin ${pluginId} not found at ${pluginPath}`);
60
+ return;
61
+ }
62
+
63
+ try {
64
+ const pluginData = JSON.parse(fs.readFileSync(pluginPath, 'utf-8'));
65
+ const result = generatePluginManifest(pluginData, pluginId);
66
+
67
+ manifests.push(result.manifest);
68
+ pluginList.push(pluginId);
69
+ totalTokens += result.tokens;
70
+ totalFiles += result.stats.agents + result.stats.commands + result.stats.rules;
71
+
72
+ console.log(`✅ ${pluginId}: ${result.tokens} tokens (${result.stats.agents} agents, ${result.stats.commands} commands, ${result.stats.rules} rules)`);
73
+ } catch (error) {
74
+ console.error(`❌ Error processing ${pluginId}:`, error.message);
75
+ }
76
+ });
77
+
78
+ const pluginsSection = `<plugins>
79
+ <installed>${pluginList.join('|')}</installed>
80
+
81
+ <manifest>
82
+ ${manifests.join('\n\n')}
83
+ </manifest>
84
+
85
+ <lazy_loading>
86
+ <enabled>true</enabled>
87
+ <triggers>
88
+ commands: "/[plugin-id]:[command-name]"
89
+ agents: "@[agent-name]" (from plugin)
90
+ rules: on-violation or explicit reference
91
+ </triggers>
92
+ </lazy_loading>
93
+
94
+ <usage>
95
+ Commands: Type /[plugin-id]:[command] to invoke
96
+ Agents: Type @[agent-name] to invoke
97
+ Rules: Automatically loaded when needed
98
+ Files: All available in .claude/plugins/[plugin-id]/
99
+ </usage>
100
+ </plugins>`;
101
+
102
+ return {
103
+ section: pluginsSection,
104
+ tokens: estimateTokens(pluginsSection),
105
+ totalFiles,
106
+ pluginCount: pluginList.length
107
+ };
108
+ }
109
+
110
+ /**
111
+ * Calculate token savings
112
+ */
113
+ function calculateSavings(optimizedTokens, totalFiles) {
114
+ // Estimate: average 600 tokens per agent, 300 per command, 1500 per rule
115
+ const estimatedOldTokens = totalFiles * 800; // Conservative average
116
+ const savings = estimatedOldTokens - optimizedTokens;
117
+ const percent = ((savings / estimatedOldTokens) * 100).toFixed(1);
118
+
119
+ return {
120
+ old: estimatedOldTokens,
121
+ new: optimizedTokens,
122
+ saved: savings,
123
+ percent
124
+ };
125
+ }
126
+
127
+ /**
128
+ * Main function
129
+ */
130
+ function main() {
131
+ const args = process.argv.slice(2);
132
+
133
+ if (args.length < 2) {
134
+ console.log('Usage: node plugin-manifest-generator.js <packages-dir> <plugin1,plugin2,...>');
135
+ console.log('Example: node plugin-manifest-generator.js ./packages core,pm,cloud');
136
+ process.exit(1);
137
+ }
138
+
139
+ const packagesDir = path.resolve(args[0]);
140
+ const pluginIds = args[1].split(',').map(p => p.trim());
141
+
142
+ console.log('\n🔧 Plugin Manifest Generator');
143
+ console.log('='.repeat(70));
144
+ console.log(`Packages directory: ${packagesDir}`);
145
+ console.log(`Plugins to process: ${pluginIds.join(', ')}`);
146
+ console.log('');
147
+
148
+ const result = generatePluginsSection(pluginIds, packagesDir);
149
+
150
+ console.log('\n' + '='.repeat(70));
151
+ console.log('📊 Generation Complete');
152
+ console.log('='.repeat(70));
153
+ console.log(`Plugins processed: ${result.pluginCount}`);
154
+ console.log(`Total files: ${result.totalFiles}`);
155
+ console.log(`Manifest tokens: ${result.tokens}`);
156
+
157
+ const savings = calculateSavings(result.tokens, result.totalFiles);
158
+ console.log(`\n💰 Token Savings:`);
159
+ console.log(` Old system (est): ${savings.old.toLocaleString()} tokens`);
160
+ console.log(` New manifest: ${savings.new.toLocaleString()} tokens`);
161
+ console.log(` Savings: ${savings.saved.toLocaleString()} tokens (${savings.percent}%)`);
162
+
163
+ console.log('\n📄 Generated Manifest:');
164
+ console.log('='.repeat(70));
165
+ console.log(result.section);
166
+ console.log('='.repeat(70));
167
+
168
+ return result;
169
+ }
170
+
171
+ // Export for use in other scripts
172
+ module.exports = {
173
+ generatePluginManifest,
174
+ generatePluginsSection,
175
+ calculateSavings,
176
+ estimateTokens
177
+ };
178
+
179
+ // Run if called directly
180
+ if (require.main === module) {
181
+ main();
182
+ }
@@ -908,6 +908,137 @@ class PluginManager extends EventEmitter {
908
908
  }
909
909
  }
910
910
 
911
+ /**
912
+ * Update an installed plugin to the latest version
913
+ * @param {string} pluginName - Plugin name (with or without scope)
914
+ * @param {Object} options - Update options
915
+ * @param {boolean} options.verbose - Show detailed output
916
+ * @param {boolean} options.force - Force update even if versions match
917
+ * @returns {Promise<Object>} Update result
918
+ */
919
+ async updatePlugin(pluginName, options = {}) {
920
+ const { verbose = false, force = false } = options;
921
+ const { execSync } = require('child_process');
922
+
923
+ const fullName = pluginName.includes('/') ? pluginName : `${this.options.scopePrefix}/${pluginName}`;
924
+ const shortName = pluginName.replace(`${this.options.scopePrefix}/`, '');
925
+
926
+ this.emit('update:start', { name: fullName });
927
+
928
+ try {
929
+ // Check if plugin is installed
930
+ if (!this.isInstalled(shortName)) {
931
+ throw new Error(`Plugin ${shortName} is not installed. Use 'autopm plugin install ${shortName}' to install it.`);
932
+ }
933
+
934
+ // Get current installed version from plugin.json
935
+ const plugin = this.plugins.get(fullName);
936
+ if (!plugin || !plugin.loaded) {
937
+ await this.loadPlugin(fullName);
938
+ }
939
+
940
+ const currentMetadata = this.plugins.get(fullName)?.metadata;
941
+ const currentVersion = currentMetadata?.version || 'unknown';
942
+
943
+ // Check npm for available version
944
+ let availableVersion;
945
+ try {
946
+ const npmInfo = execSync(`npm view ${fullName} version`, { encoding: 'utf-8' }).trim();
947
+ availableVersion = npmInfo;
948
+ } catch (error) {
949
+ throw new Error(`Failed to check npm for ${fullName}: ${error.message}`);
950
+ }
951
+
952
+ // Compare versions
953
+ if (currentVersion === availableVersion && !force) {
954
+ this.emit('update:skipped', {
955
+ name: fullName,
956
+ reason: 'Already up to date',
957
+ version: currentVersion
958
+ });
959
+
960
+ return {
961
+ upToDate: true,
962
+ currentVersion,
963
+ updated: false
964
+ };
965
+ }
966
+
967
+ if (verbose) {
968
+ console.log(` Current version: ${currentVersion}`);
969
+ console.log(` Available version: ${availableVersion}`);
970
+ }
971
+
972
+ // Uninstall old version
973
+ if (verbose) {
974
+ console.log(` Removing old version...`);
975
+ }
976
+
977
+ const wasEnabled = this.isEnabled(shortName);
978
+ await this.uninstallPlugin(fullName);
979
+
980
+ // Update npm package globally
981
+ if (verbose) {
982
+ console.log(` Updating npm package...`);
983
+ }
984
+
985
+ try {
986
+ execSync(`npm update -g ${fullName}`, {
987
+ stdio: verbose ? 'inherit' : 'ignore'
988
+ });
989
+ } catch (error) {
990
+ throw new Error(`Failed to update npm package: ${error.message}`);
991
+ }
992
+
993
+ // Reload plugin metadata from updated package
994
+ await this.discoverPlugins();
995
+
996
+ // Reinstall with new version
997
+ if (verbose) {
998
+ console.log(` Installing new version...`);
999
+ }
1000
+
1001
+ const installResult = await this.installPlugin(fullName);
1002
+
1003
+ // Restore enabled state
1004
+ if (wasEnabled) {
1005
+ this.enablePlugin(shortName);
1006
+ }
1007
+
1008
+ this.emit('update:complete', {
1009
+ name: fullName,
1010
+ oldVersion: currentVersion,
1011
+ newVersion: availableVersion,
1012
+ stats: {
1013
+ agents: installResult.agentsInstalled,
1014
+ commands: installResult.commandsInstalled,
1015
+ rules: installResult.rulesInstalled,
1016
+ hooks: installResult.hooksInstalled,
1017
+ scripts: installResult.scriptsInstalled
1018
+ }
1019
+ });
1020
+
1021
+ return {
1022
+ updated: true,
1023
+ oldVersion: currentVersion,
1024
+ newVersion: availableVersion,
1025
+ stats: {
1026
+ agents: installResult.agentsInstalled,
1027
+ commands: installResult.commandsInstalled,
1028
+ rules: installResult.rulesInstalled,
1029
+ hooks: installResult.hooksInstalled,
1030
+ scripts: installResult.scriptsInstalled
1031
+ }
1032
+ };
1033
+ } catch (error) {
1034
+ this.emit('update:error', {
1035
+ name: fullName,
1036
+ error: error.message
1037
+ });
1038
+ throw error;
1039
+ }
1040
+ }
1041
+
911
1042
  /**
912
1043
  * Get list of installed plugins (from registry)
913
1044
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-autopm",
3
- "version": "2.8.9",
3
+ "version": "2.11.1",
4
4
  "description": "Autonomous Project Management Framework for Claude Code - Advanced AI-powered development automation",
5
5
  "main": "bin/autopm.js",
6
6
  "workspaces": [