poly-agent 1.0.2 → 1.0.4

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/cli.js ADDED
@@ -0,0 +1,199 @@
1
+ #!/usr/bin/env node
2
+ import { intro, select, multiselect, spinner, log, outro, cancel, isCancel } from '@clack/prompts';
3
+ import fs from 'fs/promises';
4
+ import path from 'path';
5
+ import { PromptLoader } from './lib/prompt-loader.js';
6
+ import { createRequire } from 'module';
7
+ const require = createRequire(import.meta.url);
8
+ // Get the prompts directory
9
+ async function getPromptsDir() {
10
+ // Try multiple possible locations
11
+ const possiblePaths = [
12
+ path.join(process.cwd(), 'prompts'), // Local development
13
+ path.join(process.cwd(), 'node_modules', 'poly-agent', 'prompts'), // Installed package
14
+ ];
15
+ // Try to resolve via require if available
16
+ try {
17
+ const packagePath = require.resolve('poly-agent/package.json');
18
+ const packageDir = path.dirname(packagePath);
19
+ possiblePaths.unshift(path.join(packageDir, 'prompts'));
20
+ }
21
+ catch {
22
+ // Not installed as package, continue
23
+ }
24
+ // Check which path actually exists
25
+ for (const promptsPath of possiblePaths) {
26
+ try {
27
+ await fs.access(promptsPath);
28
+ return promptsPath;
29
+ }
30
+ catch {
31
+ continue;
32
+ }
33
+ }
34
+ // Fallback to first option
35
+ return possiblePaths[0];
36
+ }
37
+ // Map IDE to target directory
38
+ const IDE_DIRECTORIES = {
39
+ 'Cursor': '.cursor/commands',
40
+ 'Antigravity': '.agent/workflows',
41
+ 'Claude': '.claude/skills',
42
+ };
43
+ async function runInit() {
44
+ // Welcome message
45
+ intro('Welcome to PolyAgent CLI');
46
+ // Step 1: Select AI IDE
47
+ const selectedIDE = await select({
48
+ message: 'Choose the AI IDE you want to use:',
49
+ options: [
50
+ { value: 'Cursor', label: 'Cursor' },
51
+ { value: 'Claude', label: 'Claude' },
52
+ { value: 'Antigravity', label: 'Antigravity' }
53
+ ]
54
+ });
55
+ if (isCancel(selectedIDE)) {
56
+ cancel('Operation cancelled.');
57
+ process.exit(0);
58
+ }
59
+ // Step 2: Load available prompts
60
+ const promptsDir = await getPromptsDir();
61
+ const loader = new PromptLoader(promptsDir);
62
+ const promptFiles = await loader.listPrompts();
63
+ if (promptFiles.length === 0) {
64
+ log.error('No prompts found in the prompts directory.');
65
+ process.exit(1);
66
+ }
67
+ // Load prompt metadata for display
68
+ const promptOptions = await Promise.all(promptFiles.map(async (filename) => {
69
+ try {
70
+ const prompt = await loader.loadPrompt(filename);
71
+ return {
72
+ value: filename,
73
+ label: `${prompt.name} - ${prompt.description || 'No description'}`
74
+ };
75
+ }
76
+ catch (error) {
77
+ return {
78
+ value: filename,
79
+ label: filename.replace('.md', '')
80
+ };
81
+ }
82
+ }));
83
+ // Step 3: Multi-select prompts
84
+ const selectedPrompts = await multiselect({
85
+ message: 'Select prompts to install (use Space to select, Enter to continue):',
86
+ options: promptOptions,
87
+ required: true
88
+ });
89
+ if (isCancel(selectedPrompts)) {
90
+ cancel('Operation cancelled.');
91
+ process.exit(0);
92
+ }
93
+ // Step 4: Copy files
94
+ const targetDir = IDE_DIRECTORIES[selectedIDE];
95
+ const fullTargetPath = path.join(process.cwd(), targetDir);
96
+ const s = spinner();
97
+ s.start(`Installing ${selectedPrompts.length} prompt(s) to ${targetDir}...`);
98
+ try {
99
+ // Create target directory if it doesn't exist
100
+ await fs.mkdir(fullTargetPath, { recursive: true });
101
+ // Copy each selected prompt file
102
+ const copyPromises = selectedPrompts.map(async (filename) => {
103
+ const sourcePath = path.join(promptsDir, filename);
104
+ if (selectedIDE === 'Claude') {
105
+ // For Claude, create a folder with the prompt name and SKILL.md inside
106
+ const promptName = path.basename(filename, '.md');
107
+ const skillFolderPath = path.join(fullTargetPath, promptName);
108
+ const skillFilePath = path.join(skillFolderPath, 'SKILL.md');
109
+ // Create the skill folder
110
+ await fs.mkdir(skillFolderPath, { recursive: true });
111
+ // Copy the content to SKILL.md
112
+ await fs.copyFile(sourcePath, skillFilePath);
113
+ return `${promptName}/SKILL.md`;
114
+ }
115
+ else {
116
+ // For other IDEs, copy directly
117
+ const targetPath = path.join(fullTargetPath, filename);
118
+ await fs.copyFile(sourcePath, targetPath);
119
+ return filename;
120
+ }
121
+ });
122
+ const copiedFiles = await Promise.all(copyPromises);
123
+ s.stop(`✓ Installed ${copiedFiles.length} prompt(s) successfully`);
124
+ // Success message
125
+ log.success(`Prompts installed to: ${targetDir}`);
126
+ log.info(`Installed files:`);
127
+ copiedFiles.forEach(file => {
128
+ log.info(` - ${file}`);
129
+ });
130
+ outro('Installation complete! 🎉');
131
+ }
132
+ catch (error) {
133
+ s.stop('✗ Installation failed');
134
+ log.error(`Failed to install prompts: ${error instanceof Error ? error.message : String(error)}`);
135
+ process.exit(1);
136
+ }
137
+ }
138
+ function showHelp() {
139
+ console.log(`
140
+ PolyAgent CLI - Install AI IDE prompts
141
+
142
+ Usage:
143
+ poly-agent init Initialize and install prompts
144
+ poly-agent --help Show this help message
145
+ poly-agent --version Show version
146
+
147
+ Examples:
148
+ npx poly-agent init Install prompts for your AI IDE
149
+ `);
150
+ }
151
+ function showVersion() {
152
+ try {
153
+ // Try to get version from installed package first
154
+ const packagePath = require.resolve('poly-agent/package.json');
155
+ const packageJson = require(packagePath);
156
+ console.log(`poly-agent v${packageJson.version}`);
157
+ }
158
+ catch {
159
+ try {
160
+ // Fallback to local package.json for development
161
+ const packageJson = require('../package.json');
162
+ console.log(`poly-agent v${packageJson.version}`);
163
+ }
164
+ catch {
165
+ console.log('poly-agent (version unknown)');
166
+ }
167
+ }
168
+ }
169
+ async function main() {
170
+ const args = process.argv.slice(2);
171
+ const command = args[0];
172
+ switch (command) {
173
+ case 'init':
174
+ await runInit();
175
+ break;
176
+ case '--help':
177
+ case '-h':
178
+ case 'help':
179
+ showHelp();
180
+ break;
181
+ case '--version':
182
+ case '-v':
183
+ case 'version':
184
+ showVersion();
185
+ break;
186
+ case undefined:
187
+ // No command provided, default to init for backward compatibility
188
+ await runInit();
189
+ break;
190
+ default:
191
+ log.error(`Unknown command: ${command}`);
192
+ showHelp();
193
+ process.exit(1);
194
+ }
195
+ }
196
+ main().catch((error) => {
197
+ console.error(`Fatal error: ${error instanceof Error ? error.message : String(error)}`);
198
+ process.exit(1);
199
+ });
@@ -0,0 +1,64 @@
1
+ import fs from 'fs/promises';
2
+ import path from 'path';
3
+ export class PromptLoader {
4
+ promptsDir;
5
+ constructor(promptsDir) {
6
+ this.promptsDir = promptsDir;
7
+ }
8
+ async loadPrompt(filename, variables = {}) {
9
+ const filePath = path.join(this.promptsDir, filename);
10
+ try {
11
+ const fileContent = await fs.readFile(filePath, 'utf-8');
12
+ // Basic Frontmatter parsing
13
+ const frontmatterRegex = /^---\n([\s\S]*?)\n---\n([\s\S]*)$/;
14
+ const match = fileContent.match(frontmatterRegex);
15
+ if (!match) {
16
+ // Fallback if no frontmatter
17
+ return {
18
+ name: path.basename(filename, '.md'),
19
+ description: 'No description provided.',
20
+ content: this.injectVariables(fileContent, variables)
21
+ };
22
+ }
23
+ const rawFrontmatter = match[1];
24
+ const content = match[2];
25
+ const metadata = this.parseFrontmatter(rawFrontmatter);
26
+ return {
27
+ name: metadata.name || path.basename(filename, '.md'),
28
+ description: metadata.description || '',
29
+ content: this.injectVariables(content, variables)
30
+ };
31
+ }
32
+ catch (error) {
33
+ throw new Error(`Failed to load prompt ${filename}: ${error}`);
34
+ }
35
+ }
36
+ parseFrontmatter(frontmatter) {
37
+ const lines = frontmatter.split('\n');
38
+ const metadata = {};
39
+ for (const line of lines) {
40
+ const [key, ...valueParts] = line.split(':');
41
+ if (key && valueParts.length > 0) {
42
+ metadata[key.trim()] = valueParts.join(':').trim();
43
+ }
44
+ }
45
+ return metadata;
46
+ }
47
+ injectVariables(content, variables) {
48
+ let result = content;
49
+ for (const [key, value] of Object.entries(variables)) {
50
+ // Replace {{KEY}}
51
+ result = result.replaceAll(`{{${key}}}`, value);
52
+ }
53
+ return result;
54
+ }
55
+ async listPrompts() {
56
+ try {
57
+ const files = await fs.readdir(this.promptsDir);
58
+ return files.filter(f => f.endsWith('.md'));
59
+ }
60
+ catch (error) {
61
+ return [];
62
+ }
63
+ }
64
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "poly-agent",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "CLI installer for AI IDE prompts - install commands, skills, and workflows for Cursor, ClaudeCode, and Antigravity",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -8,6 +8,8 @@
8
8
  },
9
9
  "scripts": {
10
10
  "build": "tsc",
11
+ "start": "npm run build && node dist/cli.js",
12
+ "dev": "tsc && node dist/cli.js",
11
13
  "test": "echo \"Error: no test specified\" && exit 1"
12
14
  },
13
15
  "keywords": [