fix(windows): resolve symlinked config paths for plugin detection (fixes #2271)
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
import { afterEach, beforeEach, describe, expect, it } from "bun:test"
|
||||
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs"
|
||||
import { tmpdir } from "node:os"
|
||||
import { join } from "node:path"
|
||||
|
||||
import { discoverInstalledPlugins } from "./discovery"
|
||||
|
||||
const originalClaudePluginsHome = process.env.CLAUDE_PLUGINS_HOME
|
||||
const temporaryDirectories: string[] = []
|
||||
|
||||
function createTemporaryDirectory(prefix: string): string {
|
||||
const directory = mkdtempSync(join(tmpdir(), prefix))
|
||||
temporaryDirectories.push(directory)
|
||||
return directory
|
||||
}
|
||||
|
||||
describe("discoverInstalledPlugins", () => {
|
||||
beforeEach(() => {
|
||||
const pluginsHome = createTemporaryDirectory("omo-claude-plugins-")
|
||||
process.env.CLAUDE_PLUGINS_HOME = pluginsHome
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
if (originalClaudePluginsHome === undefined) {
|
||||
delete process.env.CLAUDE_PLUGINS_HOME
|
||||
} else {
|
||||
process.env.CLAUDE_PLUGINS_HOME = originalClaudePluginsHome
|
||||
}
|
||||
|
||||
for (const directory of temporaryDirectories.splice(0)) {
|
||||
rmSync(directory, { recursive: true, force: true })
|
||||
}
|
||||
})
|
||||
|
||||
it("derives package name from file URL plugin keys", () => {
|
||||
//#given
|
||||
const pluginsHome = process.env.CLAUDE_PLUGINS_HOME as string
|
||||
const installPath = join(createTemporaryDirectory("omo-plugin-install-"), "oh-my-opencode")
|
||||
mkdirSync(installPath, { recursive: true })
|
||||
|
||||
const databasePath = join(pluginsHome, "installed_plugins.json")
|
||||
writeFileSync(
|
||||
databasePath,
|
||||
JSON.stringify({
|
||||
version: 2,
|
||||
plugins: {
|
||||
"file:///D:/configs/user-configs/.config/opencode/node_modules/oh-my-opencode@latest": [
|
||||
{
|
||||
scope: "user",
|
||||
installPath,
|
||||
version: "3.10.0",
|
||||
installedAt: "2026-03-20T00:00:00Z",
|
||||
lastUpdated: "2026-03-20T00:00:00Z",
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
"utf-8",
|
||||
)
|
||||
|
||||
//#when
|
||||
const discovered = discoverInstalledPlugins()
|
||||
|
||||
//#then
|
||||
expect(discovered.errors).toHaveLength(0)
|
||||
expect(discovered.plugins).toHaveLength(1)
|
||||
expect(discovered.plugins[0]?.name).toBe("oh-my-opencode")
|
||||
})
|
||||
})
|
||||
@@ -1,6 +1,7 @@
|
||||
import { existsSync, readFileSync } from "fs"
|
||||
import { homedir } from "os"
|
||||
import { join } from "path"
|
||||
import { basename, join } from "path"
|
||||
import { fileURLToPath } from "url"
|
||||
import { log } from "../../shared/logger"
|
||||
import type {
|
||||
InstalledPluginsDatabase,
|
||||
@@ -79,8 +80,23 @@ function loadPluginManifest(installPath: string): PluginManifest | null {
|
||||
}
|
||||
|
||||
function derivePluginNameFromKey(pluginKey: string): string {
|
||||
const atIndex = pluginKey.indexOf("@")
|
||||
return atIndex > 0 ? pluginKey.substring(0, atIndex) : pluginKey
|
||||
const keyWithoutSource = pluginKey.startsWith("npm:") ? pluginKey.slice(4) : pluginKey
|
||||
const versionSeparator = keyWithoutSource.lastIndexOf("@")
|
||||
const keyWithoutVersion = versionSeparator > 0 ? keyWithoutSource.slice(0, versionSeparator) : keyWithoutSource
|
||||
|
||||
if (keyWithoutVersion.startsWith("file://")) {
|
||||
try {
|
||||
return basename(fileURLToPath(keyWithoutVersion))
|
||||
} catch {
|
||||
return basename(keyWithoutVersion)
|
||||
}
|
||||
}
|
||||
|
||||
if (keyWithoutVersion.includes("/") || keyWithoutVersion.includes("\\")) {
|
||||
return basename(keyWithoutVersion)
|
||||
}
|
||||
|
||||
return keyWithoutVersion
|
||||
}
|
||||
|
||||
function isPluginEnabled(
|
||||
|
||||
Reference in New Issue
Block a user