diff --git a/src/hooks/legacy-plugin-toast/auto-migrate-runner.ts b/src/hooks/legacy-plugin-toast/auto-migrate-runner.ts new file mode 100644 index 000000000..c77fea2b9 --- /dev/null +++ b/src/hooks/legacy-plugin-toast/auto-migrate-runner.ts @@ -0,0 +1,2 @@ +export { autoMigrateLegacyPluginEntry } from "./auto-migrate" +export type { MigrationResult } from "./auto-migrate" diff --git a/src/hooks/legacy-plugin-toast/auto-migrate.ts b/src/hooks/legacy-plugin-toast/auto-migrate.ts index 34bc4bbc0..a33cf8ac9 100644 --- a/src/hooks/legacy-plugin-toast/auto-migrate.ts +++ b/src/hooks/legacy-plugin-toast/auto-migrate.ts @@ -1,9 +1,10 @@ -import { existsSync, readFileSync, writeFileSync } from "node:fs" +import { existsSync, readFileSync } from "node:fs" import { join } from "node:path" import { parseJsoncSafe } from "../../shared/jsonc-parser" import { getOpenCodeConfigPaths } from "../../shared/opencode-config-dir" import { LEGACY_PLUGIN_NAME, PLUGIN_NAME } from "../../shared/plugin-identity" +import { migrateLegacyPluginEntry } from "./plugin-entry-migrator" export interface MigrationResult { migrated: boolean @@ -63,27 +64,15 @@ export function autoMigrateLegacyPluginEntry(overrideConfigDir?: string): Migrat const hasCanonical = plugins.some(isCanonicalEntry) const from = legacyEntries[0] const to = toLegacyCanonical(from) + const migrated = migrateLegacyPluginEntry(configPath) + if (!migrated) return { migrated: false, from: null, to: null, configPath } - const normalized = hasCanonical - ? plugins.filter((p) => !isLegacyEntry(p)) - : plugins.map((p) => (isLegacyEntry(p) ? toLegacyCanonical(p) : p)) - - const isJsonc = configPath.endsWith(".jsonc") - if (isJsonc) { - const pluginArrayRegex = /((?:"plugin"|plugin)\s*:\s*)\[([\s\S]*?)\]/ - const match = content.match(pluginArrayRegex) - if (match) { - const formattedPlugins = normalized.map((p) => `"${p}"`).join(",\n ") - const newContent = content.replace(pluginArrayRegex, `$1[\n ${formattedPlugins}\n ]`) - writeFileSync(configPath, newContent) - return { migrated: true, from, to, configPath } - } + return { + migrated: true, + from, + to: hasCanonical ? PLUGIN_NAME : to, + configPath, } - - const parsed = JSON.parse(content) as Record - parsed.plugin = normalized - writeFileSync(configPath, JSON.stringify(parsed, null, 2) + "\n") - return { migrated: true, from, to, configPath } } catch { return { migrated: false, from: null, to: null, configPath } } diff --git a/src/hooks/legacy-plugin-toast/hook.test.ts b/src/hooks/legacy-plugin-toast/hook.test.ts index 490908429..c355587fc 100644 --- a/src/hooks/legacy-plugin-toast/hook.test.ts +++ b/src/hooks/legacy-plugin-toast/hook.test.ts @@ -1,5 +1,5 @@ import { afterAll, beforeEach, describe, expect, it, mock } from "bun:test" -import type { MigrationResult } from "./auto-migrate" +import type { MigrationResult } from "./auto-migrate-runner" const mockCheckForLegacyPluginEntry = mock(() => ({ hasLegacyEntry: false, @@ -26,7 +26,7 @@ mock.module("../../shared/logger", () => ({ log: mockLog, })) -mock.module("./auto-migrate", () => ({ +mock.module("./auto-migrate-runner", () => ({ autoMigrateLegacyPluginEntry: mockAutoMigrate, })) diff --git a/src/hooks/legacy-plugin-toast/hook.ts b/src/hooks/legacy-plugin-toast/hook.ts index 4d6f55918..69f971f25 100644 --- a/src/hooks/legacy-plugin-toast/hook.ts +++ b/src/hooks/legacy-plugin-toast/hook.ts @@ -3,7 +3,7 @@ import type { PluginInput } from "@opencode-ai/plugin" import { checkForLegacyPluginEntry } from "../../shared/legacy-plugin-warning" import { log } from "../../shared/logger" import { LEGACY_PLUGIN_NAME, PLUGIN_NAME } from "../../shared/plugin-identity" -import { autoMigrateLegacyPluginEntry } from "./auto-migrate" +import { autoMigrateLegacyPluginEntry } from "./auto-migrate-runner" export function createLegacyPluginToastHook(ctx: PluginInput) { let fired = false diff --git a/src/hooks/legacy-plugin-toast/plugin-entry-migrator.ts b/src/hooks/legacy-plugin-toast/plugin-entry-migrator.ts new file mode 100644 index 000000000..27aaaedc1 --- /dev/null +++ b/src/hooks/legacy-plugin-toast/plugin-entry-migrator.ts @@ -0,0 +1 @@ +export { migrateLegacyPluginEntry } from "../../shared/migrate-legacy-plugin-entry" diff --git a/src/shared/log-legacy-plugin-startup-warning.test.ts b/src/shared/log-legacy-plugin-startup-warning.test.ts index 4acd38385..0b288a461 100644 --- a/src/shared/log-legacy-plugin-startup-warning.test.ts +++ b/src/shared/log-legacy-plugin-startup-warning.test.ts @@ -26,7 +26,7 @@ mock.module("./logger", () => ({ log: mockLog, })) -mock.module("./migrate-legacy-plugin-entry", () => ({ +mock.module("./plugin-entry-migrator", () => ({ migrateLegacyPluginEntry: mockMigrateLegacyPluginEntry, })) diff --git a/src/shared/log-legacy-plugin-startup-warning.ts b/src/shared/log-legacy-plugin-startup-warning.ts index dc6505a5f..1ff3c7c19 100644 --- a/src/shared/log-legacy-plugin-startup-warning.ts +++ b/src/shared/log-legacy-plugin-startup-warning.ts @@ -1,6 +1,6 @@ import { checkForLegacyPluginEntry } from "./legacy-plugin-warning" import { log } from "./logger" -import { migrateLegacyPluginEntry } from "./migrate-legacy-plugin-entry" +import { migrateLegacyPluginEntry } from "./plugin-entry-migrator" import { LEGACY_PLUGIN_NAME, PLUGIN_NAME } from "./plugin-identity" function toCanonicalEntry(entry: string): string { diff --git a/src/shared/plugin-entry-migrator.ts b/src/shared/plugin-entry-migrator.ts new file mode 100644 index 000000000..50cc7c1a1 --- /dev/null +++ b/src/shared/plugin-entry-migrator.ts @@ -0,0 +1 @@ +export { migrateLegacyPluginEntry } from "./migrate-legacy-plugin-entry"