voicci 1.0.8 → 1.0.10

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "voicci",
3
- "version": "1.0.8",
3
+ "version": "1.0.10",
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",
@@ -9,12 +9,13 @@ import { execFileSync } from 'child_process';
9
9
  const __filename = fileURLToPath(import.meta.url);
10
10
  const __dirname = path.dirname(__filename);
11
11
 
12
- // Two skill files: simple and detailed
13
- const SKILL_NAME_SIMPLE = 'voicci.md';
14
- const SKILL_NAME_DETAILED = 'voicci-audiobook.md';
15
-
16
- const SKILL_CONTENT_SIMPLE = `---
17
- description: "Voicci - AI audiobook generator"
12
+ // Skills use directory-based format: skills/<name>/SKILL.md
13
+ const SKILLS = [
14
+ {
15
+ dirName: 'voicci',
16
+ content: `---
17
+ name: voicci
18
+ description: "Voicci - AI audiobook generator. Use when the user wants to convert books, PDFs, or documents to audiobooks."
18
19
  argument-hint: "COMMAND_OR_FILE"
19
20
  ---
20
21
 
@@ -33,10 +34,13 @@ Convert books, PDFs, and documents to audiobooks using AI text-to-speech.
33
34
  #!/bin/bash
34
35
  voicci $ARGUMENTS
