agentvibes 4.0.1 → 4.4.0
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/.agentvibes/bmad/bmad-voices.md +69 -69
- package/.agentvibes/config.json +12 -0
- package/.claude/activation-instructions +54 -54
- package/.claude/audio/tracks/README.md +52 -52
- package/.claude/commands/agent-vibes/add.md +21 -21
- package/.claude/commands/agent-vibes/agent-vibes.md +101 -101
- package/.claude/commands/agent-vibes/agent.md +79 -79
- package/.claude/commands/agent-vibes/background-music.md +111 -111
- package/.claude/commands/agent-vibes/bmad.md +198 -198
- package/.claude/commands/agent-vibes/clean.md +18 -18
- package/.claude/commands/agent-vibes/cleanup.md +18 -18
- package/.claude/commands/agent-vibes/commands.json +145 -145
- package/.claude/commands/agent-vibes/effects.md +97 -97
- package/.claude/commands/agent-vibes/get.md +9 -9
- package/.claude/commands/agent-vibes/hide.md +91 -91
- package/.claude/commands/agent-vibes/language.md +23 -23
- package/.claude/commands/agent-vibes/learn.md +67 -67
- package/.claude/commands/agent-vibes/list.md +13 -13
- package/.claude/commands/agent-vibes/mute.md +37 -37
- package/.claude/commands/agent-vibes/preview.md +17 -17
- package/.claude/commands/agent-vibes/provider.md +68 -68
- package/.claude/commands/agent-vibes/replay-target.md +14 -14
- package/.claude/commands/agent-vibes/sample.md +12 -12
- package/.claude/commands/agent-vibes/set-favorite-voice.md +84 -84
- package/.claude/commands/agent-vibes/set-pretext.md +65 -65
- package/.claude/commands/agent-vibes/set-speed.md +41 -41
- package/.claude/commands/agent-vibes/show.md +84 -84
- package/.claude/commands/agent-vibes/switch.md +87 -87
- package/.claude/commands/agent-vibes/target-voice.md +26 -26
- package/.claude/commands/agent-vibes/target.md +30 -30
- package/.claude/commands/agent-vibes/translate.md +68 -68
- package/.claude/commands/agent-vibes/unmute.md +45 -45
- package/.claude/commands/agent-vibes/verbosity.md +89 -89
- package/.claude/commands/agent-vibes/whoami.md +7 -7
- package/.claude/commands/agent-vibes-bmad-voices.md +117 -117
- package/.claude/commands/agent-vibes-rdp.md +24 -24
- package/.claude/config/agentvibes.json +1 -0
- package/.claude/config/audio-effects.cfg +3 -2
- package/.claude/config/audio-effects.cfg.sample +52 -52
- package/.claude/config/background-music-volume.txt +1 -0
- package/.claude/config/intro-text.txt +1 -0
- package/.claude/config/piper-speech-rate.txt +4 -0
- package/.claude/config/piper-target-speech-rate.txt +1 -0
- package/.claude/config/reverb-level.txt +1 -0
- package/.claude/config/tts-speech-rate.txt +4 -0
- package/.claude/config/tts-target-speech-rate.txt +1 -0
- package/.claude/docs/TERMUX_SETUP.md +408 -408
- package/.claude/github-star-reminder.txt +1 -1
- package/.claude/hooks/README-TTS-QUEUE.md +135 -135
- package/.claude/hooks/audio-cache-utils.sh +246 -246
- package/.claude/hooks/audio-processor.sh +433 -389
- package/.claude/hooks/background-music-manager.sh +404 -404
- package/.claude/hooks/bmad-speak-enhanced.sh +165 -165
- package/.claude/hooks/bmad-speak.sh +269 -112
- package/.claude/hooks/bmad-tts-injector.sh +568 -568
- package/.claude/hooks/bmad-voice-manager.sh +928 -928
- package/.claude/hooks/clawdbot-receiver-SECURE.sh +129 -129
- package/.claude/hooks/clawdbot-receiver.sh +107 -107
- package/.claude/hooks/clean-audio-cache.sh +22 -22
- package/.claude/hooks/cleanup-cache.sh +106 -106
- package/.claude/hooks/configure-rdp-mode.sh +137 -137
- package/.claude/hooks/download-extra-voices.sh +244 -244
- package/.claude/hooks/effects-manager.sh +268 -268
- package/.claude/hooks/github-star-reminder.sh +154 -154
- package/.claude/hooks/language-manager.sh +362 -362
- package/.claude/hooks/learn-manager.sh +492 -492
- package/.claude/hooks/macos-voice-manager.sh +205 -205
- package/.claude/hooks/migrate-background-music.sh +125 -125
- package/.claude/hooks/migrate-to-agentvibes.sh +161 -161
- package/.claude/hooks/optimize-background-music.sh +87 -87
- package/.claude/hooks/path-resolver.sh +60 -60
- package/.claude/hooks/personality-manager.sh +448 -448
- package/.claude/hooks/piper-download-voices.sh +225 -225
- package/.claude/hooks/piper-installer.sh +292 -292
- package/.claude/hooks/piper-multispeaker-registry.sh +171 -171
- package/.claude/hooks/piper-voice-manager.sh +24 -3
- package/.claude/hooks/play-tts-agentvibes-receiver-for-voiceless-connections.sh +90 -90
- package/.claude/hooks/play-tts-enhanced.sh +105 -70
- package/.claude/hooks/play-tts-macos.sh +368 -345
- package/.claude/hooks/play-tts-piper.sh +679 -578
- package/.claude/hooks/play-tts-soprano.sh +356 -320
- package/.claude/hooks/play-tts-ssh-remote.sh +167 -88
- package/.claude/hooks/play-tts-termux-ssh.sh +169 -169
- package/.claude/hooks/play-tts.sh +301 -298
- package/.claude/hooks/prepare-release.sh +54 -54
- package/.claude/hooks/provider-commands.sh +617 -617
- package/.claude/hooks/provider-manager.sh +399 -399
- package/.claude/hooks/replay-target-audio.sh +95 -95
- package/.claude/hooks/requirements.txt +6 -6
- package/.claude/hooks/sentiment-manager.sh +201 -201
- package/.claude/hooks/session-start-tts.sh +81 -71
- package/.claude/hooks/soprano-gradio-synth.py +139 -139
- package/.claude/hooks/speed-manager.sh +291 -291
- package/.claude/hooks/stop-tts.sh +84 -0
- package/.claude/hooks/termux-installer.sh +261 -261
- package/.claude/hooks/translate-manager.sh +341 -341
- package/.claude/hooks/translator.py +237 -237
- package/.claude/hooks/tts-queue-worker.sh +145 -114
- package/.claude/hooks/tts-queue.sh +165 -136
- package/.claude/hooks/verbosity-manager.sh +178 -178
- package/.claude/hooks/voice-manager.sh +548 -544
- package/.claude/hooks-windows/audio-cache-utils.ps1 +119 -119
- package/.claude/hooks-windows/background-music-manager.ps1 +348 -0
- package/.claude/hooks-windows/clean-audio-cache.ps1 +53 -0
- package/.claude/hooks-windows/download-extra-voices.ps1 +185 -0
- package/.claude/hooks-windows/effects-manager.ps1 +294 -0
- package/.claude/hooks-windows/language-manager.ps1 +193 -0
- package/.claude/hooks-windows/learn-manager.ps1 +241 -0
- package/.claude/hooks-windows/personality-manager.ps1 +266 -0
- package/.claude/hooks-windows/play-tts-piper.ps1 +209 -0
- package/.claude/hooks-windows/play-tts-sapi.ps1 +108 -0
- package/.claude/hooks-windows/play-tts-soprano.ps1 +159 -158
- package/.claude/hooks-windows/play-tts-windows-piper.ps1 +50 -5
- package/.claude/hooks-windows/play-tts-windows-sapi.ps1 +108 -108
- package/.claude/hooks-windows/play-tts.ps1 +344 -266
- package/.claude/hooks-windows/provider-manager.ps1 +29 -10
- package/.claude/hooks-windows/session-start-tts.ps1 +124 -124
- package/.claude/hooks-windows/soprano-gradio-synth.py +153 -153
- package/.claude/hooks-windows/speed-manager.ps1 +166 -0
- package/.claude/hooks-windows/verbosity-manager.ps1 +119 -0
- package/.claude/hooks-windows/voice-manager-windows.ps1 +92 -8
- package/.claude/output-styles/agent-vibes.md +202 -202
- package/.claude/personalities/angry.md +14 -14
- package/.claude/personalities/annoying.md +14 -14
- package/.claude/personalities/crass.md +14 -14
- package/.claude/personalities/dramatic.md +14 -14
- package/.claude/personalities/dry-humor.md +50 -50
- package/.claude/personalities/flirty.md +20 -20
- package/.claude/personalities/funny.md +14 -14
- package/.claude/personalities/grandpa.md +32 -32
- package/.claude/personalities/millennial.md +14 -14
- package/.claude/personalities/moody.md +14 -14
- package/.claude/personalities/normal.md +16 -16
- package/.claude/personalities/pirate.md +14 -14
- package/.claude/personalities/poetic.md +14 -14
- package/.claude/personalities/professional.md +14 -14
- package/.claude/personalities/rapper.md +55 -55
- package/.claude/personalities/robot.md +14 -14
- package/.claude/personalities/sarcastic.md +38 -38
- package/.claude/personalities/sassy.md +14 -14
- package/.claude/personalities/surfer-dude.md +14 -14
- package/.claude/personalities/zen.md +14 -14
- package/.claude/settings.json +15 -15
- package/.claude/verbosity.txt +1 -1
- package/.clawdbot/README.md +105 -105
- package/.clawdbot/skill/SKILL.md +241 -241
- package/.mcp.json +12 -0
- package/CLAUDE.md +170 -181
- package/README.md +2029 -1909
- package/RELEASE_NOTES.md +1310 -66
- package/WINDOWS-SETUP.md +208 -208
- package/bin/agent-vibes +39 -39
- package/bin/agentvibes-voice-browser.js +1840 -1826
- package/bin/agentvibes.js +48 -2
- package/bin/mcp-server.js +121 -121
- package/bin/mcp-server.sh +206 -206
- package/bin/test-bmad-pr +78 -78
- package/mcp-server/QUICK_START.md +203 -203
- package/mcp-server/README.md +345 -345
- package/mcp-server/WINDOWS_SETUP.md +260 -260
- package/mcp-server/docs/troubleshooting-audio.md +313 -313
- package/mcp-server/examples/claude_desktop_config.json +11 -11
- package/mcp-server/examples/claude_desktop_config_piper.json +9 -9
- package/mcp-server/examples/custom_instructions.md +169 -169
- package/mcp-server/install-deps.js +130 -130
- package/mcp-server/pyproject.toml +52 -52
- package/mcp-server/requirements.txt +2 -2
- package/mcp-server/server.py +1465 -1417
- package/mcp-server/test_server.py +395 -395
- package/mcp-server/test_windows_script_parity.py +336 -0
- package/package.json +110 -112
- package/setup-windows.ps1 +815 -815
- package/src/bmad-detector.js +71 -71
- package/src/cli/list-personalities.js +110 -110
- package/src/cli/list-voices.js +114 -114
- package/src/commands/bmad-voices.js +394 -394
- package/src/commands/install-mcp.js +476 -476
- package/src/console/app.js +824 -806
- package/src/console/audio-env.js +20 -1
- package/src/console/brand-colors.js +13 -13
- package/src/console/constants/personalities.js +44 -0
- package/src/console/footer-config.js +50 -46
- package/src/console/modals/modal-overlay.js +247 -247
- package/src/console/navigation.js +62 -61
- package/src/console/tabs/agents-tab.js +1684 -369
- package/src/console/tabs/help-tab.js +261 -261
- package/src/console/tabs/install-tab.js +1007 -991
- package/src/console/tabs/music-tab.js +22 -8
- package/src/console/tabs/placeholder-tab.js +53 -46
- package/src/console/tabs/readme-tab.js +267 -267
- package/src/console/tabs/receiver-tab.js +1472 -0
- package/src/console/tabs/settings-tab.js +185 -402
- package/src/console/tabs/voices-tab.js +100 -21
- package/src/console/widgets/destroy-list.js +25 -0
- package/src/console/widgets/format-utils.js +89 -0
- package/src/console/widgets/notice.js +55 -0
- package/src/console/widgets/personality-picker.js +185 -0
- package/src/console/widgets/reverb-picker.js +94 -0
- package/src/console/widgets/track-picker.js +285 -0
- package/src/installer/music-file-input.js +304 -304
- package/src/installer.js +5882 -5777
- package/src/services/agent-voice-store.js +423 -163
- package/src/services/config-service.js +264 -264
- package/src/services/navigation-service.js +123 -123
- package/src/services/provider-service.js +132 -132
- package/src/services/verbosity-service.js +157 -157
- package/src/utils/audio-duration-validator.js +298 -298
- package/src/utils/audio-format-validator.js +277 -277
- package/src/utils/dependency-checker.js +469 -466
- package/src/utils/file-ownership-verifier.js +358 -358
- package/src/utils/list-formatter.js +194 -194
- package/src/utils/music-file-validator.js +285 -275
- package/src/utils/preview-list-prompt.js +136 -136
- package/src/utils/provider-validator.js +96 -12
- package/src/utils/secure-music-storage.js +412 -412
- package/templates/agentvibes-receiver.sh +482 -162
- package/templates/audio/welcome-music.mp3 +0 -0
- package/voice-assignments.json +8244 -8244
- package/.claude/config/background-music-position.txt +0 -1
|
@@ -1,194 +1,194 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* AgentVibes List Formatter
|
|
4
|
-
*
|
|
5
|
-
* Beautiful multi-column boxen displays for voices and personalities
|
|
6
|
-
* Inspired by BMAD-METHOD's installer UX
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import chalk from 'chalk';
|
|
10
|
-
import boxen from 'boxen';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Format items into multi-column layout
|
|
14
|
-
* @param {Array} items - Array of strings or objects with {name, description, current}
|
|
15
|
-
* @param {Object} options - Formatting options
|
|
16
|
-
* @returns {string} Formatted multi-column text
|
|
17
|
-
*/
|
|
18
|
-
export function formatColumns(items, options = {}) {
|
|
19
|
-
const {
|
|
20
|
-
columns = 2,
|
|
21
|
-
columnWidth = 35,
|
|
22
|
-
highlightChar = '▶',
|
|
23
|
-
indent = ' '
|
|
24
|
-
} = options;
|
|
25
|
-
|
|
26
|
-
const rows = [];
|
|
27
|
-
const itemsPerRow = columns;
|
|
28
|
-
|
|
29
|
-
for (let i = 0; i < items.length; i += itemsPerRow) {
|
|
30
|
-
const rowItems = items.slice(i, i + itemsPerRow);
|
|
31
|
-
const row = rowItems.map((item, idx) => {
|
|
32
|
-
const isObject = typeof item === 'object';
|
|
33
|
-
const name = isObject ? item.name : item;
|
|
34
|
-
const desc = isObject ? item.description : '';
|
|
35
|
-
const isCurrent = isObject ? item.current : false;
|
|
36
|
-
|
|
37
|
-
// Format item
|
|
38
|
-
let formatted = isCurrent ? `${highlightChar} ${name}` : ` ${name}`;
|
|
39
|
-
|
|
40
|
-
if (desc) {
|
|
41
|
-
formatted = chalk.cyan(formatted) + chalk.gray(` ${desc}`);
|
|
42
|
-
} else if (isCurrent) {
|
|
43
|
-
formatted = chalk.cyan(formatted);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Pad to column width (accounting for ANSI codes)
|
|
47
|
-
const plainLength = (isCurrent ? `${highlightChar} ${name}` : ` ${name}`).length + (desc ? ` ${desc}`.length : 0);
|
|
48
|
-
const padding = Math.max(0, columnWidth - plainLength);
|
|
49
|
-
|
|
50
|
-
return formatted + ' '.repeat(padding);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
rows.push(indent + row.join(' '));
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return rows.join('\n');
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Format voices list with boxen
|
|
61
|
-
* @param {Array} voices - Array of voice objects {name, lang, current}
|
|
62
|
-
* @param {Object} options - Display options
|
|
63
|
-
* @returns {string} Formatted boxen output
|
|
64
|
-
*/
|
|
65
|
-
export function formatVoicesList(voices, options = {}) {
|
|
66
|
-
const {
|
|
67
|
-
provider = 'Piper TTS',
|
|
68
|
-
title = '🎤 Available Voices',
|
|
69
|
-
columns = 2,
|
|
70
|
-
showUsage = true
|
|
71
|
-
} = options;
|
|
72
|
-
|
|
73
|
-
if (voices.length === 0) {
|
|
74
|
-
const content = chalk.yellow('No voices found') + '\n\n' +
|
|
75
|
-
chalk.gray('Download voices with:\n') +
|
|
76
|
-
chalk.cyan(' /agent-vibes:provider download <voice-name>');
|
|
77
|
-
|
|
78
|
-
return boxen(content, {
|
|
79
|
-
padding: 1,
|
|
80
|
-
margin: 1,
|
|
81
|
-
borderStyle: 'round',
|
|
82
|
-
borderColor: 'yellow',
|
|
83
|
-
title: chalk.bold(title),
|
|
84
|
-
titleAlignment: 'center'
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Format voices
|
|
89
|
-
const formattedItems = voices.map(v => ({
|
|
90
|
-
name: v.name,
|
|
91
|
-
description: v.lang || '',
|
|
92
|
-
current: v.current || false
|
|
93
|
-
}));
|
|
94
|
-
|
|
95
|
-
let content = chalk.bold(`${provider}\n\n`);
|
|
96
|
-
content += formatColumns(formattedItems, { columns });
|
|
97
|
-
|
|
98
|
-
if (showUsage) {
|
|
99
|
-
content += '\n\n' + chalk.gray('─'.repeat(60)) + '\n';
|
|
100
|
-
content += chalk.dim('Switch voice: ') + chalk.cyan('/agent-vibes:switch <voice-name>') + '\n';
|
|
101
|
-
content += chalk.dim('Preview voice: ') + chalk.cyan('/agent-vibes:preview <voice-name>');
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
return boxen(content, {
|
|
105
|
-
padding: 1,
|
|
106
|
-
margin: 1,
|
|
107
|
-
borderStyle: 'round',
|
|
108
|
-
borderColor: 'cyan',
|
|
109
|
-
title: chalk.bold(title),
|
|
110
|
-
titleAlignment: 'center'
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Format personalities list with boxen
|
|
116
|
-
* @param {Array} personalities - Array of personality objects {name, description, current}
|
|
117
|
-
* @param {Object} options - Display options
|
|
118
|
-
* @returns {string} Formatted boxen output
|
|
119
|
-
*/
|
|
120
|
-
export function formatPersonalitiesList(personalities, options = {}) {
|
|
121
|
-
const {
|
|
122
|
-
title = '🎭 Available Personalities',
|
|
123
|
-
columns = 2,
|
|
124
|
-
showUsage = true
|
|
125
|
-
} = options;
|
|
126
|
-
|
|
127
|
-
if (personalities.length === 0) {
|
|
128
|
-
const content = chalk.yellow('No personalities found') + '\n\n' +
|
|
129
|
-
chalk.gray('Add a personality with:\n') +
|
|
130
|
-
chalk.cyan(' /agent-vibes:personality add <name>');
|
|
131
|
-
|
|
132
|
-
return boxen(content, {
|
|
133
|
-
padding: 1,
|
|
134
|
-
margin: 1,
|
|
135
|
-
borderStyle: 'round',
|
|
136
|
-
borderColor: 'yellow',
|
|
137
|
-
title: chalk.bold(title),
|
|
138
|
-
titleAlignment: 'center'
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
let content = formatColumns(personalities, { columns, columnWidth: 40 });
|
|
143
|
-
|
|
144
|
-
if (showUsage) {
|
|
145
|
-
content += '\n\n' + chalk.gray('─'.repeat(60)) + '\n';
|
|
146
|
-
content += chalk.dim('Set personality: ') + chalk.cyan('/agent-vibes:personality <name>') + '\n';
|
|
147
|
-
content += chalk.dim('Add personality: ') + chalk.cyan('/agent-vibes:personality add <name>') + '\n';
|
|
148
|
-
content += chalk.dim('Edit personality: ') + chalk.cyan('/agent-vibes:personality edit <name>');
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
return boxen(content, {
|
|
152
|
-
padding: 1,
|
|
153
|
-
margin: 1,
|
|
154
|
-
borderStyle: 'round',
|
|
155
|
-
borderColor: 'magenta',
|
|
156
|
-
title: chalk.bold(title),
|
|
157
|
-
titleAlignment: 'center'
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Format generic list with boxen
|
|
163
|
-
* @param {Array} items - Array of items (strings or objects)
|
|
164
|
-
* @param {Object} options - Display options
|
|
165
|
-
* @returns {string} Formatted boxen output
|
|
166
|
-
*/
|
|
167
|
-
export function formatList(items, options = {}) {
|
|
168
|
-
const {
|
|
169
|
-
title = 'Items',
|
|
170
|
-
icon = '📋',
|
|
171
|
-
columns = 2,
|
|
172
|
-
borderColor = 'blue',
|
|
173
|
-
showCount = true
|
|
174
|
-
} = options;
|
|
175
|
-
|
|
176
|
-
const titleText = icon ? `${icon} ${title}` : title;
|
|
177
|
-
const countText = showCount ? chalk.gray(` (${items.length})`) : '';
|
|
178
|
-
|
|
179
|
-
let content = '';
|
|
180
|
-
if (showCount) {
|
|
181
|
-
content = chalk.bold(`Total: ${items.length} items\n\n`);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
content += formatColumns(items, { columns });
|
|
185
|
-
|
|
186
|
-
return boxen(content, {
|
|
187
|
-
padding: 1,
|
|
188
|
-
margin: 1,
|
|
189
|
-
borderStyle: 'round',
|
|
190
|
-
borderColor,
|
|
191
|
-
title: chalk.bold(titleText) + countText,
|
|
192
|
-
titleAlignment: 'center'
|
|
193
|
-
});
|
|
194
|
-
}
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* AgentVibes List Formatter
|
|
4
|
+
*
|
|
5
|
+
* Beautiful multi-column boxen displays for voices and personalities
|
|
6
|
+
* Inspired by BMAD-METHOD's installer UX
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import chalk from 'chalk';
|
|
10
|
+
import boxen from 'boxen';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Format items into multi-column layout
|
|
14
|
+
* @param {Array} items - Array of strings or objects with {name, description, current}
|
|
15
|
+
* @param {Object} options - Formatting options
|
|
16
|
+
* @returns {string} Formatted multi-column text
|
|
17
|
+
*/
|
|
18
|
+
export function formatColumns(items, options = {}) {
|
|
19
|
+
const {
|
|
20
|
+
columns = 2,
|
|
21
|
+
columnWidth = 35,
|
|
22
|
+
highlightChar = '▶',
|
|
23
|
+
indent = ' '
|
|
24
|
+
} = options;
|
|
25
|
+
|
|
26
|
+
const rows = [];
|
|
27
|
+
const itemsPerRow = columns;
|
|
28
|
+
|
|
29
|
+
for (let i = 0; i < items.length; i += itemsPerRow) {
|
|
30
|
+
const rowItems = items.slice(i, i + itemsPerRow);
|
|
31
|
+
const row = rowItems.map((item, idx) => {
|
|
32
|
+
const isObject = typeof item === 'object';
|
|
33
|
+
const name = isObject ? item.name : item;
|
|
34
|
+
const desc = isObject ? item.description : '';
|
|
35
|
+
const isCurrent = isObject ? item.current : false;
|
|
36
|
+
|
|
37
|
+
// Format item
|
|
38
|
+
let formatted = isCurrent ? `${highlightChar} ${name}` : ` ${name}`;
|
|
39
|
+
|
|
40
|
+
if (desc) {
|
|
41
|
+
formatted = chalk.cyan(formatted) + chalk.gray(` ${desc}`);
|
|
42
|
+
} else if (isCurrent) {
|
|
43
|
+
formatted = chalk.cyan(formatted);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Pad to column width (accounting for ANSI codes)
|
|
47
|
+
const plainLength = (isCurrent ? `${highlightChar} ${name}` : ` ${name}`).length + (desc ? ` ${desc}`.length : 0);
|
|
48
|
+
const padding = Math.max(0, columnWidth - plainLength);
|
|
49
|
+
|
|
50
|
+
return formatted + ' '.repeat(padding);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
rows.push(indent + row.join(' '));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return rows.join('\n');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Format voices list with boxen
|
|
61
|
+
* @param {Array} voices - Array of voice objects {name, lang, current}
|
|
62
|
+
* @param {Object} options - Display options
|
|
63
|
+
* @returns {string} Formatted boxen output
|
|
64
|
+
*/
|
|
65
|
+
export function formatVoicesList(voices, options = {}) {
|
|
66
|
+
const {
|
|
67
|
+
provider = 'Piper TTS',
|
|
68
|
+
title = '🎤 Available Voices',
|
|
69
|
+
columns = 2,
|
|
70
|
+
showUsage = true
|
|
71
|
+
} = options;
|
|
72
|
+
|
|
73
|
+
if (voices.length === 0) {
|
|
74
|
+
const content = chalk.yellow('No voices found') + '\n\n' +
|
|
75
|
+
chalk.gray('Download voices with:\n') +
|
|
76
|
+
chalk.cyan(' /agent-vibes:provider download <voice-name>');
|
|
77
|
+
|
|
78
|
+
return boxen(content, {
|
|
79
|
+
padding: 1,
|
|
80
|
+
margin: 1,
|
|
81
|
+
borderStyle: 'round',
|
|
82
|
+
borderColor: 'yellow',
|
|
83
|
+
title: chalk.bold(title),
|
|
84
|
+
titleAlignment: 'center'
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Format voices
|
|
89
|
+
const formattedItems = voices.map(v => ({
|
|
90
|
+
name: v.name,
|
|
91
|
+
description: v.lang || '',
|
|
92
|
+
current: v.current || false
|
|
93
|
+
}));
|
|
94
|
+
|
|
95
|
+
let content = chalk.bold(`${provider}\n\n`);
|
|
96
|
+
content += formatColumns(formattedItems, { columns });
|
|
97
|
+
|
|
98
|
+
if (showUsage) {
|
|
99
|
+
content += '\n\n' + chalk.gray('─'.repeat(60)) + '\n';
|
|
100
|
+
content += chalk.dim('Switch voice: ') + chalk.cyan('/agent-vibes:switch <voice-name>') + '\n';
|
|
101
|
+
content += chalk.dim('Preview voice: ') + chalk.cyan('/agent-vibes:preview <voice-name>');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return boxen(content, {
|
|
105
|
+
padding: 1,
|
|
106
|
+
margin: 1,
|
|
107
|
+
borderStyle: 'round',
|
|
108
|
+
borderColor: 'cyan',
|
|
109
|
+
title: chalk.bold(title),
|
|
110
|
+
titleAlignment: 'center'
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Format personalities list with boxen
|
|
116
|
+
* @param {Array} personalities - Array of personality objects {name, description, current}
|
|
117
|
+
* @param {Object} options - Display options
|
|
118
|
+
* @returns {string} Formatted boxen output
|
|
119
|
+
*/
|
|
120
|
+
export function formatPersonalitiesList(personalities, options = {}) {
|
|
121
|
+
const {
|
|
122
|
+
title = '🎭 Available Personalities',
|
|
123
|
+
columns = 2,
|
|
124
|
+
showUsage = true
|
|
125
|
+
} = options;
|
|
126
|
+
|
|
127
|
+
if (personalities.length === 0) {
|
|
128
|
+
const content = chalk.yellow('No personalities found') + '\n\n' +
|
|
129
|
+
chalk.gray('Add a personality with:\n') +
|
|
130
|
+
chalk.cyan(' /agent-vibes:personality add <name>');
|
|
131
|
+
|
|
132
|
+
return boxen(content, {
|
|
133
|
+
padding: 1,
|
|
134
|
+
margin: 1,
|
|
135
|
+
borderStyle: 'round',
|
|
136
|
+
borderColor: 'yellow',
|
|
137
|
+
title: chalk.bold(title),
|
|
138
|
+
titleAlignment: 'center'
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
let content = formatColumns(personalities, { columns, columnWidth: 40 });
|
|
143
|
+
|
|
144
|
+
if (showUsage) {
|
|
145
|
+
content += '\n\n' + chalk.gray('─'.repeat(60)) + '\n';
|
|
146
|
+
content += chalk.dim('Set personality: ') + chalk.cyan('/agent-vibes:personality <name>') + '\n';
|
|
147
|
+
content += chalk.dim('Add personality: ') + chalk.cyan('/agent-vibes:personality add <name>') + '\n';
|
|
148
|
+
content += chalk.dim('Edit personality: ') + chalk.cyan('/agent-vibes:personality edit <name>');
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return boxen(content, {
|
|
152
|
+
padding: 1,
|
|
153
|
+
margin: 1,
|
|
154
|
+
borderStyle: 'round',
|
|
155
|
+
borderColor: 'magenta',
|
|
156
|
+
title: chalk.bold(title),
|
|
157
|
+
titleAlignment: 'center'
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Format generic list with boxen
|
|
163
|
+
* @param {Array} items - Array of items (strings or objects)
|
|
164
|
+
* @param {Object} options - Display options
|
|
165
|
+
* @returns {string} Formatted boxen output
|
|
166
|
+
*/
|
|
167
|
+
export function formatList(items, options = {}) {
|
|
168
|
+
const {
|
|
169
|
+
title = 'Items',
|
|
170
|
+
icon = '📋',
|
|
171
|
+
columns = 2,
|
|
172
|
+
borderColor = 'blue',
|
|
173
|
+
showCount = true
|
|
174
|
+
} = options;
|
|
175
|
+
|
|
176
|
+
const titleText = icon ? `${icon} ${title}` : title;
|
|
177
|
+
const countText = showCount ? chalk.gray(` (${items.length})`) : '';
|
|
178
|
+
|
|
179
|
+
let content = '';
|
|
180
|
+
if (showCount) {
|
|
181
|
+
content = chalk.bold(`Total: ${items.length} items\n\n`);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
content += formatColumns(items, { columns });
|
|
185
|
+
|
|
186
|
+
return boxen(content, {
|
|
187
|
+
padding: 1,
|
|
188
|
+
margin: 1,
|
|
189
|
+
borderStyle: 'round',
|
|
190
|
+
borderColor,
|
|
191
|
+
title: chalk.bold(titleText) + countText,
|
|
192
|
+
titleAlignment: 'center'
|
|
193
|
+
});
|
|
194
|
+
}
|