voicci 1.0.3 → 1.0.7

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.
@@ -111,8 +111,6 @@ class BookFinder {
111
111
  });
112
112
  }
113
113
 
114
- this.ensureDownloadDir();
115
- }
116
114
 
117
115
  ensureDownloadDir() {
118
116
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "voicci",
3
- "version": "1.0.3",
3
+ "version": "1.0.7",
4
4
  "description": "AI-Powered Audiobook Generator for Claude Code, OpenCode & AI Code Editors. Convert books and PDFs to audiobooks using natural language.",
5
5
  "type": "module",
6
6
  "main": "cli/index.js",
@@ -3,31 +3,36 @@
3
3
  import fs from 'fs';
4
4
  import path from 'path';
5
5
  import os from 'os';
6
+ import { fileURLToPath } from 'url';
7
+ import { execFileSync } from 'child_process';
6
8
 
7
- const skillContent = `#!/bin/bash
8
- # Voicci CLI - AI Audiobook Generator
9
- # Auto-installed via npm package
9
+ const __filename = fileURLToPath(import.meta.url);
10
+ const __dirname = path.dirname(__filename);
10
11
 
11
- cat << 'PROMPT_EOF'
12
- <command-name>/voicci</command-name>
12
+ // Use unique name to avoid conflicts with SSH shorthand skills
13
+ const SKILL_NAME = 'voicci-audiobook.md';
13
14
 
14
- You are helping the user with the **Voicci CLI** - an AI audiobook generator and text summarizer.
15
+ const SKILL_CONTENT = `---
16
+ description: "Voicci - AI audiobook generator CLI"
17
+ argument-hint: "COMMAND_OR_FILE"
18
+ ---
15
19
 
16
- ## What is Voicci CLI?
17
- A command-line tool that converts books and PDFs into audiobooks using XTTS v2 AI voice synthesis. It also provides AI text summarization.
20
+ # Voicci - AI Audiobook Generator
18
21
 
19
- ## Your Task
20
- Execute voicci CLI commands based on the user's request. The tool is installed locally and runs on this machine.
22
+ Convert books, PDFs, and documents to audiobooks using AI-powered text-to-speech (XTTS v2).
23
+
24
+ ## What is Voicci?
25
+ A command-line tool that converts books and PDFs into natural-sounding audiobooks. Also provides AI text summarization.
21
26
 
22
27
  ## Common Commands
23
28
 
24
- **Search for a book:**
29
+ **Search and convert a book:**
25
30
  \`\`\`bash
26
31
  voicci "Lord of the Rings"
27
32
  voicci "Attention Is All You Need"
28
33
  \`\`\`
29
34
 
30
- **Convert a file:**
35
+ **Convert a local file:**
31
36
  \`\`\`bash
32
37
  voicci mybook.pdf
33
38
  voicci document.txt
@@ -38,13 +43,14 @@ voicci document.txt
38
43
  voicci --search "The Great Gatsby"
39
44
  \`\`\`
40
45
 
41
- **Generate summary:**
46
+ **Generate text summary:**
42
47
  \`\`\`bash
43
48
  voicci summary mybook.pdf
44
49
  voicci --summary "1984"
50
+ voicci --with-summary "book.pdf" # Generate both audiobook + summary
45
51
  \`\`\`
46
52
 
47
- **Check status:**
53
+ **Check job status:**
48
54
  \`\`\`bash
49
55
  voicci -s # All jobs
50
56
  voicci -s <jobId> # Specific job
@@ -55,6 +61,13 @@ voicci -s <jobId> # Specific job
55
61
  voicci -l
56
62
  \`\`\`
57
63
 
64
+ **Manage jobs:**
65
+ \`\`\`bash
66
+ voicci --cancel <jobId> # Cancel running job
67
+ voicci --delete <jobId> # Delete audiobook
68
+ voicci --open <jobId> # Open audiobook folder
69
+ \`\`\`
70
+
58
71
  **Configuration:**
59
72
  \`\`\`bash
60
73
  voicci config show
@@ -63,67 +76,183 @@ voicci config set-quality best
63
76
  voicci memory
64
77
  \`\`\`
65
78
 
66
- **Help:**
67
- \`\`\`bash
68
- voicci --help
69
- voicci config --help
79
+ \`\`\`!
80
+ #!/bin/bash
81
+ # Execute voicci with user-provided arguments
82
+ voicci $ARGUMENTS
70
83
  \`\`\`
71
84
 
72
85
  ## Important Notes
73
86
  - Book downloads require copyright compliance (public domain, owned books, academic papers)
74
87
  - Processing runs in background - check status with \`voicci -s\`
75
- - Audiobooks saved to \`~/Library/Application Support/voicci/audiobooks/\` (macOS) or \`~/.local/share/voicci/audiobooks/\` (Linux)
88
+ - Audiobooks saved to:
89
+ - macOS: \`~/Library/Application Support/voicci/audiobooks/\`
90
+ - Linux: \`~/.local/share/voicci/audiobooks/\`
76
91
  - Copyright warning will appear before first book search
77
92
 
78
- ## When User Says
79
- - "find/search/download [book name]" Run \`voicci "[book name]"\`
80
- - "convert [file]" Run \`voicci [file]\`
81
- - "summarize [file]" Run \`voicci summary [file]\`
82
- - "check status" Run \`voicci -s\`
83
- - "list audiobooks" Run \`voicci -l\`
84
-
85
- Execute the appropriate command now based on the user's request.
86
- PROMPT_EOF
93
+ ## Usage Examples
94
+ - \`/voicci-audiobook "Lord of the Rings"\` - Search and convert book
95
+ - \`/voicci-audiobook ~/Documents/book.pdf\` - Convert local file
96
+ - \`/voicci-audiobook -s\` - Check all job statuses
97
+ - \`/voicci-audiobook summary book.pdf\` - Generate summary only
98
+ - \`/voicci-audiobook --help\` - Show all options
87
99
  `;
88
100
 
89
- try {
101
+ // Editor detection configurations
102
+ const EDITORS = {
103
+ 'Claude Code': {
104
+ name: 'Claude Code',
105
+ detect: () => {
106
+ const homeDir = os.homedir();
107
+ // Check for claude command or .claude directory
108
+ if (fs.existsSync(path.join(homeDir, '.claude'))) return true;
109
+ try {
110
+ execFileSync('which', ['claude'], { stdio: 'ignore' });
111
+ return true;
112
+ } catch {
113
+ return false;
114
+ }
115
+ },
116
+ skillsDir: () => path.join(os.homedir(), '.claude', 'skills'),
117
+ skillName: SKILL_NAME
118
+ },
119
+ 'OpenCode': {
120
+ name: 'OpenCode',
121
+ detect: () => {
122
+ const homeDir = os.homedir();
123
+ // Check for opencode command or config directory
124
+ if (fs.existsSync(path.join(homeDir, '.opencode'))) return true;
125
+ try {
126
+ execFileSync('which', ['opencode'], { stdio: 'ignore' });
127
+ return true;
128
+ } catch {
129
+ return false;
130
+ }
131
+ },
132
+ skillsDir: () => path.join(os.homedir(), '.opencode', 'skills'),
133
+ skillName: SKILL_NAME
134
+ },
135
+ 'Cursor': {
136
+ name: 'Cursor',
137
+ detect: () => {
138
+ const homeDir = os.homedir();
139
+ // Check for cursor command or config directory
140
+ if (fs.existsSync(path.join(homeDir, '.cursor'))) return true;
141
+ if (fs.existsSync(path.join(homeDir, 'Library', 'Application Support', 'Cursor'))) return true;
142
+ try {
143
+ execFileSync('which', ['cursor'], { stdio: 'ignore' });
144
+ return true;
145
+ } catch {
146
+ return false;
147
+ }
148
+ },
149
+ skillsDir: () => {
150
+ const homeDir = os.homedir();
151
+ // Try common locations
152
+ const locations = [
153
+ path.join(homeDir, '.cursor', 'skills'),
154
+ path.join(homeDir, 'Library', 'Application Support', 'Cursor', 'skills')
155
+ ];
156
+ for (const loc of locations) {
157
+ const parent = path.dirname(loc);
158
+ if (fs.existsSync(parent)) return loc;
159
+ }
160
+ return locations[0]; // Default to first
161
+ },
162
+ skillName: SKILL_NAME
163
+ },
164
+ 'Windsurf': {
165
+ name: 'Windsurf',
166
+ detect: () => {
167
+ const homeDir = os.homedir();
168
+ // Check for windsurf command or config directory
169
+ if (fs.existsSync(path.join(homeDir, '.windsurf'))) return true;
170
+ try {
171
+ execFileSync('which', ['windsurf'], { stdio: 'ignore' });
172
+ return true;
173
+ } catch {
174
+ return false;
175
+ }
176
+ },
177
+ skillsDir: () => path.join(os.homedir(), '.windsurf', 'skills'),
178
+ skillName: SKILL_NAME
179
+ }
180
+ };
181
+
182
+ function detectAndInstall() {
90
183
  const homeDir = os.homedir();
91
- const claudeSkillsDir = path.join(homeDir, '.claude', 'skills', 'shorthand');
92
-
93
- // Check if .claude directory exists
94
- if (!fs.existsSync(path.join(homeDir, '.claude'))) {
95
- console.log('⚠️ Claude Code not detected (~/.claude directory not found)');
96
- console.log(' The voicci CLI tool is installed, but the Claude Code skill was not installed.');
97
- console.log(' Install Claude Code to use /voicci as a skill.');
98
- process.exit(0);
184
+ const installedEditors = [];
185
+ const failedEditors = [];
186
+
187
+ console.log('🔍 Detecting AI code editors...\n');
188
+
189
+ // Detect and install for each editor
190
+ for (const [key, editor] of Object.entries(EDITORS)) {
191
+ try {
192
+ if (editor.detect()) {
193
+ console.log(`✓ Found ${editor.name}`);
194
+
195
+ const skillsDir = editor.skillsDir();
196
+ const skillFile = path.join(skillsDir, editor.skillName);
197
+
198
+ // Create skills directory if it doesn't exist
199
+ if (!fs.existsSync(skillsDir)) {
200
+ fs.mkdirSync(skillsDir, { recursive: true });
201
+ }
202
+
203
+ // Check for conflicts with existing files
204
+ if (fs.existsSync(skillFile)) {
205
+ const existingContent = fs.readFileSync(skillFile, 'utf8');
206
+ // Only skip if it's already our skill
207
+ if (existingContent.includes('voicci $ARGUMENTS')) {
208
+ console.log(` ↳ Skill already installed at: ${skillFile}`);
209
+ installedEditors.push({ name: editor.name, path: skillFile, status: 'exists' });
210
+ continue;
211
+ }
212
+ }
213
+
214
+ // Write the skill file
215
+ fs.writeFileSync(skillFile, SKILL_CONTENT, 'utf8');
216
+ console.log(` ↳ Installed skill: ${skillFile}`);
217
+ installedEditors.push({ name: editor.name, path: skillFile, status: 'new' });
218
+ }
219
+ } catch (error) {
220
+ failedEditors.push({ name: editor.name, error: error.message });
221
+ }
99
222
  }
100
223
 
101
- // Create skills directory if it doesn't exist
102
- if (!fs.existsSync(claudeSkillsDir)) {
103
- fs.mkdirSync(claudeSkillsDir, { recursive: true });
224
+ // Summary
225
+ console.log('\n' + '═'.repeat(60));
226
+
227
+ if (installedEditors.length > 0) {
228
+ console.log('\n✅ Voicci CLI installed successfully!');
229
+ console.log('\n📦 Command-line tool: voicci');
230
+ console.log('🔧 Skill command: /voicci-audiobook');
231
+ console.log('\n📍 Installed in:');
232
+ installedEditors.forEach(editor => {
233
+ const status = editor.status === 'new' ? '(new)' : '(already installed)';
234
+ console.log(` • ${editor.name} ${status}`);
235
+ });
236
+
237
+ console.log('\n💡 Usage:');
238
+ console.log(' 1. Restart your AI code editor');
239
+ console.log(' 2. Use: /voicci-audiobook "search query"');
240
+ console.log(' 3. Or use CLI directly: voicci "your search query"');
241
+ } else {
242
+ console.log('\n⚠️ No supported AI code editors detected');
243
+ console.log('\nSupported editors: Claude Code, OpenCode, Cursor, Windsurf');
244
+ console.log('\n✓ You can still use the CLI: voicci <command>');
245
+ }
246
+
247
+ if (failedEditors.length > 0) {
248
+ console.log('\n⚠️ Failed to install for:');
249
+ failedEditors.forEach(({ name, error }) => {
250
+ console.log(` • ${name}: ${error}`);
251
+ });
104
252
  }
105
253
 
106
- // Write skill file
107
- const skillPath = path.join(claudeSkillsDir, 'voicci.sh');
108
- fs.writeFileSync(skillPath, skillContent, { mode: 0o755 });
109
-
110
- console.log('✅ Voicci CLI installed successfully!');
111
- console.log('');
112
- console.log('📦 Command-line tool: voicci');
113
- console.log('🎯 Claude Code skill: /voicci');
114
- console.log('');
115
- console.log('Try it:');
116
- console.log(' $ voicci --help');
117
- console.log(' $ claude');
118
- console.log(' ❯ /voicci Lord of the Rings');
119
- console.log('');
120
- console.log('Docs: https://voicci.com/voicci-cli');
121
-
122
- } catch (error) {
123
- console.error('⚠️ Warning: Could not install Claude Code skill');
124
- console.error(' Error:', error.message);
125
- console.log('');
126
- console.log('✅ Voicci CLI tool installed successfully!');
127
- console.log(' Run: voicci --help');
128
- process.exit(0);
254
+ console.log('\n' + '═'.repeat(60));
255
+ console.log();
129
256
  }
257
+
258
+ detectAndInstall();