Files
oh-my-openagent/src/cli/doctor/checks/system-plugin.ts
YeonGyu-Kim 2ba148be12 refactor(doctor): redesign with 3-tier output and consolidated checks
Consolidate 16 separate checks into 5 (system, config, providers, tools, models).
Add 3-tier formatting: default (problems-only), --status (dashboard), --verbose (deep diagnostics).
Read actual loaded plugin version from opencode cache directory.
Check environment variables for provider authentication.
2026-02-13 17:29:38 +09:00

96 lines
2.4 KiB
TypeScript

import { existsSync, readFileSync } from "node:fs"
import { PACKAGE_NAME } from "../constants"
import { getOpenCodeConfigPaths, parseJsonc } from "../../../shared"
export interface PluginInfo {
registered: boolean
configPath: string | null
entry: string | null
isPinned: boolean
pinnedVersion: string | null
isLocalDev: boolean
}
interface OpenCodeConfigShape {
plugin?: string[]
}
function detectConfigPath(): string | null {
const paths = getOpenCodeConfigPaths({ binary: "opencode", version: null })
if (existsSync(paths.configJsonc)) return paths.configJsonc
if (existsSync(paths.configJson)) return paths.configJson
return null
}
function parsePluginVersion(entry: string): string | null {
if (!entry.startsWith(`${PACKAGE_NAME}@`)) return null
const value = entry.slice(PACKAGE_NAME.length + 1)
if (!value || value === "latest") return null
return value
}
function findPluginEntry(entries: string[]): { entry: string; isLocalDev: boolean } | null {
for (const entry of entries) {
if (entry === PACKAGE_NAME || entry.startsWith(`${PACKAGE_NAME}@`)) {
return { entry, isLocalDev: false }
}
if (entry.startsWith("file://") && entry.includes(PACKAGE_NAME)) {
return { entry, isLocalDev: true }
}
}
return null
}
export function getPluginInfo(): PluginInfo {
const configPath = detectConfigPath()
if (!configPath) {
return {
registered: false,
configPath: null,
entry: null,
isPinned: false,
pinnedVersion: null,
isLocalDev: false,
}
}
try {
const content = readFileSync(configPath, "utf-8")
const parsedConfig = parseJsonc<OpenCodeConfigShape>(content)
const pluginEntry = findPluginEntry(parsedConfig.plugin ?? [])
if (!pluginEntry) {
return {
registered: false,
configPath,
entry: null,
isPinned: false,
pinnedVersion: null,
isLocalDev: false,
}
}
const pinnedVersion = parsePluginVersion(pluginEntry.entry)
return {
registered: true,
configPath,
entry: pluginEntry.entry,
isPinned: pinnedVersion !== null,
pinnedVersion,
isLocalDev: pluginEntry.isLocalDev,
}
} catch {
return {
registered: false,
configPath,
entry: null,
isPinned: false,
pinnedVersion: null,
isLocalDev: false,
}
}
}
export { detectConfigPath, findPluginEntry }