Browse Source

fix: pin installed version in plugin config entry

When 'bunx oh-my-opencode-slim install' writes the plugin entry to
OpenCode config, it now pins the exact version (e.g.
oh-my-opencode-slim@1.2.3) instead of a bare package name.

This lets OpenCode resolve the plugin from its local cache without
hitting npm on every startup. Users with broken npm registries
(expired certs, blocked mirrors) no longer get stuck on a white
screen during plugin resolution.

Fixes #781
Michael Henke 3 weeks ago
parent
commit
9869346868
2 changed files with 34 additions and 3 deletions
  1. 25 2
      src/cli/config-io.test.ts
  2. 9 1
      src/cli/config-io.ts

+ 25 - 2
src/cli/config-io.test.ts

@@ -46,11 +46,14 @@ describe('config-io', () => {
     mock.restore();
   });
 
-  function writePackageJson(dir: string): void {
+  function writePackageJson(dir: string, version?: string): void {
     mkdirSync(dir, { recursive: true });
     writeFileSync(
       join(dir, 'package.json'),
-      JSON.stringify({ name: 'oh-my-opencode-slim' }),
+      JSON.stringify({
+        name: 'oh-my-opencode-slim',
+        ...(version ? { version } : {}),
+      }),
     );
   }
 
@@ -181,6 +184,26 @@ describe('config-io', () => {
     expect(saved.plugin).toEqual(['oh-my-opencode-slim']);
   });
 
+  test('addPluginToOpenCodeConfig pins version for bunx temp paths', async () => {
+    const configPath = join(tmpDir, 'opencode', 'opencode.json');
+    const packageRoot = join(
+      tmpDir,
+      'bunx-1000-oh-my-opencode-slim@latest',
+      'node_modules',
+      'oh-my-opencode-slim',
+    );
+    paths.ensureConfigDir();
+    writeFileSync(configPath, JSON.stringify({ plugin: [] }));
+    writePackageJson(packageRoot, '1.2.3');
+    process.argv[1] = join(packageRoot, 'dist', 'cli', 'index.js');
+
+    const result = await addPluginToOpenCodeConfig();
+
+    expect(result.success).toBe(true);
+    const saved = JSON.parse(readFileSync(configPath, 'utf-8'));
+    expect(saved.plugin).toEqual(['oh-my-opencode-slim@1.2.3']);
+  });
+
   test('addPluginToOpenCodeConfig stores local repo path for local dev paths', async () => {
     const configPath = join(tmpDir, 'opencode', 'opencode.json');
     const packageRoot = join(tmpDir, 'repo');

+ 9 - 1
src/cli/config-io.ts

@@ -146,10 +146,18 @@ function getPluginEntry(): string {
   try {
     const packageRoot = findPackageRoot(cliEntryPath);
 
-    if (!packageRoot || isPackageManagerInstall(packageRoot)) {
+    if (!packageRoot) {
       return PACKAGE_NAME;
     }
 
+    if (isPackageManagerInstall(packageRoot)) {
+      const version = getVersionFromPackageRoot(packageRoot);
+      // ponytail: pin installed version so OpenCode can resolve from
+      // its cache without hitting npm on every startup. Falls back to
+      // bare package name if version detection fails.
+      return version ? `${PACKAGE_NAME}@${version}` : PACKAGE_NAME;
+    }
+
     return packageRoot;
   } catch {
     return PACKAGE_NAME;