fix: break circular dependency in config error utilities to prevent plugin loader crash

- Created src/shared/config-errors.ts to isolate config error state management
- Removed function re-exports (getConfigLoadErrors, clearConfigLoadErrors) from main index.ts
- Only ConfigLoadError type is re-exported from main module to avoid OpenCode calling it as a plugin
- Updated auto-update-checker hook to import from shared/config-errors instead of main index
- Fixes "TypeError: undefined is not an object" crash when OpenCode iterated through ALL exports and called clearConfigLoadErrors(input) which returned undefined

🤖 GENERATED WITH ASSISTANCE OF [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
This commit is contained in:
YeonGyu-Kim
2025-12-19 02:19:54 +09:00
parent 63fea77572
commit dad534e7c0
4 changed files with 28 additions and 19 deletions

View File

@@ -4,7 +4,7 @@ import { invalidatePackage } from "./cache"
import { PACKAGE_NAME } from "./constants"
import { log } from "../../shared/logger"
import { getUserConfigPath } from "../../shared/config-path"
import { getConfigLoadErrors, clearConfigLoadErrors } from "../../index"
import { getConfigLoadErrors, clearConfigLoadErrors } from "../../shared/config-errors"
import type { AutoUpdateCheckerOptions } from "./types"
export function createAutoUpdateCheckerHook(ctx: PluginInput, options: AutoUpdateCheckerOptions = {}) {

View File

@@ -46,7 +46,7 @@ import { builtinTools, createCallOmoAgent, createBackgroundTools, createLookAt,
import { BackgroundManager } from "./features/background-agent";
import { createBuiltinMcps } from "./mcp";
import { OhMyOpenCodeConfigSchema, type OhMyOpenCodeConfig, type HookName } from "./config";
import { log, deepMerge, getUserConfigDir } from "./shared";
import { log, deepMerge, getUserConfigDir, addConfigLoadError } from "./shared";
import { PLAN_SYSTEM_PROMPT, PLAN_PERMISSION } from "./agents/plan-prompt";
import * as fs from "fs";
import * as path from "path";
@@ -62,21 +62,6 @@ const AGENT_NAME_MAP: Record<string, string> = {
"multimodal-looker": "multimodal-looker",
};
export type ConfigLoadError = {
path: string;
error: string;
};
let configLoadErrors: ConfigLoadError[] = [];
export function getConfigLoadErrors(): ConfigLoadError[] {
return configLoadErrors;
}
export function clearConfigLoadErrors(): void {
configLoadErrors = [];
}
function normalizeAgentNames(agents: Record<string, unknown>): Record<string, unknown> {
const normalized: Record<string, unknown> = {};
for (const [key, value] of Object.entries(agents)) {
@@ -101,7 +86,7 @@ function loadConfigFromPath(configPath: string): OhMyOpenCodeConfig | null {
if (!result.success) {
const errorMsg = result.error.issues.map(i => `${i.path.join(".")}: ${i.message}`).join(", ");
log(`Config validation error in ${configPath}:`, result.error.issues);
configLoadErrors.push({ path: configPath, error: `Validation error: ${errorMsg}` });
addConfigLoadError({ path: configPath, error: `Validation error: ${errorMsg}` });
return null;
}
@@ -111,7 +96,7 @@ function loadConfigFromPath(configPath: string): OhMyOpenCodeConfig | null {
} catch (err) {
const errorMsg = err instanceof Error ? err.message : String(err);
log(`Error loading config from ${configPath}:`, err);
configLoadErrors.push({ path: configPath, error: errorMsg });
addConfigLoadError({ path: configPath, error: errorMsg });
}
return null;
}
@@ -506,3 +491,8 @@ export type {
McpName,
HookName,
} from "./config";
// NOTE: Do NOT export functions from main index.ts!
// OpenCode treats ALL exports as plugin instances and calls them.
// Config error utilities are available via "./shared/config-errors" for internal use only.
export type { ConfigLoadError } from "./shared/config-errors";

View File

@@ -0,0 +1,18 @@
export type ConfigLoadError = {
path: string
error: string
}
let configLoadErrors: ConfigLoadError[] = []
export function getConfigLoadErrors(): ConfigLoadError[] {
return configLoadErrors
}
export function clearConfigLoadErrors(): void {
configLoadErrors = []
}
export function addConfigLoadError(error: ConfigLoadError): void {
configLoadErrors.push(error)
}

View File

@@ -11,3 +11,4 @@ export * from "./deep-merge"
export * from "./file-utils"
export * from "./dynamic-truncator"
export * from "./config-path"
export * from "./config-errors"