From 1ae7d7d67e7909dd3ab419ce61e985ab39e6f595 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Sat, 7 Feb 2026 13:32:51 +0900 Subject: [PATCH] feat(config): add plugin_load_timeout_ms and safe_hook_creation experimental flags --- src/config/schema.test.ts | 57 +++++++++++++++++++++++++++++++++++++++ src/config/schema.ts | 4 +++ 2 files changed, 61 insertions(+) diff --git a/src/config/schema.test.ts b/src/config/schema.test.ts index bbf3a50b..bb4f3d58 100644 --- a/src/config/schema.test.ts +++ b/src/config/schema.test.ts @@ -5,6 +5,7 @@ import { BrowserAutomationProviderSchema, BuiltinCategoryNameSchema, CategoryConfigSchema, + ExperimentalConfigSchema, OhMyOpenCodeConfigSchema, } from "./schema" @@ -606,3 +607,59 @@ describe("OhMyOpenCodeConfigSchema - browser_automation_engine", () => { expect(result.data?.browser_automation_engine).toBeUndefined() }) }) + +describe("ExperimentalConfigSchema feature flags", () => { + test("accepts plugin_load_timeout_ms as number", () => { + //#given + const config = { plugin_load_timeout_ms: 5000 } + + //#when + const result = ExperimentalConfigSchema.safeParse(config) + + //#then + expect(result.success).toBe(true) + if (result.success) { + expect(result.data.plugin_load_timeout_ms).toBe(5000) + } + }) + + test("rejects plugin_load_timeout_ms below 1000", () => { + //#given + const config = { plugin_load_timeout_ms: 500 } + + //#when + const result = ExperimentalConfigSchema.safeParse(config) + + //#then + expect(result.success).toBe(false) + }) + + test("accepts safe_hook_creation as boolean", () => { + //#given + const config = { safe_hook_creation: false } + + //#when + const result = ExperimentalConfigSchema.safeParse(config) + + //#then + expect(result.success).toBe(true) + if (result.success) { + expect(result.data.safe_hook_creation).toBe(false) + } + }) + + test("both fields are optional", () => { + //#given + const config = {} + + //#when + const result = ExperimentalConfigSchema.safeParse(config) + + //#then + expect(result.success).toBe(true) + if (result.success) { + expect(result.data.plugin_load_timeout_ms).toBeUndefined() + expect(result.data.safe_hook_creation).toBeUndefined() + } + }) +}) diff --git a/src/config/schema.ts b/src/config/schema.ts index 3b70a31f..8990ea1b 100644 --- a/src/config/schema.ts +++ b/src/config/schema.ts @@ -268,6 +268,10 @@ export const ExperimentalConfigSchema = z.object({ dynamic_context_pruning: DynamicContextPruningConfigSchema.optional(), /** Enable experimental task system for Todowrite disabler hook */ task_system: z.boolean().optional(), + /** Timeout in ms for loadAllPluginComponents during config handler init (default: 10000, min: 1000) */ + plugin_load_timeout_ms: z.number().min(1000).optional(), + /** Wrap hook creation in try/catch to prevent one failing hook from crashing the plugin (default: true at call site) */ + safe_hook_creation: z.boolean().optional(), }) export const SkillSourceSchema = z.union([