35
36
  \`\`\`
36
- `;
37
-
38
- const SKILL_CONTENT_DETAILED = `---
39
- description: "Voicci - AI audiobook generator CLI"
37
+ `
38
+ },
39
+ {
40
+ dirName: 'voicci-audiobook',
41
+ content: `---
42
+ name: voicci-audiobook
43
+ description: "Voicci - AI audiobook generator with full documentation. Use when the user needs detailed help with audiobook generation."
40
44
  argument-hint: "COMMAND_OR_FILE"
41
45
  ---
42
46
 
@@ -101,7 +105,6 @@ voicci memory
101
105
 
102
106
  \`\`\`!
103
107
  #!/bin/bash
104
- # Execute voicci with user-provided arguments
105
108
  voicci $ARGUMENTS
106
109
  \`\`\`
107
110
 
@@ -112,14 +115,9 @@ voicci $ARGUMENTS
112
115
  - macOS: \`~/Library/Application Support/voicci/audiobooks/\`
113
116
  - Linux: \`~/.local/share/voicci/audiobooks/\`
114
117
  - Copyright warning will appear before first book search
115
-
116
- ## Usage Examples
117
- - \`/voicci-audiobook "Lord of the Rings"\` - Search and convert book
118
- - \`/voicci-audiobook ~/Documents/book.pdf\` - Convert local file
119
- - \`/voicci-audiobook -s\` - Check all job statuses
120
- - \`/voicci-audiobook summary book.pdf\` - Generate summary only
121
- - \`/voicci-audiobook --help\` - Show all options
122
- `;
118
+ `
119
+ }
120
+ ];
123
121
 
124
122
  // Editor detection configurations
125
123
  const EDITORS = {
@@ -127,7 +125,6 @@ const EDITORS = {
127
125
  name: 'Claude Code',
128
126
  detect: () => {
129
127
  const homeDir = os.homedir();
130
- // Check for claude command or .claude directory
131
128
  if (fs.existsSync(path.join(homeDir, '.claude'))) return true;
132
129
  try {
133
130
  execFileSync('which', ['claude'], { stdio: 'ignore' });
@@ -142,7 +139,6 @@ const EDITORS = {
142
139
  name: 'OpenCode',
143
140
  detect: () => {
144
141
  const homeDir = os.homedir();
145
- // Check for opencode command or config directory
146
142
  if (fs.existsSync(path.join(homeDir, '.opencode'))) return true;
147
143
  try {
148
144
  execFileSync('which', ['opencode'], { stdio: 'ignore' });
@@ -157,7 +153,6 @@ const EDITORS = {
157
153
  name: 'Cursor',
158
154
  detect: () => {
159
155
  const homeDir = os.homedir();
160
- // Check for cursor command or config directory
161
156
  if (fs.existsSync(path.join(homeDir, '.cursor'))) return true;
162
157
  if (fs.existsSync(path.join(homeDir, 'Library', 'Application Support', 'Cursor'))) return true;
163
158
  try {
@@ -169,23 +164,20 @@ const EDITORS = {
169
164
  },
170
165
  skillsDir: () => {
171
166
  const homeDir = os.homedir();
172
- // Try common locations
173
167
  const locations = [
174
168
  path.join(homeDir, '.cursor', 'skills'),
175
169
  path.join(homeDir, 'Library', 'Application Support', 'Cursor', 'skills')
176
170
  ];
177
171
  for (const loc of locations) {
178
- const parent = path.dirname(loc);
179
- if (fs.existsSync(parent)) return loc;
172
+ if (fs.existsSync(path.dirname(loc))) return loc;
180
173
  }
181
- return locations[0]; // Default to first
174
+ return locations[0];
182
175
  }
183
176
  },
184
177
  'Windsurf': {
185
178
  name: 'Windsurf',
186
179
  detect: () => {
187
180
  const homeDir = os.homedir();
188
- // Check for windsurf command or config directory
189
181
  if (fs.existsSync(path.join(homeDir, '.windsurf'))) return true;
190
182
  try {
191
183
  execFileSync('which', ['windsurf'], { stdio: 'ignore' });
@@ -198,55 +190,63 @@ const EDITORS = {
198
190
  }
199
191
  };
200
192
 
201
- function installSkillFile(skillsDir, skillName, content) {
202
- const skillFile = path.join(skillsDir, skillName);
203
-
193
+ function installSkill(skillsDir, skill) {
194
+ const skillDir = path.join(skillsDir, skill.dirName);
195
+ const skillFile = path.join(skillDir, 'SKILL.md');
196
+
204
197
  // Check if already installed
205
198
  if (fs.existsSync(skillFile)) {
206
199
  const existingContent = fs.readFileSync(skillFile, 'utf8');
207
- if (existingContent.includes('voicci $ARGUMENTS')) {
200
+ if (existingContent.includes('voicci')) {
208
201
  return 'exists';
209
202
  }
210
203
  }
211
-
212
- // Write the skill file
213
- fs.writeFileSync(skillFile, content, 'utf8');
204
+
205
+ // Create skill directory and write SKILL.md
206
+ fs.mkdirSync(skillDir, { recursive: true });
207
+ fs.writeFileSync(skillFile, skill.content, 'utf8');
208
+
209
+ // Clean up legacy flat file if it exists
210
+ const legacyFile = path.join(skillsDir, `${skill.dirName}.md`);
211
+ if (fs.existsSync(legacyFile)) {
212
+ fs.unlinkSync(legacyFile);
213
+ }
214
+
214
215
  return 'new';
215
216
  }
216
217
 
217
218
  function detectAndInstall() {
218
- const homeDir = os.homedir();
219
219
  const installedEditors = [];
220
220
  const failedEditors = [];
221
221
 
222
- console.log('🔍 Detecting AI code editors...\n');
222
+ console.log('Detecting AI code editors...\n');
223
223
 
224
- // Detect and install for each editor
225
224
  for (const [key, editor] of Object.entries(EDITORS)) {
226
225
  try {
227
226
  if (editor.detect()) {
228
- console.log(`✓ Found ${editor.name}`);
227
+ console.log(` Found ${editor.name}`);
229
228
 
230
229
  const skillsDir = editor.skillsDir();
231
230
 
232
- // Create skills directory if it doesn't exist
231
+ // Create skills directory if needed
233
232
  if (!fs.existsSync(skillsDir)) {
234
233
  fs.mkdirSync(skillsDir, { recursive: true });
235
234
  }
236
235
 
237
- // Install both skills
238
- const simpleStatus = installSkillFile(skillsDir, SKILL_NAME_SIMPLE, SKILL_CONTENT_SIMPLE);
239
- const detailedStatus = installSkillFile(skillsDir, SKILL_NAME_DETAILED, SKILL_CONTENT_DETAILED);
236
+ let anyNew = false;
240
237
 
241
- const simpleFile = path.join(skillsDir, SKILL_NAME_SIMPLE);
242
- const detailedFile = path.join(skillsDir, SKILL_NAME_DETAILED);
238
+ for (const skill of SKILLS) {
239
+ const status = installSkill(skillsDir, skill);
240
+ if (status === 'new') {
241
+ anyNew = true;
242
+ console.log(` Installed: ${path.join(skillsDir, skill.dirName, 'SKILL.md')}`);
243
+ }
244
+ }
243
245
 
244
- if (simpleStatus === 'exists' && detailedStatus === 'exists') {
245
- console.log(`Skills already installed`);
246
+ if (!anyNew) {
247
+ console.log(` Skills already installed`);
246
248
  installedEditors.push({ name: editor.name, status: 'exists' });
247
249
  } else {
248
- if (simpleStatus === 'new') console.log(` ↳ Installed: ${simpleFile}`);
249
- if (detailedStatus === 'new') console.log(` ↳ Installed: ${detailedFile}`);
250
250
  installedEditors.push({ name: editor.name, status: 'new' });
251
251
  }
252
252
  }
@@ -256,37 +256,36 @@ function detectAndInstall() {
256
256
  }
257
257
 
258
258
  // Summary
259
- console.log('\n' + ''.repeat(60));
259
+ console.log('\n' + '='.repeat(60));
260
260
 
261
261
  if (installedEditors.length > 0) {
262
- console.log('\n✅ Voicci CLI installed successfully!');
263
- console.log('\n📦 Command-line tool: voicci');
264
- console.log('🔧 Skill commands: /voicci OR /voicci-audiobook');
265
- console.log('\n📍 Installed in:');
262
+ console.log('\nVoicci CLI installed successfully!');
263
+ console.log('\n Command-line tool: voicci');
264
+ console.log(' Skill commands: /voicci OR /voicci-audiobook');
265
+ console.log('\n Installed in:');
266
266
  installedEditors.forEach(editor => {
267
267
  const status = editor.status === 'new' ? '(new)' : '(already installed)';
268
- console.log(`${editor.name} ${status}`);
268
+ console.log(` ${editor.name} ${status}`);
269
269
  });
270
270
 
271
- console.log('\n💡 Usage:');
272
- console.log(' 1. Restart your AI code editor');
273
- console.log(' 2. Use: /voicci "search query" (simple)');
274
- console.log(' 3. Or: /voicci-audiobook "search query" (detailed docs)');
275
- console.log(' 4. Or CLI: voicci "your search query"');
271
+ console.log('\n Usage:');
272
+ console.log(' 1. Restart your AI code editor');
273
+ console.log(' 2. Type: /voicci "search query"');
274
+ console.log(' 3. Or CLI: voicci "your search query"');
276
275
  } else {
277
- console.log('\n⚠️ No supported AI code editors detected');
278
- console.log('\nSupported editors: Claude Code, OpenCode, Cursor, Windsurf');
279
- console.log('\nYou can still use the CLI: voicci <command>');
276
+ console.log('\n No supported AI code editors detected');
277
+ console.log('\n Supported editors: Claude Code, OpenCode, Cursor, Windsurf');
278
+ console.log('\n You can still use the CLI: voicci <command>');
280
279
  }
281
280
 
282
281
  if (failedEditors.length > 0) {
283
- console.log('\n⚠️ Failed to install for:');
282
+ console.log('\n Failed to install for:');
284
283
  failedEditors.forEach(({ name, error }) => {
285
- console.log(`${name}: ${error}`);
284
+ console.log(` ${name}: ${error}`);
286
285
  });
287
286
  }
288
287
 
289
- console.log('\n' + ''.repeat(60));
288
+ console.log('\n' + '='.repeat(60));
290
289
  console.log();
291
290
  }
292
291
 
@@ -1,69 +0,0 @@
1
- name: Publish to npm
2
-
3
- on:
4
- push:
5
- tags:
6
- - 'v*'
7
-
8
- jobs:
9
- test:
10
- runs-on: ubuntu-latest
11
-
12
- steps:
13
- - name: Checkout code
14
- uses: actions/checkout@v4
15
-
16
- - name: Setup Node.js
17
- uses: actions/setup-node@v4
18
- with:
19
- node-version: '18'
20
-
21
- - name: Install dependencies
22
- run: npm ci
23
-
24
- - name: Run tests
25
- run: npm test
26
-
27
- publish:
28
- needs: test
29
- runs-on: ubuntu-latest
30
-
31
- steps:
32
- - name: Checkout code
33
- uses: actions/checkout@v4
34
-
35
- - name: Setup Node.js
36
- uses: actions/setup-node@v4
37
- with:
38
- node-version: '18'
39
- registry-url: 'https://registry.npmjs.org'
40
-
41
- - name: Install dependencies
42
- run: npm ci
43
-
44
- - name: Publish to npm
45
- run: npm publish
46
- env:
47
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
48
-
49
- - name: Create GitHub Release
50
- uses: actions/create-release@v1
51
- env:
52
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
53
- with:
54
- tag_name: ${{ github.ref }}
55
- release_name: Release ${{ github.ref }}
56
- body: |
57
- ## Installation
58
- ```bash
59
- npm install -g voicci
60
- ```
61
-
62
- Or via install script:
63
- ```bash
64
- curl -fsSL https://voicci.com/voicci-cli/install.sh | bash
65
- ```
66
-
67
- See [CHANGELOG.md](https://github.com/voicci/voicci-cli/blob/main/CHANGELOG.md) for details.
68
- draft: false
69
- prerelease: false
@@ -1,33 +0,0 @@
1
- name: Run Tests
2
-
3
- on:
4
- push:
5
- branches: [ main ]
6
- pull_request:
7
- branches: [ main ]
8
-
9
- jobs:
10
- test:
11
- runs-on: ubuntu-latest
12
-
13
- strategy:
14
- matrix:
15
- node-version: [18.x, 20.x]
16
-
17
- steps:
18
- - name: Checkout code
19
- uses: actions/checkout@v4
20
-
21
- - name: Setup Node.js ${{ matrix.node-version }}
22
- uses: actions/setup-node@v4
23
- with:
24
- node-version: ${{ matrix.node-version }}
25
-
26
- - name: Install dependencies
27
- run: npm ci
28
-
29
- - name: Run tests
30
- run: npm test
31
-
32
- - name: Check package can be packed
33
- run: npm pack --dry-run
package/install.sh DELETED
@@ -1,198 +0,0 @@
1
- #!/bin/bash
2
-
3
- # Voicci Installer
4
- # Converts PDF/text files to high-quality audiobooks using XTTS v2 AI
5
-
6
- set -e
7
-
8
- # Colors for output
9
- RED='\033[0;31m'
10
- GREEN='\033[0;32m'
11
- YELLOW='\033[1;33m'
12
- BLUE='\033[0;34m'
13
- NC='\033[0m' # No Color
14
-
15
- echo -e "${BLUE}╔════════════════════════════════════════╗${NC}"
16
- echo -e "${BLUE}║ Voicci Installer v1.0 ║${NC}"
17
- echo -e "${BLUE}║ AI Audiobook Generator (XTTS v2) ║${NC}"
18
- echo -e "${BLUE}╚════════════════════════════════════════╝${NC}"
19
- echo ""
20
-
21
- # Detect OS
22
- OS="$(uname -s)"
23
- case "${OS}" in
24
- Linux*) OS_TYPE=Linux;;
25
- Darwin*) OS_TYPE=Mac;;
26
- *) OS_TYPE="UNKNOWN:${OS}"
27
- esac
28
-
29
- if [[ "$OS_TYPE" == "UNKNOWN"* ]]; then
30
- echo -e "${RED}✗${NC} Unsupported operating system: ${OS}"
31
- echo "Voicci currently supports macOS and Linux only."
32
- exit 1
33
- fi
34
-
35
- echo -e "${GREEN}✓${NC} Detected OS: ${OS_TYPE}"
36
-
37
- # Check dependencies
38
- echo ""
39
- echo "Checking dependencies..."
40
-
41
- # Check Node.js
42
- if command -v node &> /dev/null; then
43
- NODE_VERSION=$(node --version)
44
- echo -e "${GREEN}✓${NC} Node.js $NODE_VERSION found"
45
- else
46
- echo -e "${RED}✗${NC} Node.js not found"
47
- echo "Please install Node.js 18+ from https://nodejs.org/"
48
- exit 1
49
- fi
50
-
51
- # Check npm
52
- if command -v npm &> /dev/null; then
53
- NPM_VERSION=$(npm --version)
54
- echo -e "${GREEN}✓${NC} npm $NPM_VERSION found"
55
- else
56
- echo -e "${RED}✗${NC} npm not found"
57
- exit 1
58
- fi
59
-
60
- # Check Python
61
- if command -v python3 &> /dev/null; then
62
- PYTHON_VERSION=$(python3 --version 2>&1 | awk '{print $2}')
63
- PYTHON_MAJOR=$(echo $PYTHON_VERSION | cut -d. -f1)
64
- PYTHON_MINOR=$(echo $PYTHON_VERSION | cut -d. -f2)
65
-
66
- if [[ $PYTHON_MAJOR -ge 3 ]] && [[ $PYTHON_MINOR -ge 9 ]]; then
67
- echo -e "${GREEN}✓${NC} Python $PYTHON_VERSION found"
68
- else
69
- echo -e "${RED}✗${NC} Python 3.9+ required (found $PYTHON_VERSION)"
70
- exit 1
71
- fi
72
- else
73
- echo -e "${RED}✗${NC} Python 3 not found"
74
- echo "Please install Python 3.9+ from https://www.python.org/"
75
- exit 1
76
- fi
77
-
78
- # Check pip
79
- if command -v pip3 &> /dev/null; then
80
- echo -e "${GREEN}✓${NC} pip3 found"
81
- else
82
- echo -e "${RED}✗${NC} pip3 not found"
83
- exit 1
84
- fi
85
-
86
- # Check pdftotext (optional but recommended)
87
- if command -v pdftotext &> /dev/null; then
88
- echo -e "${GREEN}✓${NC} pdftotext found"
89
- else
90
- echo -e "${YELLOW}⚠${NC} pdftotext not found (optional, for PDF support)"
91
- echo "Install with: brew install poppler (Mac) or apt-get install poppler-utils (Linux)"
92
- fi
93
-
94
- # Determine installation directory
95
- if [[ "$OS_TYPE" == "Mac" ]]; then
96
- INSTALL_DIR="$HOME/Library/Application Support/voicci"
97
- else
98
- INSTALL_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/voicci"
99
- fi
100
-
101
- echo ""
102
- echo -e "Installation directory: ${BLUE}$INSTALL_DIR${NC}"
103
- echo ""
104
-
105
- # Ask for confirmation
106
- read -p "Continue with installation? (y/n) " -n 1 -r
107
- echo
108
- if [[ ! $REPLY =~ ^[Yy]$ ]]; then
109
- echo "Installation cancelled."
110
- exit 0
111
- fi
112
-
113
- # Create installation directory
114
- echo ""
115
- echo "Creating directories..."
116
- mkdir -p "$INSTALL_DIR"/{lib,cli,backend}
117
- echo -e "${GREEN}✓${NC} Directories created"
118
-
119
- # Download Voicci files (in production, this would download from GitHub/website)
120
- echo ""
121
- echo "Installing Voicci..."
122
-
123
- # For now, we'll create the files directly
124
- # In production, this would be: curl -fsSL https://voicci.com/voicci-cli/voicci.tar.gz | tar -xz -C "$INSTALL_DIR"
125
-
126
- # Install Node.js dependencies
127
- cd "$INSTALL_DIR"
128
- echo ""
129
- echo "Installing Node.js dependencies..."
130
-
131
- cat > package.json <<'EOF'
132
- {
133
- "name": "voicci",
134
- "version": "1.0.0",
135
- "description": "AI Audiobook Generator using XTTS v2",
136
- "type": "module",
137
- "bin": {
138
- "voicci": "./cli/index.js"
139
- },
140
- "dependencies": {
141
- "commander": "^11.1.0",
142
- "better-sqlite3": "^9.2.2",
143
- "uuid": "^9.0.1",
144
- "ink": "^4.4.1",
145
- "react": "^18.2.0",
146
- "chalk": "^5.3.0"
147
- },
148
- "engines": {
149
- "node": ">=18.0.0"
150
- }
151
- }
152
- EOF
153
-
154
- npm install --silent --no-audit --no-fund 2>&1 | grep -v "npm WARN"
155
- echo -e "${GREEN}✓${NC} Node.js dependencies installed"
156
-
157
- # Install Python dependencies
158
- echo ""
159
- echo "Installing Python dependencies..."
160
- echo "This may take several minutes (downloading XTTS v2 model ~450MB)..."
161
-
162
- pip3 install --quiet --upgrade pip
163
- pip3 install --quiet TTS torch torchaudio
164
-
165
- echo -e "${GREEN}✓${NC} Python dependencies installed"
166
-
167
- # Download XTTS v2 model
168
- echo ""
169
- echo "Downloading XTTS v2 model (this may take a few minutes)..."
170
- python3 -c "from TTS.api import TTS; TTS('tts_models/multilingual/multi-dataset/xtts_v2')" &>/dev/null || true
171
- echo -e "${GREEN}✓${NC} XTTS v2 model downloaded"
172
-
173
- # Create symlink for global access
174
- BIN_DIR="/usr/local/bin"
175
- if [[ -w "$BIN_DIR" ]]; then
176
- ln -sf "$INSTALL_DIR/cli/index.js" "$BIN_DIR/voicci"
177
- echo -e "${GREEN}✓${NC} Global command 'voicci' installed"
178
- else
179
- echo -e "${YELLOW}⚠${NC} Could not create global command (insufficient permissions)"
180
- echo "Add to your PATH manually: export PATH=\"$INSTALL_DIR/cli:\$PATH\""
181
- fi
182
-
183
- # Final message
184
- echo ""
185
- echo -e "${GREEN}╔════════════════════════════════════════╗${NC}"
186
- echo -e "${GREEN}║ Installation Complete! 🎉 ║${NC}"
187
- echo -e "${GREEN}╚════════════════════════════════════════╝${NC}"
188
- echo ""
189
- echo "Usage:"
190
- echo -e " ${BLUE}voicci mybook.pdf${NC} - Convert PDF to audiobook"
191
- echo -e " ${BLUE}voicci -s${NC} - Check all job statuses"
192
- echo -e " ${BLUE}voicci -l${NC} - List completed audiobooks"
193
- echo -e " ${BLUE}voicci -o <jobId>${NC} - Open audiobook folder"
194
- echo ""
195
- echo "Installation location: $INSTALL_DIR"
196
- echo ""
197
- echo "Get started: voicci --help"
198
- echo ""