opencode-plugin-boops 2.2.0 → 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.
Files changed (2) hide show
  1. package/cli/browse +46 -12
  2. package/package.json +1 -1
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
- if (config.sounds) {
112
- for (const [event, sound] of Object.entries(config.sounds)) {
113
- content += `"${event}" = "${sound}"\n`;
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
  }
@@ -1846,20 +1883,17 @@ async function browse() {
1846
1883
  }
1847
1884
  return;
1848
1885
  } else if (key === '\u0013') {
1849
- // Ctrl+S - save assignment
1886
+ // Ctrl+S - save assignment (stay in picker mode to assign more)
1850
1887
  const config = loadCurrentConfig();
1851
1888
  const event = availableEvents[state.pickerSelectedEvent];
1852
1889
 
1853
1890
  if (!config.sounds) config.sounds = {};
1854
- config.sounds[event] = state.pickerSound.id;
1891
+ config.sounds[event] = state.pickerSound.name; // Save friendly name, not ID
1855
1892
 
1856
1893
  // Save to config file
1857
- const saved = saveConfig(config);
1894
+ saveConfig(config);
1858
1895
 
1859
- if (saved) {
1860
- state.pickerMode = false;
1861
- state.pickerSound = null;
1862
- }
1896
+ // Stay in picker mode, just show it was saved
1863
1897
  render();
1864
1898
  return;
1865
1899
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-plugin-boops",
3
- "version": "2.2.0",
3
+ "version": "2.2.1",
4
4
  "description": "Sound notifications for OpenCode - plays pleasant sounds when tasks complete or input is needed",
5
5
  "main": "index.ts",
6
6
  "type": "module",