Browse Source

fix: deep merge agent configs to preserve user-defined tools/permission (#173)

* fix: deep merge agent configs to preserve user-defined tools/permission

Replace shallow Object.assign with per-agent deep merge in config() hook.
Previously, plugin agent configs fully overwrote user configs from opencode.json,
silently discarding fields like `tools` and `permission`.

Now plugin defaults are applied first, then user overrides win for each field,
preserving user-supplied configuration while filling in plugin defaults.

Fixes #165

* fix: correct comment to say 'shallow merge' not 'deep merge'

---------

Co-authored-by: alvinreal <alvinreal@users.noreply.github.com>
alvinreal 1 month ago
parent
commit
acc366318b
2 changed files with 21 additions and 5 deletions
  1. 3 3
      oh-my-opencode-slim.schema.json
  2. 18 2
      src/index.ts

+ 3 - 3
oh-my-opencode-slim.schema.json

@@ -1,7 +1,5 @@
 {
   "$schema": "https://json-schema.org/draft/2020-12/schema",
-  "title": "oh-my-opencode-slim",
-  "description": "Configuration schema for oh-my-opencode-slim plugin for OpenCode",
   "type": "object",
   "properties": {
     "preset": {
@@ -436,5 +434,7 @@
         }
       }
     }
-  }
+  },
+  "title": "oh-my-opencode-slim",
+  "description": "Configuration schema for oh-my-opencode-slim plugin for OpenCode"
 }

+ 18 - 2
src/index.ts

@@ -113,11 +113,27 @@ const OhMyOpenCodeLite: Plugin = async (ctx) => {
       (opencodeConfig as { default_agent?: string }).default_agent =
         'orchestrator';
 
-      // Merge Agent configs
+      // Merge Agent configs — per-agent shallow merge to preserve
+      // user-supplied fields (e.g. tools, permission) from opencode.json
       if (!opencodeConfig.agent) {
         opencodeConfig.agent = { ...agents };
       } else {
-        Object.assign(opencodeConfig.agent, agents);
+        for (const [name, pluginAgent] of Object.entries(agents)) {
+          const existing = (opencodeConfig.agent as Record<string, unknown>)[
+            name
+          ] as Record<string, unknown> | undefined;
+          if (existing) {
+            // Shallow merge: plugin defaults first, user overrides win
+            (opencodeConfig.agent as Record<string, unknown>)[name] = {
+              ...pluginAgent,
+              ...existing,
+            };
+          } else {
+            (opencodeConfig.agent as Record<string, unknown>)[name] = {
+              ...pluginAgent,
+            };
+          }
+        }
       }
       const configAgent = opencodeConfig.agent as Record<string, unknown>;