fix: show error messages when oh-my-opencode.json config fails to load (#242)
* fix: show error messages when oh-my-opencode.json config fails to load - Add console.error output for config parse errors (syntax errors) - Add console.error output for config validation errors (schema violations) - Display helpful hints for JSON syntax errors - List all validation errors clearly with proper formatting - Errors now shown immediately regardless of hook configuration Fixes #241 * refactor: replace console.error with toast notifications for config errors - Replace console.error with ctx.client.tui.showToast() for better UX - Show toast notifications for both syntax errors and validation errors - Toast notifications persist for 10 seconds for visibility - Display error details with bullet points for validation errors - Include helpful hints for JSON syntax errors This provides a more user-friendly notification system that integrates with OpenCode's UI instead of just logging to console. --------- Co-authored-by: sisyphus-dev-ai <sisyphus-dev-ai@users.noreply.github.com>
This commit is contained in:
37
src/index.ts
37
src/index.ts
@@ -116,7 +116,7 @@ function migrateConfigFile(configPath: string, rawConfig: Record<string, unknown
|
|||||||
return needsWrite;
|
return needsWrite;
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadConfigFromPath(configPath: string): OhMyOpenCodeConfig | null {
|
function loadConfigFromPath(configPath: string, ctx: any): OhMyOpenCodeConfig | null {
|
||||||
try {
|
try {
|
||||||
if (fs.existsSync(configPath)) {
|
if (fs.existsSync(configPath)) {
|
||||||
const content = fs.readFileSync(configPath, "utf-8");
|
const content = fs.readFileSync(configPath, "utf-8");
|
||||||
@@ -130,6 +130,20 @@ function loadConfigFromPath(configPath: string): OhMyOpenCodeConfig | null {
|
|||||||
const errorMsg = result.error.issues.map(i => `${i.path.join(".")}: ${i.message}`).join(", ");
|
const errorMsg = result.error.issues.map(i => `${i.path.join(".")}: ${i.message}`).join(", ");
|
||||||
log(`Config validation error in ${configPath}:`, result.error.issues);
|
log(`Config validation error in ${configPath}:`, result.error.issues);
|
||||||
addConfigLoadError({ path: configPath, error: `Validation error: ${errorMsg}` });
|
addConfigLoadError({ path: configPath, error: `Validation error: ${errorMsg}` });
|
||||||
|
|
||||||
|
const errorList = result.error.issues
|
||||||
|
.map(issue => `• ${issue.path.join(".")}: ${issue.message}`)
|
||||||
|
.join("\n");
|
||||||
|
|
||||||
|
ctx.client.tui.showToast({
|
||||||
|
body: {
|
||||||
|
title: "❌ OhMyOpenCode: Config Validation Failed",
|
||||||
|
message: `Failed to load ${configPath}\n\nValidation errors:\n${errorList}\n\nConfig will be ignored. Please fix the errors above.`,
|
||||||
|
variant: "error" as const,
|
||||||
|
duration: 10000,
|
||||||
|
},
|
||||||
|
}).catch(() => {});
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,6 +154,19 @@ function loadConfigFromPath(configPath: string): OhMyOpenCodeConfig | null {
|
|||||||
const errorMsg = err instanceof Error ? err.message : String(err);
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
||||||
log(`Error loading config from ${configPath}:`, err);
|
log(`Error loading config from ${configPath}:`, err);
|
||||||
addConfigLoadError({ path: configPath, error: errorMsg });
|
addConfigLoadError({ path: configPath, error: errorMsg });
|
||||||
|
|
||||||
|
const hint = err instanceof SyntaxError
|
||||||
|
? "\n\nHint: Check for syntax errors in your JSON file (missing commas, quotes, brackets, etc.)"
|
||||||
|
: "";
|
||||||
|
|
||||||
|
ctx.client.tui.showToast({
|
||||||
|
body: {
|
||||||
|
title: "❌ OhMyOpenCode: Config Load Failed",
|
||||||
|
message: `Failed to load ${configPath}\n\nError: ${errorMsg}${hint}\n\nConfig will be ignored. Please fix the error above.`,
|
||||||
|
variant: "error" as const,
|
||||||
|
duration: 10000,
|
||||||
|
},
|
||||||
|
}).catch(() => {});
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -174,7 +201,7 @@ function mergeConfigs(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadPluginConfig(directory: string): OhMyOpenCodeConfig {
|
function loadPluginConfig(directory: string, ctx: any): OhMyOpenCodeConfig {
|
||||||
// User-level config path (OS-specific)
|
// User-level config path (OS-specific)
|
||||||
const userConfigPath = path.join(
|
const userConfigPath = path.join(
|
||||||
getUserConfigDir(),
|
getUserConfigDir(),
|
||||||
@@ -190,10 +217,10 @@ function loadPluginConfig(directory: string): OhMyOpenCodeConfig {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Load user config first (base)
|
// Load user config first (base)
|
||||||
let config: OhMyOpenCodeConfig = loadConfigFromPath(userConfigPath) ?? {};
|
let config: OhMyOpenCodeConfig = loadConfigFromPath(userConfigPath, ctx) ?? {};
|
||||||
|
|
||||||
// Override with project config
|
// Override with project config
|
||||||
const projectConfig = loadConfigFromPath(projectConfigPath);
|
const projectConfig = loadConfigFromPath(projectConfigPath, ctx);
|
||||||
if (projectConfig) {
|
if (projectConfig) {
|
||||||
config = mergeConfigs(config, projectConfig);
|
config = mergeConfigs(config, projectConfig);
|
||||||
}
|
}
|
||||||
@@ -209,7 +236,7 @@ function loadPluginConfig(directory: string): OhMyOpenCodeConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const OhMyOpenCodePlugin: Plugin = async (ctx) => {
|
const OhMyOpenCodePlugin: Plugin = async (ctx) => {
|
||||||
const pluginConfig = loadPluginConfig(ctx.directory);
|
const pluginConfig = loadPluginConfig(ctx.directory, ctx);
|
||||||
const disabledHooks = new Set(pluginConfig.disabled_hooks ?? []);
|
const disabledHooks = new Set(pluginConfig.disabled_hooks ?? []);
|
||||||
const isHookEnabled = (hookName: HookName) => !disabledHooks.has(hookName);
|
const isHookEnabled = (hookName: HookName) => !disabledHooks.has(hookName);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user