opencode-plugin-boops 2.1.3 → 2.2.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.
- package/README.md +4 -3
- package/cli/browse +60 -15
- package/cli/main +3 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -49,13 +49,14 @@ Then restart OpenCode. The plugin will be automatically downloaded and installed
|
|
|
49
49
|
# Install plugin (adds to OpenCode config)
|
|
50
50
|
npx opencode-plugin-boops install
|
|
51
51
|
|
|
52
|
+
# Configure sounds (TUI browser)
|
|
53
|
+
npx opencode-plugin-boops config # Same as browse
|
|
54
|
+
npx opencode-plugin-boops browse # Browse 448 sounds with semantic tags
|
|
55
|
+
|
|
52
56
|
# Uninstall plugin (removes from config)
|
|
53
57
|
npx opencode-plugin-boops uninstall # Interactive - asks about data cleanup
|
|
54
58
|
npx opencode-plugin-boops uninstall --full # Remove plugin + data
|
|
55
59
|
|
|
56
|
-
# Browse 448 sounds with semantic tags
|
|
57
|
-
npx opencode-plugin-boops browse
|
|
58
|
-
|
|
59
60
|
# Show help
|
|
60
61
|
npx opencode-plugin-boops
|
|
61
62
|
```
|
package/cli/browse
CHANGED
|
@@ -96,7 +96,7 @@ function loadCurrentConfig() {
|
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
// Save config to boops.toml
|
|
99
|
+
// Save config to boops.toml (preserves existing entries and comments)
|
|
100
100
|
function saveConfig(config) {
|
|
101
101
|
if (!PLUGIN_INSTALLED) {
|
|
102
102
|
console.error("\n⚠️ Cannot save: Plugin not installed");
|
|
@@ -106,14 +106,51 @@ function saveConfig(config) {
|
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
const configPath = join(homedir(), ".config", "opencode", "plugins", "boops", "boops.toml");
|
|
109
|
-
let content = "# OpenCode Boops Plugin Configuration\n\n[sounds]\n";
|
|
110
109
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
110
|
+
// Read existing config to preserve comments and other sections
|
|
111
|
+
let existingContent = "";
|
|
112
|
+
if (existsSync(configPath)) {
|
|
113
|
+
existingContent = readFileSync(configPath, "utf-8");
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Parse existing [sounds] section to merge with new values
|
|
117
|
+
const existingSounds = {};
|
|
118
|
+
if (existingContent) {
|
|
119
|
+
const lines = existingContent.split("\n");
|
|
120
|
+
let inSoundsSection = false;
|
|
121
|
+
|
|
122
|
+
for (const line of lines) {
|
|
123
|
+
const trimmed = line.trim();
|
|
124
|
+
|
|
125
|
+
if (trimmed === "[sounds]") {
|
|
126
|
+
inSoundsSection = true;
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (trimmed.startsWith("[") && trimmed !== "[sounds]") {
|
|
131
|
+
inSoundsSection = false;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (inSoundsSection && !trimmed.startsWith("#") && trimmed) {
|
|
135
|
+
const match = trimmed.match(/^"?([^"=]+)"?\s*=\s*"?([^"#]+)"?/);
|
|
136
|
+
if (match) {
|
|
137
|
+
const [, key, value] = match;
|
|
138
|
+
existingSounds[key.trim()] = value.trim().replace(/"/g, "");
|
|
139
|
+
}
|
|
140
|
+
}
|
|
114
141
|
}
|
|
115
142
|
}
|
|
116
143
|
|
|
144
|
+
// Merge new sounds with existing
|
|
145
|
+
const mergedSounds = { ...existingSounds, ...(config.sounds || {}) };
|
|
146
|
+
|
|
147
|
+
// Write back, preserving the header
|
|
148
|
+
let content = "# OpenCode Boops Plugin Configuration\n# Sounds can be local file paths OR URLs (automatically downloaded and cached)\n\n[sounds]\n";
|
|
149
|
+
|
|
150
|
+
for (const [event, sound] of Object.entries(mergedSounds).sort()) {
|
|
151
|
+
content += `"${event}" = "${sound}"\n`;
|
|
152
|
+
}
|
|
153
|
+
|
|
117
154
|
writeFileSync(configPath, content);
|
|
118
155
|
return true;
|
|
119
156
|
}
|
|
@@ -1116,9 +1153,20 @@ async function browse() {
|
|
|
1116
1153
|
const currentSound = config.sounds ? config.sounds[event] : null;
|
|
1117
1154
|
|
|
1118
1155
|
const bg = isSelected ? '\x1b[48;5;235m' : '';
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1156
|
+
|
|
1157
|
+
// Show current sound if selected event has one
|
|
1158
|
+
let eventText;
|
|
1159
|
+
if (isSelected && currentSound) {
|
|
1160
|
+
const soundName = currentSound.length > 15 ? currentSound.slice(0, 12) + '...' : currentSound;
|
|
1161
|
+
const label = event.length > pickerWidth - soundName.length - 10
|
|
1162
|
+
? event.slice(0, pickerWidth - soundName.length - 13) + '...'
|
|
1163
|
+
: event;
|
|
1164
|
+
eventText = `${label} \x1b[38;5;240m→ \x1b[38;5;76m${soundName}\x1b[0m${bg}`.padEnd(pickerWidth - 6 + 20); // +20 for ANSI codes
|
|
1165
|
+
} else {
|
|
1166
|
+
eventText = event.length > pickerWidth - 6
|
|
1167
|
+
? event.slice(0, pickerWidth - 9) + '...'
|
|
1168
|
+
: event.padEnd(pickerWidth - 6);
|
|
1169
|
+
}
|
|
1122
1170
|
|
|
1123
1171
|
const indicator = currentSound ? '•' : ' ';
|
|
1124
1172
|
const indicatorColor = currentSound ? '\x1b[38;5;76m' : '';
|
|
@@ -1835,20 +1883,17 @@ async function browse() {
|
|
|
1835
1883
|
}
|
|
1836
1884
|
return;
|
|
1837
1885
|
} else if (key === '\u0013') {
|
|
1838
|
-
// Ctrl+S - save assignment
|
|
1886
|
+
// Ctrl+S - save assignment (stay in picker mode to assign more)
|
|
1839
1887
|
const config = loadCurrentConfig();
|
|
1840
1888
|
const event = availableEvents[state.pickerSelectedEvent];
|
|
1841
1889
|
|
|
1842
1890
|
if (!config.sounds) config.sounds = {};
|
|
1843
|
-
config.sounds[event] = state.pickerSound.
|
|
1891
|
+
config.sounds[event] = state.pickerSound.name; // Save friendly name, not ID
|
|
1844
1892
|
|
|
1845
1893
|
// Save to config file
|
|
1846
|
-
|
|
1894
|
+
saveConfig(config);
|
|
1847
1895
|
|
|
1848
|
-
|
|
1849
|
-
state.pickerMode = false;
|
|
1850
|
-
state.pickerSound = null;
|
|
1851
|
-
}
|
|
1896
|
+
// Stay in picker mode, just show it was saved
|
|
1852
1897
|
render();
|
|
1853
1898
|
return;
|
|
1854
1899
|
}
|
package/cli/main
CHANGED
|
@@ -17,6 +17,7 @@ const commands = {
|
|
|
17
17
|
install: join(__dirname, "install"),
|
|
18
18
|
uninstall: join(__dirname, "uninstall"),
|
|
19
19
|
browse: join(__dirname, "browse"),
|
|
20
|
+
config: join(__dirname, "browse"), // Alias for browse
|
|
20
21
|
};
|
|
21
22
|
|
|
22
23
|
// Show help if no command or invalid command
|
|
@@ -25,7 +26,8 @@ if (!command || !commands[command]) {
|
|
|
25
26
|
console.log("Usage:");
|
|
26
27
|
console.log(" npx opencode-plugin-boops install - Add plugin to OpenCode config");
|
|
27
28
|
console.log(" npx opencode-plugin-boops uninstall - Remove plugin from config");
|
|
28
|
-
console.log(" npx opencode-plugin-boops
|
|
29
|
+
console.log(" npx opencode-plugin-boops config - Configure sounds (TUI)");
|
|
30
|
+
console.log(" npx opencode-plugin-boops browse - Browse and test sounds (same as config)");
|
|
29
31
|
console.log("");
|
|
30
32
|
console.log("448 sounds with semantic tags (human, speech, ding, alarm, etc.)");
|
|
31
33
|
process.exit(command ? 1 : 0);
|