diff --git a/script/build-schema-document.ts b/script/build-schema-document.ts index a4cdf16a9..8238110e4 100644 --- a/script/build-schema-document.ts +++ b/script/build-schema-document.ts @@ -1,8 +1,8 @@ import * as z from "zod" -import { OhMyOpenCodeConfigSchema } from "../src/config/schema" +import { OhMyOpenAgentConfigSchema } from "../src/config/schema" export function createOhMyOpenCodeJsonSchema(): Record { - const jsonSchema = z.toJSONSchema(OhMyOpenCodeConfigSchema, { + const jsonSchema = z.toJSONSchema(OhMyOpenAgentConfigSchema, { target: "draft-7", unrepresentable: "any", }) diff --git a/src/cli/config-manager/add-plugin-to-opencode-config.ts b/src/cli/config-manager/add-plugin-to-opencode-config.ts index 90a78f0ae..cbe6fcc42 100644 --- a/src/cli/config-manager/add-plugin-to-opencode-config.ts +++ b/src/cli/config-manager/add-plugin-to-opencode-config.ts @@ -8,6 +8,8 @@ import { detectConfigFormat } from "./opencode-config-format" import { parseOpenCodeConfigFileWithError, type OpenCodeConfig } from "./parse-opencode-config-file" import { getPluginNameWithVersion } from "./plugin-name-with-version" +const PACKAGE_NAME = PLUGIN_NAME + export async function addPluginToOpenCodeConfig(currentVersion: string): Promise { try { ensureConfigDirectoryExists() @@ -20,7 +22,7 @@ export async function addPluginToOpenCodeConfig(currentVersion: string): Promise } const { format, path } = detectConfigFormat() - const pluginEntry = await getPluginNameWithVersion(currentVersion, PLUGIN_NAME) + const pluginEntry = await getPluginNameWithVersion(currentVersion, PACKAGE_NAME) try { if (format === "none") { @@ -41,7 +43,6 @@ export async function addPluginToOpenCodeConfig(currentVersion: string): Promise const config = parseResult.config const plugins = config.plugin ?? [] - // Check for existing plugin (either current or legacy name) const currentNameIndex = plugins.findIndex( (plugin) => plugin === PLUGIN_NAME || plugin.startsWith(`${PLUGIN_NAME}@`) ) @@ -49,14 +50,12 @@ export async function addPluginToOpenCodeConfig(currentVersion: string): Promise (plugin) => plugin === LEGACY_PLUGIN_NAME || plugin.startsWith(`${LEGACY_PLUGIN_NAME}@`) ) - // If either name exists, update to new name if (currentNameIndex !== -1) { if (plugins[currentNameIndex] === pluginEntry) { return { success: true, configPath: path } } plugins[currentNameIndex] = pluginEntry } else if (legacyNameIndex !== -1) { - // Upgrade legacy name to new name plugins[legacyNameIndex] = pluginEntry } else { plugins.push(pluginEntry) diff --git a/src/cli/config-manager/plugin-name-with-version.ts b/src/cli/config-manager/plugin-name-with-version.ts index 4dfa7cf6b..f8a8f43c1 100644 --- a/src/cli/config-manager/plugin-name-with-version.ts +++ b/src/cli/config-manager/plugin-name-with-version.ts @@ -1,6 +1,7 @@ +import { PLUGIN_NAME } from "../../shared/plugin-identity" import { fetchNpmDistTags } from "./npm-dist-tags" -const DEFAULT_PACKAGE_NAME = "oh-my-opencode" +const DEFAULT_PACKAGE_NAME = PLUGIN_NAME const PRIORITIZED_TAGS = ["latest", "beta", "next"] as const function getFallbackEntry(version: string, packageName: string): string { @@ -18,7 +19,6 @@ export async function getPluginNameWithVersion( ): Promise { const distTags = await fetchNpmDistTags(packageName) - if (distTags) { const allTags = new Set([...PRIORITIZED_TAGS, ...Object.keys(distTags)]) for (const tag of allTags) { diff --git a/src/cli/doctor/checks/config.ts b/src/cli/doctor/checks/config.ts index 4f8fc549f..1a9cb40d8 100644 --- a/src/cli/doctor/checks/config.ts +++ b/src/cli/doctor/checks/config.ts @@ -1,7 +1,7 @@ import { readFileSync } from "node:fs" import { join } from "node:path" -import { OhMyOpenCodeConfigSchema } from "../../../config" +import { OhMyOpenAgentConfigSchema } from "../../../config" import { detectConfigFile, getOpenCodeConfigDir, parseJsonc } from "../../../shared" import { CHECK_IDS, CHECK_NAMES, PACKAGE_NAME } from "../constants" import type { CheckResult, DoctorIssue } from "../types" @@ -39,7 +39,7 @@ function validateConfig(): ConfigValidationResult { try { const content = readFileSync(configPath, "utf-8") const rawConfig = parseJsonc(content) - const schemaResult = OhMyOpenCodeConfigSchema.safeParse(rawConfig) + const schemaResult = OhMyOpenAgentConfigSchema.safeParse(rawConfig) if (!schemaResult.success) { return { diff --git a/src/cli/doctor/checks/model-resolution-config.ts b/src/cli/doctor/checks/model-resolution-config.ts index db01cc4e5..f6626b45c 100644 --- a/src/cli/doctor/checks/model-resolution-config.ts +++ b/src/cli/doctor/checks/model-resolution-config.ts @@ -1,9 +1,10 @@ +import { PLUGIN_NAME } from "../../../shared/plugin-identity" import { readFileSync } from "node:fs" import { join } from "node:path" import { detectConfigFile, getOpenCodeConfigPaths, parseJsonc } from "../../../shared" import type { OmoConfig } from "./model-resolution-types" -const PACKAGE_NAME = "oh-my-opencode" +const PACKAGE_NAME = PLUGIN_NAME const USER_CONFIG_BASE = join( getOpenCodeConfigPaths({ binary: "opencode", version: null }).configDir, PACKAGE_NAME diff --git a/src/cli/doctor/constants.ts b/src/cli/doctor/constants.ts index ff41f836e..06fdf9e59 100644 --- a/src/cli/doctor/constants.ts +++ b/src/cli/doctor/constants.ts @@ -1,3 +1,4 @@ +import { PLUGIN_NAME } from "../../shared/plugin-identity" import color from "picocolors" export const SYMBOLS = { @@ -38,6 +39,6 @@ export const EXIT_CODES = { export const MIN_OPENCODE_VERSION = "1.0.150" -export const PACKAGE_NAME = "oh-my-opencode" +export const PACKAGE_NAME = PLUGIN_NAME export const OPENCODE_BINARIES = ["opencode", "opencode-desktop"] as const diff --git a/src/cli/run/agent-resolver.ts b/src/cli/run/agent-resolver.ts index 9bb820412..d1b9d09ec 100644 --- a/src/cli/run/agent-resolver.ts +++ b/src/cli/run/agent-resolver.ts @@ -1,6 +1,6 @@ import pc from "picocolors" import type { RunOptions } from "./types" -import type { OhMyOpenCodeConfig } from "../../config" +import type { OhMyOpenAgentConfig } from "../../config" import { getAgentConfigKey, getAgentDisplayName } from "../../shared/agent-display-names" const CORE_AGENT_ORDER = ["sisyphus", "hephaestus", "prometheus", "atlas"] as const @@ -29,7 +29,7 @@ const normalizeAgentName = (agent?: string): ResolvedAgent | undefined => { } } -const isAgentDisabled = (agentConfigKey: string, config: OhMyOpenCodeConfig): boolean => { +const isAgentDisabled = (agentConfigKey: string, config: OhMyOpenAgentConfig): boolean => { const lowered = agentConfigKey.toLowerCase() if (lowered === DEFAULT_AGENT && config.sisyphus_agent?.disabled === true) { return true @@ -39,7 +39,7 @@ const isAgentDisabled = (agentConfigKey: string, config: OhMyOpenCodeConfig): bo ) } -const pickFallbackAgent = (config: OhMyOpenCodeConfig): CoreAgentKey => { +const pickFallbackAgent = (config: OhMyOpenAgentConfig): CoreAgentKey => { for (const agent of CORE_AGENT_ORDER) { if (!isAgentDisabled(agent, config)) { return agent @@ -50,7 +50,7 @@ const pickFallbackAgent = (config: OhMyOpenCodeConfig): CoreAgentKey => { export const resolveRunAgent = ( options: RunOptions, - pluginConfig: OhMyOpenCodeConfig, + pluginConfig: OhMyOpenAgentConfig, env: EnvVars = process.env ): string => { const cliAgent = normalizeAgentName(options.agent) diff --git a/src/cli/run/runner.test.ts b/src/cli/run/runner.test.ts index fa5d80b51..507895fc1 100644 --- a/src/cli/run/runner.test.ts +++ b/src/cli/run/runner.test.ts @@ -1,10 +1,10 @@ /// -import { describe, it, expect, beforeEach, afterEach, vi } from "bun:test" -import type { OhMyOpenCodeConfig } from "../../config" +import { describe, it, expect } from "bun:test" +import type { OhMyOpenAgentConfig } from "../../config" import { resolveRunAgent, waitForEventProcessorShutdown } from "./runner" -const createConfig = (overrides: Partial = {}): OhMyOpenCodeConfig => ({ +const createConfig = (overrides: Partial = {}): OhMyOpenAgentConfig => ({ ...overrides, }) @@ -133,23 +133,16 @@ describe("run with invalid model", () => { try { // when - // Note: This will actually try to run - but the issue is that resolveRunModel - // is called BEFORE the try block, so it throws an unhandled exception - // We're testing the runner's error handling const { run } = await import("./runner") - // This will throw because model "invalid" is invalid format try { await run({ message: "test", model: "invalid", }) } catch { - // Expected to potentially throw due to unhandled model resolution error } } finally { - // then - verify error handling - // Currently this will fail because the error is not caught properly console.error = originalError process.exit = originalExit } diff --git a/src/config/index.ts b/src/config/index.ts index 2f7f98578..22e74cbb2 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -1,9 +1,9 @@ export { - OhMyOpenCodeConfigSchema, + OhMyOpenAgentConfigSchema, } from "./schema" export type { - OhMyOpenCodeConfig, + OhMyOpenAgentConfig, AgentOverrideConfig, AgentOverrides, McpName, diff --git a/src/config/schema.test.ts b/src/config/schema.test.ts index d357571c7..904be3476 100644 --- a/src/config/schema.test.ts +++ b/src/config/schema.test.ts @@ -10,7 +10,7 @@ import { ExperimentalConfigSchema, GitMasterConfigSchema, HookNameSchema, - OhMyOpenCodeConfigSchema, + OhMyOpenAgentConfigSchema, } from "./schema" describe("disabled_mcps schema", () => { @@ -21,7 +21,7 @@ describe("disabled_mcps schema", () => { } // when - const result = OhMyOpenCodeConfigSchema.safeParse(config) + const result = OhMyOpenAgentConfigSchema.safeParse(config) // then expect(result.success).toBe(true) @@ -37,7 +37,7 @@ describe("disabled_mcps schema", () => { } // when - const result = OhMyOpenCodeConfigSchema.safeParse(config) + const result = OhMyOpenAgentConfigSchema.safeParse(config) // then expect(result.success).toBe(true) @@ -53,7 +53,7 @@ describe("disabled_mcps schema", () => { } // when - const result = OhMyOpenCodeConfigSchema.safeParse(config) + const result = OhMyOpenAgentConfigSchema.safeParse(config) // then expect(result.success).toBe(true) @@ -69,7 +69,7 @@ describe("disabled_mcps schema", () => { } // when - const result = OhMyOpenCodeConfigSchema.safeParse(config) + const result = OhMyOpenAgentConfigSchema.safeParse(config) // then expect(result.success).toBe(true) @@ -85,7 +85,7 @@ describe("disabled_mcps schema", () => { } // when - const result = OhMyOpenCodeConfigSchema.safeParse(config) + const result = OhMyOpenAgentConfigSchema.safeParse(config) // then expect(result.success).toBe(false) @@ -96,7 +96,7 @@ describe("disabled_mcps schema", () => { const config = {} // when - const result = OhMyOpenCodeConfigSchema.safeParse(config) + const result = OhMyOpenAgentConfigSchema.safeParse(config) // then expect(result.success).toBe(true) @@ -112,7 +112,7 @@ describe("disabled_mcps schema", () => { } // when - const result = OhMyOpenCodeConfigSchema.safeParse(config) + const result = OhMyOpenAgentConfigSchema.safeParse(config) // then expect(result.success).toBe(false) @@ -131,7 +131,7 @@ describe("disabled_mcps schema", () => { } // when - const result = OhMyOpenCodeConfigSchema.safeParse(config) + const result = OhMyOpenAgentConfigSchema.safeParse(config) // then expect(result.success).toBe(true) @@ -433,7 +433,7 @@ describe("Sisyphus-Junior agent override", () => { } // when - const result = OhMyOpenCodeConfigSchema.safeParse(config) + const result = OhMyOpenAgentConfigSchema.safeParse(config) // then expect(result.success).toBe(true) @@ -455,7 +455,7 @@ describe("Sisyphus-Junior agent override", () => { } // when - const result = OhMyOpenCodeConfigSchema.safeParse(config) + const result = OhMyOpenAgentConfigSchema.safeParse(config) // then expect(result.success).toBe(true) @@ -480,7 +480,7 @@ describe("Sisyphus-Junior agent override", () => { } // when - const result = OhMyOpenCodeConfigSchema.safeParse(config) + const result = OhMyOpenAgentConfigSchema.safeParse(config) // then expect(result.success).toBe(true) @@ -509,7 +509,7 @@ describe("Sisyphus-Junior agent override", () => { } // when - const result = OhMyOpenCodeConfigSchema.safeParse(config) + const result = OhMyOpenAgentConfigSchema.safeParse(config) // then expect(result.success).toBe(true) @@ -534,7 +534,7 @@ describe("Sisyphus-Junior agent override", () => { } // when - const result = OhMyOpenCodeConfigSchema.safeParse(config) + const result = OhMyOpenAgentConfigSchema.safeParse(config) // then expect(result.success).toBe(true) @@ -639,7 +639,7 @@ describe("OhMyOpenCodeConfigSchema - browser_automation_engine", () => { } // when - const result = OhMyOpenCodeConfigSchema.safeParse(input) + const result = OhMyOpenAgentConfigSchema.safeParse(input) // then expect(result.success).toBe(true) @@ -651,7 +651,7 @@ describe("OhMyOpenCodeConfigSchema - browser_automation_engine", () => { const input = {} // when - const result = OhMyOpenCodeConfigSchema.safeParse(input) + const result = OhMyOpenAgentConfigSchema.safeParse(input) // then expect(result.success).toBe(true) @@ -663,7 +663,7 @@ describe("OhMyOpenCodeConfigSchema - browser_automation_engine", () => { const input = { browser_automation_engine: { provider: "playwright-cli" } } // when - const result = OhMyOpenCodeConfigSchema.safeParse(input) + const result = OhMyOpenAgentConfigSchema.safeParse(input) // then expect(result.success).toBe(true) @@ -677,7 +677,7 @@ describe("OhMyOpenCodeConfigSchema - hashline_edit", () => { const input = { hashline_edit: true } //#when - const result = OhMyOpenCodeConfigSchema.safeParse(input) + const result = OhMyOpenAgentConfigSchema.safeParse(input) //#then expect(result.success).toBe(true) @@ -689,7 +689,7 @@ describe("OhMyOpenCodeConfigSchema - hashline_edit", () => { const input = { hashline_edit: false } //#when - const result = OhMyOpenCodeConfigSchema.safeParse(input) + const result = OhMyOpenAgentConfigSchema.safeParse(input) //#then expect(result.success).toBe(true) @@ -701,7 +701,7 @@ describe("OhMyOpenCodeConfigSchema - hashline_edit", () => { const input = { auto_update: true } //#when - const result = OhMyOpenCodeConfigSchema.safeParse(input) + const result = OhMyOpenAgentConfigSchema.safeParse(input) //#then expect(result.success).toBe(true) @@ -713,7 +713,7 @@ describe("OhMyOpenCodeConfigSchema - hashline_edit", () => { const input = { hashline_edit: "true" } //#when - const result = OhMyOpenCodeConfigSchema.safeParse(input) + const result = OhMyOpenAgentConfigSchema.safeParse(input) //#then expect(result.success).toBe(false) @@ -928,7 +928,7 @@ describe("skills schema", () => { } //#when - const result = OhMyOpenCodeConfigSchema.safeParse(config) + const result = OhMyOpenAgentConfigSchema.safeParse(config) //#then expect(result.success).toBe(true) diff --git a/src/config/schema/oh-my-openagent-config.ts b/src/config/schema/oh-my-openagent-config.ts index 9f4d70c99..9c0260287 100644 --- a/src/config/schema/oh-my-openagent-config.ts +++ b/src/config/schema/oh-my-openagent-config.ts @@ -21,7 +21,7 @@ import { TmuxConfigSchema } from "./tmux" import { StartWorkConfigSchema } from "./start-work" import { WebsearchConfigSchema } from "./websearch" -export const OhMyOpenCodeConfigSchema = z.object({ +export const OhMyOpenAgentConfigSchema = z.object({ $schema: z.string().optional(), /** Enable new task system (default: false) */ new_task_system_enabled: z.boolean().optional(), @@ -66,4 +66,4 @@ export const OhMyOpenCodeConfigSchema = z.object({ _migrations: z.array(z.string()).optional(), }) -export type OhMyOpenCodeConfig = z.infer +export type OhMyOpenAgentConfig = z.infer diff --git a/src/create-hooks.ts b/src/create-hooks.ts index e49f08c9a..38cf79ed9 100644 --- a/src/create-hooks.ts +++ b/src/create-hooks.ts @@ -1,5 +1,5 @@ import type { AvailableSkill } from "./agents/dynamic-agent-prompt-builder" -import type { HookName, OhMyOpenCodeConfig } from "./config" +import type { HookName, OhMyOpenAgentConfig } from "./config" import type { LoadedSkill } from "./features/opencode-skill-loader/types" import type { BackgroundManager } from "./features/background-agent" import type { PluginContext } from "./plugin/types" @@ -27,7 +27,7 @@ export function disposeCreatedHooks(hooks: DisposableCreatedHooks): void { export function createHooks(args: { ctx: PluginContext - pluginConfig: OhMyOpenCodeConfig + pluginConfig: OhMyOpenAgentConfig modelCacheState: ModelCacheState backgroundManager: BackgroundManager isHookEnabled: (hookName: HookName) => boolean diff --git a/src/create-managers.ts b/src/create-managers.ts index 0aefd0e20..f8050fe98 100644 --- a/src/create-managers.ts +++ b/src/create-managers.ts @@ -1,4 +1,4 @@ -import type { OhMyOpenCodeConfig } from "./config" +import type { OhMyOpenAgentConfig } from "./config" import type { ModelCacheState } from "./plugin-state" import type { PluginContext, TmuxConfig } from "./plugin/types" @@ -19,7 +19,7 @@ export type Managers = { export function createManagers(args: { ctx: PluginContext - pluginConfig: OhMyOpenCodeConfig + pluginConfig: OhMyOpenAgentConfig tmuxConfig: TmuxConfig modelCacheState: ModelCacheState backgroundNotificationHookEnabled: boolean diff --git a/src/create-tools.ts b/src/create-tools.ts index 880e0a427..ee45f1e5d 100644 --- a/src/create-tools.ts +++ b/src/create-tools.ts @@ -1,5 +1,5 @@ import type { AvailableCategory, AvailableSkill } from "./agents/dynamic-agent-prompt-builder" -import type { OhMyOpenCodeConfig } from "./config" +import type { OhMyOpenAgentConfig } from "./config" import type { BrowserAutomationProvider } from "./config/schema/browser-automation" import type { LoadedSkill } from "./features/opencode-skill-loader/types" import type { PluginContext, ToolsRecord } from "./plugin/types" @@ -21,7 +21,7 @@ export type CreateToolsResult = { export async function createTools(args: { ctx: PluginContext - pluginConfig: OhMyOpenCodeConfig + pluginConfig: OhMyOpenAgentConfig managers: Pick }): Promise { const { ctx, pluginConfig, managers } = args diff --git a/src/features/claude-tasks/session-storage.test.ts b/src/features/claude-tasks/session-storage.test.ts index 7b3e5a5ba..3fff8ce4e 100644 --- a/src/features/claude-tasks/session-storage.test.ts +++ b/src/features/claude-tasks/session-storage.test.ts @@ -1,7 +1,7 @@ import { describe, test, expect, beforeEach, afterEach } from "bun:test" import { existsSync, mkdirSync, rmSync, writeFileSync, readdirSync } from "fs" import { join } from "path" -import type { OhMyOpenCodeConfig } from "../../config/schema" +import type { OhMyOpenAgentConfig } from "../../config/schema" import { getSessionTaskDir, listSessionTaskFiles, @@ -12,7 +12,7 @@ import { const TEST_DIR = ".test-session-storage" const TEST_DIR_ABS = join(process.cwd(), TEST_DIR) -function makeConfig(storagePath: string): Partial { +function makeConfig(storagePath: string): Partial { return { sisyphus: { tasks: { storage_path: storagePath, claude_code_compat: false }, diff --git a/src/features/claude-tasks/session-storage.ts b/src/features/claude-tasks/session-storage.ts index 749f9c1bd..9bba649a3 100644 --- a/src/features/claude-tasks/session-storage.ts +++ b/src/features/claude-tasks/session-storage.ts @@ -1,17 +1,17 @@ import { join } from "path" import { existsSync, readdirSync, statSync } from "fs" import { getTaskDir } from "./storage" -import type { OhMyOpenCodeConfig } from "../../config/schema" +import type { OhMyOpenAgentConfig } from "../../config/schema" export function getSessionTaskDir( - config: Partial, + config: Partial, sessionID: string, ): string { return join(getTaskDir(config), sessionID) } export function listSessionTaskFiles( - config: Partial, + config: Partial, sessionID: string, ): string[] { const dir = getSessionTaskDir(config, sessionID) @@ -22,7 +22,7 @@ export function listSessionTaskFiles( } export function listAllSessionDirs( - config: Partial, + config: Partial, ): string[] { const baseDir = getTaskDir(config) if (!existsSync(baseDir)) return [] @@ -38,7 +38,7 @@ export interface TaskLocation { } export function findTaskAcrossSessions( - config: Partial, + config: Partial, taskId: string, ): TaskLocation | null { const sessionDirs = listAllSessionDirs(config) diff --git a/src/features/claude-tasks/storage.test.ts b/src/features/claude-tasks/storage.test.ts index e4aed7ffc..c619299dc 100644 --- a/src/features/claude-tasks/storage.test.ts +++ b/src/features/claude-tasks/storage.test.ts @@ -13,7 +13,7 @@ import { resolveTaskListId, sanitizePathSegment, } from "./storage" -import type { OhMyOpenCodeConfig } from "../../config/schema" +import type { OhMyOpenAgentConfig } from "../../config/schema" const TEST_DIR = ".test-claude-tasks" const TEST_DIR_ABS = join(process.cwd(), TEST_DIR) @@ -52,7 +52,7 @@ describe("getTaskDir", () => { test("returns global config path for default config", () => { //#given - const config: Partial = {} + const config: Partial = {} const configDir = getOpenCodeConfigDir({ binary: "opencode" }) const expectedListId = sanitizePathSegment(basename(process.cwd())) @@ -103,7 +103,7 @@ describe("getTaskDir", () => { test("returns absolute storage_path without joining cwd", () => { //#given - const config: Partial = { + const config: Partial = { sisyphus: { tasks: { storage_path: "/tmp/custom-task-path", @@ -121,7 +121,7 @@ describe("getTaskDir", () => { test("joins relative storage_path with cwd", () => { //#given - const config: Partial = { + const config: Partial = { sisyphus: { tasks: { storage_path: ".custom/tasks", @@ -263,7 +263,7 @@ describe("listTaskFiles", () => { test("returns empty array for non-existent directory", () => { //#given - const config: Partial = { + const config: Partial = { new_task_system_enabled: false, sisyphus: { tasks: { storage_path: TEST_DIR, claude_code_compat: false } } } @@ -277,7 +277,7 @@ describe("listTaskFiles", () => { test("returns empty array for directory with no task files", () => { //#given - const config: Partial = { + const config: Partial = { new_task_system_enabled: false, sisyphus: { tasks: { storage_path: TEST_DIR, claude_code_compat: false } } } @@ -293,7 +293,7 @@ describe("listTaskFiles", () => { test("lists task files with T- prefix and .json extension", () => { //#given - const config: Partial = { + const config: Partial = { new_task_system_enabled: false, sisyphus: { tasks: { storage_path: TEST_DIR, claude_code_compat: false } } } @@ -314,7 +314,7 @@ describe("listTaskFiles", () => { test("returns task IDs without .json extension", () => { //#given - const config: Partial = { + const config: Partial = { new_task_system_enabled: false, sisyphus: { tasks: { storage_path: TEST_DIR, claude_code_compat: false } } } diff --git a/src/features/claude-tasks/storage.ts b/src/features/claude-tasks/storage.ts index 698a9a7ca..6d075af8c 100644 --- a/src/features/claude-tasks/storage.ts +++ b/src/features/claude-tasks/storage.ts @@ -3,9 +3,9 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync, renameSync, unlinkS import { randomUUID } from "crypto" import { getOpenCodeConfigDir } from "../../shared/opencode-config-dir" import type { z } from "zod" -import type { OhMyOpenCodeConfig } from "../../config/schema" +import type { OhMyOpenAgentConfig } from "../../config/schema" -export function getTaskDir(config: Partial = {}): string { +export function getTaskDir(config: Partial = {}): string { const tasksConfig = config.sisyphus?.tasks const storagePath = tasksConfig?.storage_path @@ -22,7 +22,7 @@ export function sanitizePathSegment(value: string): string { return value.replace(/[^a-zA-Z0-9_-]/g, "-") || "default" } -export function resolveTaskListId(config: Partial = {}): string { +export function resolveTaskListId(config: Partial = {}): string { const envId = process.env.ULTRAWORK_TASK_LIST_ID?.trim() if (envId) return sanitizePathSegment(envId) @@ -88,7 +88,7 @@ export function generateTaskId(): string { return `T-${randomUUID()}` } -export function listTaskFiles(config: Partial = {}): string[] { +export function listTaskFiles(config: Partial = {}): string[] { const dir = getTaskDir(config) if (!existsSync(dir)) return [] return readdirSync(dir) diff --git a/src/hooks/anthropic-context-window-limit-recovery/executor.ts b/src/hooks/anthropic-context-window-limit-recovery/executor.ts index 02a2a06e4..3d49449fb 100644 --- a/src/hooks/anthropic-context-window-limit-recovery/executor.ts +++ b/src/hooks/anthropic-context-window-limit-recovery/executor.ts @@ -1,5 +1,5 @@ import type { AutoCompactState } from "./types"; -import type { OhMyOpenCodeConfig } from "../../config"; +import type { OhMyOpenAgentConfig } from "../../config"; import type { ExperimentalConfig } from "../../config"; import { TRUNCATE_CONFIG } from "./types"; @@ -18,7 +18,7 @@ export async function executeCompact( autoCompactState: AutoCompactState, client: Client, directory: string, - pluginConfig: OhMyOpenCodeConfig, + pluginConfig: OhMyOpenAgentConfig, _experimental?: ExperimentalConfig ): Promise { void _experimental diff --git a/src/hooks/anthropic-context-window-limit-recovery/recovery-hook.ts b/src/hooks/anthropic-context-window-limit-recovery/recovery-hook.ts index 63a0f6fba..13b7b9add 100644 --- a/src/hooks/anthropic-context-window-limit-recovery/recovery-hook.ts +++ b/src/hooks/anthropic-context-window-limit-recovery/recovery-hook.ts @@ -1,7 +1,7 @@ import type { PluginInput } from "@opencode-ai/plugin" import type { Client } from "./client" import type { AutoCompactState, ParsedTokenLimitError } from "./types" -import type { ExperimentalConfig, OhMyOpenCodeConfig } from "../../config" +import type { ExperimentalConfig, OhMyOpenAgentConfig } from "../../config" import { parseAnthropicTokenLimitError } from "./parser" import { executeCompact, getLastAssistant } from "./executor" import { attemptDeduplicationRecovery } from "./deduplication-recovery" @@ -9,7 +9,7 @@ import { log } from "../../shared/logger" export interface AnthropicContextWindowLimitRecoveryOptions { experimental?: ExperimentalConfig - pluginConfig: OhMyOpenCodeConfig + pluginConfig: OhMyOpenAgentConfig } function createRecoveryState(): AutoCompactState { diff --git a/src/hooks/anthropic-context-window-limit-recovery/summarize-retry-strategy.test.ts b/src/hooks/anthropic-context-window-limit-recovery/summarize-retry-strategy.test.ts index fa0fb295d..6dbf92a57 100644 --- a/src/hooks/anthropic-context-window-limit-recovery/summarize-retry-strategy.test.ts +++ b/src/hooks/anthropic-context-window-limit-recovery/summarize-retry-strategy.test.ts @@ -1,7 +1,7 @@ import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test" import { runSummarizeRetryStrategy } from "./summarize-retry-strategy" import type { AutoCompactState, ParsedTokenLimitError, RetryState } from "./types" -import type { OhMyOpenCodeConfig } from "../../config" +import type { OhMyOpenAgentConfig } from "../../config" type TimeoutCall = { delay: number @@ -72,7 +72,7 @@ describe("runSummarizeRetryStrategy", () => { autoCompactState, client: client as never, directory, - pluginConfig: {} as OhMyOpenCodeConfig, + pluginConfig: {} as OhMyOpenAgentConfig, }) //#then @@ -111,7 +111,7 @@ describe("runSummarizeRetryStrategy", () => { autoCompactState, client: client as never, directory, - pluginConfig: {} as OhMyOpenCodeConfig, + pluginConfig: {} as OhMyOpenAgentConfig, }) //#then diff --git a/src/hooks/anthropic-context-window-limit-recovery/summarize-retry-strategy.ts b/src/hooks/anthropic-context-window-limit-recovery/summarize-retry-strategy.ts index 008ff74a5..3f8f4ea2d 100644 --- a/src/hooks/anthropic-context-window-limit-recovery/summarize-retry-strategy.ts +++ b/src/hooks/anthropic-context-window-limit-recovery/summarize-retry-strategy.ts @@ -1,5 +1,5 @@ import type { AutoCompactState } from "./types" -import type { OhMyOpenCodeConfig } from "../../config" +import type { OhMyOpenAgentConfig } from "../../config" import { RETRY_CONFIG } from "./types" import type { Client } from "./client" import { clearSessionState, getEmptyContentAttempt, getOrCreateRetryState } from "./state" @@ -15,7 +15,7 @@ export async function runSummarizeRetryStrategy(params: { autoCompactState: AutoCompactState client: Client directory: string - pluginConfig: OhMyOpenCodeConfig + pluginConfig: OhMyOpenAgentConfig errorType?: string messageIndex?: number }): Promise { diff --git a/src/hooks/preemptive-compaction.aws-bedrock.test.ts b/src/hooks/preemptive-compaction.aws-bedrock.test.ts index 9ce47ac8c..7280529d0 100644 --- a/src/hooks/preemptive-compaction.aws-bedrock.test.ts +++ b/src/hooks/preemptive-compaction.aws-bedrock.test.ts @@ -2,7 +2,7 @@ import { describe, expect, it, mock } from "bun:test" -import { OhMyOpenCodeConfigSchema } from "../config" +import { OhMyOpenAgentConfigSchema } from "../config" const { createPreemptiveCompactionHook } = await import("./preemptive-compaction") @@ -27,7 +27,7 @@ describe("preemptive-compaction aws-bedrock-anthropic", () => { it("triggers compaction for aws-bedrock-anthropic provider when usage exceeds threshold", async () => { // given const ctx = createMockContext() - const pluginConfig = OhMyOpenCodeConfigSchema.parse({}) + const pluginConfig = OhMyOpenAgentConfigSchema.parse({}) const hook = createPreemptiveCompactionHook(ctx, pluginConfig) const sessionID = "ses_aws_bedrock_anthropic_high" diff --git a/src/hooks/preemptive-compaction.ts b/src/hooks/preemptive-compaction.ts index b75679e40..5a46a7c92 100644 --- a/src/hooks/preemptive-compaction.ts +++ b/src/hooks/preemptive-compaction.ts @@ -1,5 +1,5 @@ import { log } from "../shared/logger" -import type { OhMyOpenCodeConfig } from "../config" +import type { OhMyOpenAgentConfig } from "../config" import { resolveActualContextLimit, type ContextLimitModelCacheState, @@ -61,7 +61,7 @@ type PluginInput = { export function createPreemptiveCompactionHook( ctx: PluginInput, - pluginConfig: OhMyOpenCodeConfig, + pluginConfig: OhMyOpenAgentConfig, modelCacheState?: ContextLimitModelCacheState, ) { const compactionInProgress = new Set() diff --git a/src/hooks/runtime-fallback/fallback-bootstrap-model.ts b/src/hooks/runtime-fallback/fallback-bootstrap-model.ts index 78437d594..26c18c144 100644 --- a/src/hooks/runtime-fallback/fallback-bootstrap-model.ts +++ b/src/hooks/runtime-fallback/fallback-bootstrap-model.ts @@ -1,4 +1,4 @@ -import type { OhMyOpenCodeConfig } from "../../config" +import type { OhMyOpenAgentConfig } from "../../config" import { HOOK_NAME } from "./constants" import { log } from "../../shared/logger" import { SessionCategoryRegistry } from "../../shared/session-category-registry" @@ -8,7 +8,7 @@ type ResolveFallbackBootstrapModelOptions = { source: string eventModel?: string resolvedAgent?: string - pluginConfig?: OhMyOpenCodeConfig + pluginConfig?: OhMyOpenAgentConfig } export function resolveFallbackBootstrapModel( diff --git a/src/hooks/runtime-fallback/fallback-models.ts b/src/hooks/runtime-fallback/fallback-models.ts index fb984bbec..41792e8d8 100644 --- a/src/hooks/runtime-fallback/fallback-models.ts +++ b/src/hooks/runtime-fallback/fallback-models.ts @@ -1,4 +1,4 @@ -import type { OhMyOpenCodeConfig } from "../../config" +import type { OhMyOpenAgentConfig } from "../../config" import { agentPattern } from "./agent-resolver" import { HOOK_NAME } from "./constants" import { log } from "../../shared/logger" @@ -8,7 +8,7 @@ import { normalizeFallbackModels } from "../../shared/model-resolver" export function getFallbackModelsForSession( sessionID: string, agent: string | undefined, - pluginConfig: OhMyOpenCodeConfig | undefined + pluginConfig: OhMyOpenAgentConfig | undefined ): string[] { if (!pluginConfig) return [] diff --git a/src/hooks/runtime-fallback/index.test.ts b/src/hooks/runtime-fallback/index.test.ts index 3956d26c8..c06c17809 100644 --- a/src/hooks/runtime-fallback/index.test.ts +++ b/src/hooks/runtime-fallback/index.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test, beforeEach, afterEach, spyOn } from "bun:test" import { createRuntimeFallbackHook } from "./index" -import type { RuntimeFallbackConfig, OhMyOpenCodeConfig } from "../../config" +import type { RuntimeFallbackConfig, OhMyOpenAgentConfig } from "../../config" import * as sharedModule from "../../shared" import { SessionCategoryRegistry } from "../../shared/session-category-registry" @@ -62,32 +62,26 @@ describe("runtime-fallback", () => { } } - function createMockPluginConfigWithCategoryFallback(fallbackModels: string[]): OhMyOpenCodeConfig { - return { - categories: { - test: { - fallback_models: fallbackModels, - }, + function createMockPluginConfigWithCategoryFallback(fallbackModels: string[]): OhMyOpenAgentConfig { return { + categories: { + test: { + fallback_models: fallbackModels, }, - } - } + }, + } } - function createMockPluginConfigWithCategoryModel( - categoryName: string, - model: string, - fallbackModels: string[], - variant?: string, - ): OhMyOpenCodeConfig { - return { - categories: { - [categoryName]: { - model, - fallback_models: fallbackModels, - ...(variant ? { variant } : {}), - }, + function createMockPluginConfigWithCategoryModel(categoryName: string, + model: string, + fallbackModels: string[], + variant?: string,): OhMyOpenAgentConfig { return { + categories: { + [categoryName]: { + model, + fallback_models: fallbackModels, + ...(variant ? { variant } : {}), }, - } - } + }, + } } describe("session.error handling", () => { test("should detect retryable error with status code 429", async () => { @@ -2297,15 +2291,13 @@ describe("runtime-fallback", () => { }) describe("fallback models configuration", () => { - function createMockPluginConfigWithAgentFallback(agentName: string, fallbackModels: string[]): OhMyOpenCodeConfig { - return { - agents: { - [agentName]: { - fallback_models: fallbackModels, - }, + function createMockPluginConfigWithAgentFallback(agentName: string, fallbackModels: string[]): OhMyOpenAgentConfig { return { + agents: { + [agentName]: { + fallback_models: fallbackModels, }, - } - } + }, + } } test("should use agent-level fallback_models", async () => { const input = createMockPluginInput() diff --git a/src/hooks/runtime-fallback/types.ts b/src/hooks/runtime-fallback/types.ts index ecf18a4f5..7b128f61c 100644 --- a/src/hooks/runtime-fallback/types.ts +++ b/src/hooks/runtime-fallback/types.ts @@ -1,4 +1,4 @@ -import type { RuntimeFallbackConfig, OhMyOpenCodeConfig } from "../../config" +import type { RuntimeFallbackConfig, OhMyOpenAgentConfig } from "../../config" export interface RuntimeFallbackInterval { unref: () => void @@ -53,7 +53,7 @@ export interface FallbackResult { export interface RuntimeFallbackOptions { config?: RuntimeFallbackConfig - pluginConfig?: OhMyOpenCodeConfig + pluginConfig?: OhMyOpenAgentConfig session_timeout_ms?: number } @@ -67,7 +67,7 @@ export interface HookDeps { ctx: RuntimeFallbackPluginInput config: Required options: RuntimeFallbackOptions | undefined - pluginConfig: OhMyOpenCodeConfig | undefined + pluginConfig: OhMyOpenAgentConfig | undefined sessionStates: Map sessionLastAccess: Map sessionRetryInFlight: Set diff --git a/src/hooks/shared/compaction-model-resolver.ts b/src/hooks/shared/compaction-model-resolver.ts index 6993c7987..4b1a24e20 100644 --- a/src/hooks/shared/compaction-model-resolver.ts +++ b/src/hooks/shared/compaction-model-resolver.ts @@ -1,9 +1,9 @@ -import type { OhMyOpenCodeConfig } from "../../config" +import type { OhMyOpenAgentConfig } from "../../config" import { getSessionAgent } from "../../features/claude-code-session-state" import { getAgentConfigKey } from "../../shared/agent-display-names" export function resolveCompactionModel( - pluginConfig: OhMyOpenCodeConfig, + pluginConfig: OhMyOpenAgentConfig, sessionID: string, originalProviderID: string, originalModelID: string diff --git a/src/index.ts b/src/index.ts index 70156f109..0c91be075 100644 --- a/src/index.ts +++ b/src/index.ts @@ -17,7 +17,7 @@ import { startTmuxCheck } from "./tools" let activePluginDispose: PluginDispose | null = null -const OhMyOpenCodePlugin: Plugin = async (ctx) => { +const OhMyOpenAgentPlugin: Plugin = async (ctx) => { // Initialize config context for plugin runtime (prevents warnings from hooks) initConfigContext("opencode", null) log("[OhMyOpenCodePlugin] ENTRY - plugin loading", { @@ -108,10 +108,10 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => { } } -export default OhMyOpenCodePlugin +export default OhMyOpenAgentPlugin export type { - OhMyOpenCodeConfig, + OhMyOpenAgentConfig, AgentName, AgentOverrideConfig, AgentOverrides, diff --git a/src/mcp/index.ts b/src/mcp/index.ts index f97261477..e70e36836 100644 --- a/src/mcp/index.ts +++ b/src/mcp/index.ts @@ -1,7 +1,7 @@ import { createWebsearchConfig } from "./websearch" import { context7 } from "./context7" import { grep_app } from "./grep-app" -import type { OhMyOpenCodeConfig } from "../config/schema" +import type { OhMyOpenAgentConfig } from "../config/schema" export { McpNameSchema, type McpName } from "./types" @@ -13,7 +13,7 @@ type RemoteMcpConfig = { oauth?: false } -export function createBuiltinMcps(disabledMcps: string[] = [], config?: OhMyOpenCodeConfig) { +export function createBuiltinMcps(disabledMcps: string[] = [], config?: OhMyOpenAgentConfig) { const mcps: Record = {} if (!disabledMcps.includes("websearch")) { diff --git a/src/plugin-config.test.ts b/src/plugin-config.test.ts index 47e1cf537..3d6c82030 100644 --- a/src/plugin-config.test.ts +++ b/src/plugin-config.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from "bun:test"; import { mergeConfigs, parseConfigPartially } from "./plugin-config"; -import { OhMyOpenCodeConfigSchema, type OhMyOpenCodeConfig } from "./config"; +import type { OhMyOpenAgentConfig } from "./config"; describe("mergeConfigs", () => { describe("categories merging", () => { @@ -19,7 +19,7 @@ describe("mergeConfigs", () => { model: "anthropic/claude-haiku-4-5", }, }, - } as OhMyOpenCodeConfig; + } as OhMyOpenAgentConfig; const override = { categories: { @@ -30,7 +30,7 @@ describe("mergeConfigs", () => { model: "google/gemini-3.1-pro", }, }, - } as unknown as OhMyOpenCodeConfig; + } as unknown as OhMyOpenAgentConfig; const result = mergeConfigs(base, override); @@ -45,7 +45,7 @@ describe("mergeConfigs", () => { }); it("should preserve base categories when override has no categories", () => { - const base: OhMyOpenCodeConfig = { + const base: OhMyOpenAgentConfig = { categories: { general: { model: "openai/gpt-5.4", @@ -53,7 +53,7 @@ describe("mergeConfigs", () => { }, }; - const override: OhMyOpenCodeConfig = {}; + const override: OhMyOpenAgentConfig = {}; const result = mergeConfigs(base, override); @@ -61,9 +61,9 @@ describe("mergeConfigs", () => { }); it("should use override categories when base has no categories", () => { - const base: OhMyOpenCodeConfig = {}; + const base: OhMyOpenAgentConfig = {}; - const override: OhMyOpenCodeConfig = { + const override: OhMyOpenAgentConfig = { categories: { general: { model: "openai/gpt-5.4", @@ -79,13 +79,13 @@ describe("mergeConfigs", () => { describe("existing behavior preservation", () => { it("should deep merge agents", () => { - const base: OhMyOpenCodeConfig = { + const base: OhMyOpenAgentConfig = { agents: { oracle: { model: "openai/gpt-5.4" }, }, }; - const override: OhMyOpenCodeConfig = { + const override: OhMyOpenAgentConfig = { agents: { oracle: { temperature: 0.5 }, explore: { model: "anthropic/claude-haiku-4-5" }, @@ -94,17 +94,17 @@ describe("mergeConfigs", () => { const result = mergeConfigs(base, override); - expect(result.agents?.oracle).toMatchObject({ model: "openai/gpt-5.4" }); + expect(result.agents?.oracle?.model).toBe("openai/gpt-5.4"); expect(result.agents?.oracle?.temperature).toBe(0.5); - expect(result.agents?.explore).toMatchObject({ model: "anthropic/claude-haiku-4-5" }); + expect(result.agents?.explore?.model).toBe("anthropic/claude-haiku-4-5"); }); it("should merge disabled arrays without duplicates", () => { - const base: OhMyOpenCodeConfig = { + const base: OhMyOpenAgentConfig = { disabled_hooks: ["comment-checker", "think-mode"], }; - const override: OhMyOpenCodeConfig = { + const override: OhMyOpenAgentConfig = { disabled_hooks: ["think-mode", "session-recovery"], }; @@ -115,44 +115,10 @@ describe("mergeConfigs", () => { expect(result.disabled_hooks).toContain("session-recovery"); expect(result.disabled_hooks?.length).toBe(3); }); - - it("should union disabled_tools from base and override without duplicates", () => { - const base: OhMyOpenCodeConfig = { - disabled_tools: ["todowrite", "interactive_bash"], - }; - - const override: OhMyOpenCodeConfig = { - disabled_tools: ["interactive_bash", "look_at"], - }; - - const result = mergeConfigs(base, override); - - expect(result.disabled_tools).toContain("todowrite"); - expect(result.disabled_tools).toContain("interactive_bash"); - expect(result.disabled_tools).toContain("look_at"); - expect(result.disabled_tools?.length).toBe(3); - }); }); }); describe("parseConfigPartially", () => { - describe("disabled_hooks compatibility", () => { - //#given a config with a future hook name unknown to this version - //#when validating against the full config schema - //#then should accept the hook name so runtime and schema stay aligned - - it("should accept unknown disabled_hooks values for forward compatibility", () => { - const result = OhMyOpenCodeConfigSchema.safeParse({ - disabled_hooks: ["future-hook-name"], - }); - - expect(result.success).toBe(true); - if (result.success) { - expect(result.data.disabled_hooks).toEqual(["future-hook-name"]); - } - }); - }); - describe("fully valid config", () => { //#given a config where all sections are valid //#when parsing the config @@ -170,8 +136,8 @@ describe("parseConfigPartially", () => { const result = parseConfigPartially(rawConfig); expect(result).not.toBeNull(); - expect(result!.agents?.oracle).toMatchObject({ model: "openai/gpt-5.4" }); - expect(result!.agents?.momus).toMatchObject({ model: "openai/gpt-5.4" }); + expect(result!.agents?.oracle?.model).toBe("openai/gpt-5.4"); + expect(result!.agents?.momus?.model).toBe("openai/gpt-5.4"); expect(result!.disabled_hooks).toEqual(["comment-checker"]); }); }); @@ -213,7 +179,7 @@ describe("parseConfigPartially", () => { const result = parseConfigPartially(rawConfig); expect(result).not.toBeNull(); - expect(result!.agents?.oracle).toMatchObject({ model: "openai/gpt-5.4" }); + expect(result!.agents?.oracle?.model).toBe("openai/gpt-5.4"); expect(result!.disabled_hooks).toEqual(["not-a-real-hook"]); }); }); @@ -266,7 +232,7 @@ describe("parseConfigPartially", () => { const result = parseConfigPartially(rawConfig); expect(result).not.toBeNull(); - expect(result!.agents?.oracle).toMatchObject({ model: "openai/gpt-5.4" }); + expect(result!.agents?.oracle?.model).toBe("openai/gpt-5.4"); expect((result as Record)["some_future_key"]).toBeUndefined(); }); }); diff --git a/src/plugin-config.ts b/src/plugin-config.ts index c9f93f10f..a1154b853 100644 --- a/src/plugin-config.ts +++ b/src/plugin-config.ts @@ -1,6 +1,7 @@ +import { CONFIG_BASENAME } from "./shared/plugin-identity" import * as fs from "fs"; import * as path from "path"; -import { OhMyOpenCodeConfigSchema, type OhMyOpenCodeConfig } from "./config"; +import { OhMyOpenAgentConfigSchema, type OhMyOpenAgentConfig } from "./config"; import { log, deepMerge, @@ -22,8 +23,8 @@ const PARTIAL_STRING_ARRAY_KEYS = new Set([ export function parseConfigPartially( rawConfig: Record -): OhMyOpenCodeConfig | null { - const fullResult = OhMyOpenCodeConfigSchema.safeParse(rawConfig); +): OhMyOpenAgentConfig | null { + const fullResult = OhMyOpenAgentConfigSchema.safeParse(rawConfig); if (fullResult.success) { return fullResult.data; } @@ -40,7 +41,7 @@ export function parseConfigPartially( continue; } - const sectionResult = OhMyOpenCodeConfigSchema.safeParse({ [key]: rawConfig[key] }); + const sectionResult = OhMyOpenAgentConfigSchema.safeParse({ [key]: rawConfig[key] }); if (sectionResult.success) { const parsed = sectionResult.data as Record; if (parsed[key] !== undefined) { @@ -61,13 +62,13 @@ export function parseConfigPartially( log("Partial config loaded — invalid sections skipped:", invalidSections); } - return partialConfig as OhMyOpenCodeConfig; + return partialConfig as OhMyOpenAgentConfig; } export function loadConfigFromPath( configPath: string, _ctx: unknown -): OhMyOpenCodeConfig | null { +): OhMyOpenAgentConfig | null { try { if (fs.existsSync(configPath)) { const content = fs.readFileSync(configPath, "utf-8"); @@ -75,7 +76,7 @@ export function loadConfigFromPath( migrateConfigFile(configPath, rawConfig); - const result = OhMyOpenCodeConfigSchema.safeParse(rawConfig); + const result = OhMyOpenAgentConfigSchema.safeParse(rawConfig); if (result.success) { log(`Config loaded from ${configPath}`, { agents: result.data.agents }); @@ -108,9 +109,9 @@ export function loadConfigFromPath( } export function mergeConfigs( - base: OhMyOpenCodeConfig, - override: OhMyOpenCodeConfig -): OhMyOpenCodeConfig { + base: OhMyOpenAgentConfig, + override: OhMyOpenAgentConfig +): OhMyOpenAgentConfig { return { ...base, ...override, @@ -159,10 +160,10 @@ export function mergeConfigs( export function loadPluginConfig( directory: string, ctx: unknown -): OhMyOpenCodeConfig { +): OhMyOpenAgentConfig { // User-level config path - prefer .jsonc over .json const configDir = getOpenCodeConfigDir({ binary: "opencode" }); - const userBasePath = path.join(configDir, "oh-my-opencode"); + const userBasePath = path.join(configDir, CONFIG_BASENAME); const userDetected = detectConfigFile(userBasePath); const userConfigPath = userDetected.format !== "none" @@ -170,7 +171,7 @@ export function loadPluginConfig( : userBasePath + ".json"; // Project-level config path - prefer .jsonc over .json - const projectBasePath = path.join(directory, ".opencode", "oh-my-opencode"); + const projectBasePath = path.join(directory, ".opencode", CONFIG_BASENAME); const projectDetected = detectConfigFile(projectBasePath); const projectConfigPath = projectDetected.format !== "none" @@ -178,7 +179,7 @@ export function loadPluginConfig( : projectBasePath + ".json"; // Load user config first (base) - let config: OhMyOpenCodeConfig = + let config: OhMyOpenAgentConfig = loadConfigFromPath(userConfigPath, ctx) ?? {}; // Override with project config diff --git a/src/plugin-handlers/agent-config-handler.test.ts b/src/plugin-handlers/agent-config-handler.test.ts index d0d01a897..d51578b08 100644 --- a/src/plugin-handlers/agent-config-handler.test.ts +++ b/src/plugin-handlers/agent-config-handler.test.ts @@ -5,7 +5,7 @@ import { afterEach, beforeEach, describe, expect, spyOn, test } from "bun:test" import * as agents from "../agents" import * as shared from "../shared" import * as sisyphusJunior from "../agents/sisyphus-junior" -import type { OhMyOpenCodeConfig } from "../config" +import type { OhMyOpenAgentConfig } from "../config" import * as agentLoader from "../features/claude-code-agent-loader" import * as skillLoader from "../features/opencode-skill-loader" import { getAgentDisplayName } from "../shared/agent-display-names" @@ -35,13 +35,11 @@ function createBaseConfig(): Record { } } -function createPluginConfig(): OhMyOpenCodeConfig { - return { - sisyphus_agent: { - planner_enabled: false, - }, - } -} +function createPluginConfig(): OhMyOpenAgentConfig { return { + sisyphus_agent: { + planner_enabled: false, + }, +} } describe("applyAgentConfig builtin override protection", () => { let createBuiltinAgentsSpy: ReturnType diff --git a/src/plugin-handlers/agent-config-handler.ts b/src/plugin-handlers/agent-config-handler.ts index de316ffb7..54f7812bf 100644 --- a/src/plugin-handlers/agent-config-handler.ts +++ b/src/plugin-handlers/agent-config-handler.ts @@ -1,6 +1,6 @@ import { createBuiltinAgents } from "../agents"; import { createSisyphusJuniorAgentWithOverrides } from "../agents/sisyphus-junior"; -import type { OhMyOpenCodeConfig } from "../config"; +import type { OhMyOpenAgentConfig } from "../config"; import { log, migrateAgentConfig } from "../shared"; import { AGENT_NAME_MAP } from "../shared/migration"; import { getAgentDisplayName } from "../shared/agent-display-names"; @@ -37,7 +37,7 @@ function getConfiguredDefaultAgent(config: Record): string | un export async function applyAgentConfig(params: { config: Record; - pluginConfig: OhMyOpenCodeConfig; + pluginConfig: OhMyOpenAgentConfig; ctx: { directory: string; client?: any }; pluginComponents: PluginComponents; }): Promise> { diff --git a/src/plugin-handlers/command-config-handler.ts b/src/plugin-handlers/command-config-handler.ts index a5cb0e946..d96fae329 100644 --- a/src/plugin-handlers/command-config-handler.ts +++ b/src/plugin-handlers/command-config-handler.ts @@ -1,4 +1,4 @@ -import type { OhMyOpenCodeConfig } from "../config"; +import type { OhMyOpenAgentConfig } from "../config"; import { getAgentDisplayName } from "../shared/agent-display-names"; import { loadUserCommands, @@ -19,7 +19,7 @@ import type { PluginComponents } from "./plugin-components-loader"; export async function applyCommandConfig(params: { config: Record; - pluginConfig: OhMyOpenCodeConfig; + pluginConfig: OhMyOpenAgentConfig; ctx: { directory: string }; pluginComponents: PluginComponents; }): Promise { diff --git a/src/plugin-handlers/config-handler-formatter.test.ts b/src/plugin-handlers/config-handler-formatter.test.ts index d8fb8494f..5a79778ed 100644 --- a/src/plugin-handlers/config-handler-formatter.test.ts +++ b/src/plugin-handlers/config-handler-formatter.test.ts @@ -1,6 +1,6 @@ import { afterEach, beforeEach, describe, expect, spyOn, test } from "bun:test" -import type { OhMyOpenCodeConfig } from "../config" +import type { OhMyOpenAgentConfig } from "../config" import { createConfigHandler } from "./config-handler" import * as agentConfigHandler from "./agent-config-handler" import * as commandConfigHandler from "./command-config-handler" @@ -62,7 +62,7 @@ afterEach(() => { describe("createConfigHandler formatter pass-through", () => { test("preserves formatter object configured in opencode config", async () => { // given - const pluginConfig: OhMyOpenCodeConfig = {} + const pluginConfig: OhMyOpenAgentConfig = {} const formatterConfig = { prettier: { command: ["prettier", "--write"], @@ -98,7 +98,7 @@ describe("createConfigHandler formatter pass-through", () => { test("preserves formatter=false configured in opencode config", async () => { // given - const pluginConfig: OhMyOpenCodeConfig = {} + const pluginConfig: OhMyOpenAgentConfig = {} const config: Record = { formatter: false, } diff --git a/src/plugin-handlers/config-handler.test.ts b/src/plugin-handlers/config-handler.test.ts index c3e7a91d8..d1af7965c 100644 --- a/src/plugin-handlers/config-handler.test.ts +++ b/src/plugin-handlers/config-handler.test.ts @@ -3,7 +3,7 @@ import { describe, test, expect, spyOn, beforeEach, afterEach } from "bun:test" import { resolveCategoryConfig, createConfigHandler } from "./config-handler" import type { CategoryConfig } from "../config/schema" -import type { OhMyOpenCodeConfig } from "../config" +import type { OhMyOpenAgentConfig } from "../config" import { getAgentDisplayName } from "../shared/agent-display-names" import * as agents from "../agents" @@ -105,7 +105,7 @@ afterEach(() => { describe("Sisyphus-Junior model inheritance", () => { test("does not inherit UI-selected model as system default", async () => { // #given - const pluginConfig: OhMyOpenCodeConfig = {} + const pluginConfig: OhMyOpenAgentConfig = {} const config: Record = { model: "opencode/kimi-k2.5-free", agent: {}, @@ -131,7 +131,7 @@ describe("Sisyphus-Junior model inheritance", () => { test("uses explicitly configured sisyphus-junior model", async () => { // #given - const pluginConfig: OhMyOpenCodeConfig = { + const pluginConfig: OhMyOpenAgentConfig = { agents: { "sisyphus-junior": { model: "openai/gpt-5.3-codex", @@ -174,7 +174,7 @@ describe("Plan agent demote behavior", () => { oracle: { name: "oracle", prompt: "test", mode: "subagent" }, atlas: { name: "atlas", prompt: "test", mode: "primary" }, }) - const pluginConfig: OhMyOpenCodeConfig = { + const pluginConfig: OhMyOpenAgentConfig = { sisyphus_agent: { planner_enabled: true, }, @@ -209,7 +209,7 @@ describe("Plan agent demote behavior", () => { test("plan agent should be demoted to subagent without inheriting prometheus prompt", async () => { // #given - const pluginConfig: OhMyOpenCodeConfig = { + const pluginConfig: OhMyOpenAgentConfig = { sisyphus_agent: { planner_enabled: true, replace_plan: true, @@ -247,7 +247,7 @@ describe("Plan agent demote behavior", () => { test("plan agent remains unchanged when planner is disabled", async () => { // #given - const pluginConfig: OhMyOpenCodeConfig = { + const pluginConfig: OhMyOpenAgentConfig = { sisyphus_agent: { planner_enabled: false, }, @@ -284,7 +284,7 @@ describe("Plan agent demote behavior", () => { test("prometheus should have mode 'all' to be callable via task", async () => { // given - const pluginConfig: OhMyOpenCodeConfig = { + const pluginConfig: OhMyOpenAgentConfig = { sisyphus_agent: { planner_enabled: true, }, @@ -324,7 +324,7 @@ describe("Agent permission defaults", () => { hephaestus: { name: "hephaestus", prompt: "test", mode: "primary" }, oracle: { name: "oracle", prompt: "test", mode: "subagent" }, }) - const pluginConfig: OhMyOpenCodeConfig = {} + const pluginConfig: OhMyOpenAgentConfig = {} const config: Record = { model: "anthropic/claude-opus-4-6", agent: {}, @@ -352,7 +352,7 @@ describe("Agent permission defaults", () => { describe("default_agent behavior with Sisyphus orchestration", () => { test("canonicalizes configured default_agent with surrounding whitespace", async () => { // given - const pluginConfig: OhMyOpenCodeConfig = {} + const pluginConfig: OhMyOpenAgentConfig = {} const config: Record = { model: "anthropic/claude-opus-4-6", default_agent: " hephaestus ", @@ -376,7 +376,7 @@ describe("default_agent behavior with Sisyphus orchestration", () => { test("canonicalizes configured default_agent when key uses mixed case", async () => { // given - const pluginConfig: OhMyOpenCodeConfig = {} + const pluginConfig: OhMyOpenAgentConfig = {} const config: Record = { model: "anthropic/claude-opus-4-6", default_agent: "HePhAeStUs", @@ -400,7 +400,7 @@ describe("default_agent behavior with Sisyphus orchestration", () => { test("canonicalizes configured default_agent key to display name", async () => { // #given - const pluginConfig: OhMyOpenCodeConfig = {} + const pluginConfig: OhMyOpenAgentConfig = {} const config: Record = { model: "anthropic/claude-opus-4-6", default_agent: "hephaestus", @@ -424,7 +424,7 @@ describe("default_agent behavior with Sisyphus orchestration", () => { test("preserves existing display-name default_agent", async () => { // #given - const pluginConfig: OhMyOpenCodeConfig = {} + const pluginConfig: OhMyOpenAgentConfig = {} const displayName = getAgentDisplayName("hephaestus") const config: Record = { model: "anthropic/claude-opus-4-6", @@ -449,7 +449,7 @@ describe("default_agent behavior with Sisyphus orchestration", () => { test("sets default_agent to sisyphus when missing", async () => { // #given - const pluginConfig: OhMyOpenCodeConfig = {} + const pluginConfig: OhMyOpenAgentConfig = {} const config: Record = { model: "anthropic/claude-opus-4-6", agent: {}, @@ -472,7 +472,7 @@ describe("default_agent behavior with Sisyphus orchestration", () => { test("sets default_agent to sisyphus when configured default_agent is empty after trim", async () => { // given - const pluginConfig: OhMyOpenCodeConfig = {} + const pluginConfig: OhMyOpenAgentConfig = {} const config: Record = { model: "anthropic/claude-opus-4-6", default_agent: " ", @@ -496,7 +496,7 @@ describe("default_agent behavior with Sisyphus orchestration", () => { test("preserves custom default_agent names while trimming whitespace", async () => { // given - const pluginConfig: OhMyOpenCodeConfig = {} + const pluginConfig: OhMyOpenAgentConfig = {} const config: Record = { model: "anthropic/claude-opus-4-6", default_agent: " Custom Agent ", @@ -520,7 +520,7 @@ describe("default_agent behavior with Sisyphus orchestration", () => { test("does not normalize configured default_agent when Sisyphus is disabled", async () => { // given - const pluginConfig: OhMyOpenCodeConfig = { + const pluginConfig: OhMyOpenAgentConfig = { sisyphus_agent: { disabled: true, }, @@ -650,7 +650,7 @@ describe("Prometheus category config resolution", () => { describe("Prometheus direct override priority over category", () => { test("direct reasoningEffort takes priority over category reasoningEffort", async () => { // given - category has reasoningEffort=xhigh, direct override says "low" - const pluginConfig: OhMyOpenCodeConfig = { + const pluginConfig: OhMyOpenAgentConfig = { sisyphus_agent: { planner_enabled: true, }, @@ -692,7 +692,7 @@ describe("Prometheus direct override priority over category", () => { test("category reasoningEffort applied when no direct override", async () => { // given - category has reasoningEffort but no direct override - const pluginConfig: OhMyOpenCodeConfig = { + const pluginConfig: OhMyOpenAgentConfig = { sisyphus_agent: { planner_enabled: true, }, @@ -733,7 +733,7 @@ describe("Prometheus direct override priority over category", () => { test("direct temperature takes priority over category temperature", async () => { // given - const pluginConfig: OhMyOpenCodeConfig = { + const pluginConfig: OhMyOpenAgentConfig = { sisyphus_agent: { planner_enabled: true, }, @@ -776,7 +776,7 @@ describe("Prometheus direct override priority over category", () => { test("prometheus prompt_append is appended to base prompt", async () => { // #given - prometheus override with prompt_append const customInstructions = "## Custom Project Rules\nUse max 2 commits." - const pluginConfig: OhMyOpenCodeConfig = { + const pluginConfig: OhMyOpenAgentConfig = { sisyphus_agent: { planner_enabled: true, }, @@ -820,7 +820,7 @@ describe("Plan agent model inheritance from prometheus", () => { provenance: "provider-fallback", variant: "max", }) - const pluginConfig: OhMyOpenCodeConfig = { + const pluginConfig: OhMyOpenAgentConfig = { sisyphus_agent: { planner_enabled: true, replace_plan: true, @@ -864,7 +864,7 @@ describe("Plan agent model inheritance from prometheus", () => { provenance: "override", variant: "high", }) - const pluginConfig: OhMyOpenCodeConfig = { + const pluginConfig: OhMyOpenAgentConfig = { sisyphus_agent: { planner_enabled: true, replace_plan: true, @@ -919,7 +919,7 @@ describe("Plan agent model inheritance from prometheus", () => { provenance: "provider-fallback", variant: "max", }) - const pluginConfig: OhMyOpenCodeConfig = { + const pluginConfig: OhMyOpenAgentConfig = { sisyphus_agent: { planner_enabled: true, replace_plan: true, @@ -962,7 +962,7 @@ describe("Plan agent model inheritance from prometheus", () => { provenance: "provider-fallback", variant: "max", }) - const pluginConfig: OhMyOpenCodeConfig = { + const pluginConfig: OhMyOpenAgentConfig = { sisyphus_agent: { planner_enabled: true, replace_plan: true, @@ -1001,7 +1001,7 @@ describe("Deadlock prevention - fetchAvailableModels must not receive client", ( // - Server waits for plugin init to complete before handling requests const fetchSpy = spyOn(shared, "fetchAvailableModels" as any).mockResolvedValue(new Set()) - const pluginConfig: OhMyOpenCodeConfig = { + const pluginConfig: OhMyOpenAgentConfig = { sisyphus_agent: { planner_enabled: true, }, @@ -1041,7 +1041,7 @@ describe("config-handler plugin loading error boundary (#1559)", () => { //#given ;(pluginLoader.loadAllPluginComponents as any).mockRestore?.() spyOn(pluginLoader, "loadAllPluginComponents" as any).mockRejectedValue(new Error("crash")) - const pluginConfig: OhMyOpenCodeConfig = {} + const pluginConfig: OhMyOpenAgentConfig = {} const config: Record = { model: "anthropic/claude-opus-4-6", agent: {}, @@ -1068,7 +1068,7 @@ describe("config-handler plugin loading error boundary (#1559)", () => { spyOn(pluginLoader, "loadAllPluginComponents" as any).mockImplementation( () => new Promise(() => {}) ) - const pluginConfig: OhMyOpenCodeConfig = { + const pluginConfig: OhMyOpenAgentConfig = { experimental: { plugin_load_timeout_ms: 100 }, } const config: Record = { @@ -1096,7 +1096,7 @@ describe("config-handler plugin loading error boundary (#1559)", () => { ;(pluginLoader.loadAllPluginComponents as any).mockRestore?.() spyOn(pluginLoader, "loadAllPluginComponents" as any).mockRejectedValue(new Error("crash")) const logSpy = shared.log as ReturnType - const pluginConfig: OhMyOpenCodeConfig = {} + const pluginConfig: OhMyOpenAgentConfig = {} const config: Record = { model: "anthropic/claude-opus-4-6", agent: {}, @@ -1133,7 +1133,7 @@ describe("config-handler plugin loading error boundary (#1559)", () => { plugins: [{ name: "test-plugin", version: "1.0.0" }], errors: [], }) - const pluginConfig: OhMyOpenCodeConfig = {} + const pluginConfig: OhMyOpenAgentConfig = {} const config: Record = { model: "anthropic/claude-opus-4-6", agent: {}, @@ -1179,7 +1179,7 @@ describe("per-agent todowrite/todoread deny when task_system enabled", () => { oracle: { name: "oracle", prompt: "test", mode: "subagent" }, }) - const pluginConfig: OhMyOpenCodeConfig = { + const pluginConfig: OhMyOpenAgentConfig = { experimental: { task_system: true }, } const config: Record = { @@ -1216,7 +1216,7 @@ describe("per-agent todowrite/todoread deny when task_system enabled", () => { hephaestus: { name: "hephaestus", prompt: "test", mode: "primary" }, }) - const pluginConfig: OhMyOpenCodeConfig = { + const pluginConfig: OhMyOpenAgentConfig = { experimental: { task_system: false }, } const config: Record = { @@ -1252,7 +1252,7 @@ describe("per-agent todowrite/todoread deny when task_system enabled", () => { sisyphus: { name: "sisyphus", prompt: "test", mode: "primary" }, }) - const pluginConfig: OhMyOpenCodeConfig = {} + const pluginConfig: OhMyOpenAgentConfig = {} const config: Record = { model: "anthropic/claude-opus-4-6", agent: {}, @@ -1287,7 +1287,7 @@ describe("disable_omo_env pass-through", () => { sisyphus: { name: "sisyphus", prompt: "without-env", mode: "primary" }, }) - const pluginConfig: OhMyOpenCodeConfig = { + const pluginConfig: OhMyOpenAgentConfig = { experimental: { disable_omo_env: true }, } const config: Record = { @@ -1323,7 +1323,7 @@ describe("disable_omo_env pass-through", () => { sisyphus: { name: "sisyphus", prompt: "with-env", mode: "primary" }, }) - const pluginConfig: OhMyOpenCodeConfig = {} + const pluginConfig: OhMyOpenAgentConfig = {} const config: Record = { model: "anthropic/claude-opus-4-6", agent: {}, diff --git a/src/plugin-handlers/config-handler.ts b/src/plugin-handlers/config-handler.ts index 47050300f..96820d7fb 100644 --- a/src/plugin-handlers/config-handler.ts +++ b/src/plugin-handlers/config-handler.ts @@ -1,4 +1,4 @@ -import type { OhMyOpenCodeConfig } from "../config"; +import type { OhMyOpenAgentConfig } from "../config"; import type { ModelCacheState } from "../plugin-state"; import { log } from "../shared"; import { applyAgentConfig } from "./agent-config-handler"; @@ -12,7 +12,7 @@ export { resolveCategoryConfig } from "./category-config-resolver"; export interface ConfigHandlerDeps { ctx: { directory: string; client?: any }; - pluginConfig: OhMyOpenCodeConfig; + pluginConfig: OhMyOpenAgentConfig; modelCacheState: ModelCacheState; } diff --git a/src/plugin-handlers/mcp-config-handler.test.ts b/src/plugin-handlers/mcp-config-handler.test.ts index 95f73fc0d..73273ff61 100644 --- a/src/plugin-handlers/mcp-config-handler.test.ts +++ b/src/plugin-handlers/mcp-config-handler.test.ts @@ -1,7 +1,7 @@ /// import { describe, test, expect, spyOn, beforeEach, afterEach } from "bun:test" -import type { OhMyOpenCodeConfig } from "../config" +import type { OhMyOpenAgentConfig } from "../config" import * as mcpLoader from "../features/claude-code-mcp-loader" import * as mcpModule from "../mcp" @@ -24,12 +24,10 @@ afterEach(() => { ;(shared.log as any)?.mockRestore?.() }) -function createPluginConfig(overrides: Partial = {}): OhMyOpenCodeConfig { - return { - disabled_mcps: [], - ...overrides, - } as OhMyOpenCodeConfig -} +function createPluginConfig(overrides: Partial = {}): OhMyOpenAgentConfig { return { + disabled_mcps: [], + ...overrides, +} as OhMyOpenAgentConfig } const EMPTY_PLUGIN_COMPONENTS = { commands: {}, diff --git a/src/plugin-handlers/mcp-config-handler.ts b/src/plugin-handlers/mcp-config-handler.ts index d4eef1ad7..2eda1e417 100644 --- a/src/plugin-handlers/mcp-config-handler.ts +++ b/src/plugin-handlers/mcp-config-handler.ts @@ -1,4 +1,4 @@ -import type { OhMyOpenCodeConfig } from "../config"; +import type { OhMyOpenAgentConfig } from "../config"; import { loadMcpConfigs } from "../features/claude-code-mcp-loader"; import { createBuiltinMcps } from "../mcp"; import type { PluginComponents } from "./plugin-components-loader"; @@ -27,7 +27,7 @@ function captureUserDisabledMcps( export async function applyMcpConfig(params: { config: Record; - pluginConfig: OhMyOpenCodeConfig; + pluginConfig: OhMyOpenAgentConfig; pluginComponents: PluginComponents; }): Promise { const disabledMcps = params.pluginConfig.disabled_mcps ?? []; diff --git a/src/plugin-handlers/plugin-components-loader.ts b/src/plugin-handlers/plugin-components-loader.ts index 7d122a39e..8a253bc31 100644 --- a/src/plugin-handlers/plugin-components-loader.ts +++ b/src/plugin-handlers/plugin-components-loader.ts @@ -1,4 +1,4 @@ -import type { OhMyOpenCodeConfig } from "../config"; +import type { OhMyOpenAgentConfig } from "../config"; import { loadAllPluginComponents } from "../features/claude-code-plugin-loader"; import { addConfigLoadError, log } from "../shared"; @@ -23,7 +23,7 @@ const EMPTY_PLUGIN_COMPONENTS: PluginComponents = { }; export async function loadPluginComponents(params: { - pluginConfig: OhMyOpenCodeConfig; + pluginConfig: OhMyOpenAgentConfig; }): Promise { const pluginsEnabled = params.pluginConfig.claude_code?.plugins ?? true; if (!pluginsEnabled) { diff --git a/src/plugin-handlers/tool-config-handler.test.ts b/src/plugin-handlers/tool-config-handler.test.ts index 0ef60d56f..a4f4ef318 100644 --- a/src/plugin-handlers/tool-config-handler.test.ts +++ b/src/plugin-handlers/tool-config-handler.test.ts @@ -1,6 +1,6 @@ import { describe, it, expect, beforeEach, afterEach } from "bun:test" import { applyToolConfig } from "./tool-config-handler" -import type { OhMyOpenCodeConfig } from "../config" +import type { OhMyOpenAgentConfig } from "../config" function createParams(overrides: { taskSystem?: boolean @@ -15,7 +15,7 @@ function createParams(overrides: { config: { tools: {}, permission: {} } as Record, pluginConfig: { experimental: { task_system: overrides.taskSystem ?? false }, - } as OhMyOpenCodeConfig, + } as OhMyOpenAgentConfig, agentResult: agentResult as Record, } } diff --git a/src/plugin-handlers/tool-config-handler.ts b/src/plugin-handlers/tool-config-handler.ts index a4486677c..6ab836a3d 100644 --- a/src/plugin-handlers/tool-config-handler.ts +++ b/src/plugin-handlers/tool-config-handler.ts @@ -1,4 +1,4 @@ -import type { OhMyOpenCodeConfig } from "../config"; +import type { OhMyOpenAgentConfig } from "../config"; import { getAgentDisplayName } from "../shared/agent-display-names"; type AgentWithPermission = { permission?: Record }; @@ -22,7 +22,7 @@ function agentByKey(agentResult: Record, key: string): AgentWit export function applyToolConfig(params: { config: Record; - pluginConfig: OhMyOpenCodeConfig; + pluginConfig: OhMyOpenAgentConfig; agentResult: Record; }): void { const denyTodoTools = params.pluginConfig.experimental?.task_system diff --git a/src/plugin-interface.ts b/src/plugin-interface.ts index b37c9d417..5203789ec 100644 --- a/src/plugin-interface.ts +++ b/src/plugin-interface.ts @@ -1,5 +1,5 @@ import type { PluginContext, PluginInterface, ToolsRecord } from "./plugin/types" -import type { OhMyOpenCodeConfig } from "./config" +import type { OhMyOpenAgentConfig } from "./config" import { createChatParamsHandler } from "./plugin/chat-params" import { createChatHeadersHandler } from "./plugin/chat-headers" @@ -15,7 +15,7 @@ import type { Managers } from "./create-managers" export function createPluginInterface(args: { ctx: PluginContext - pluginConfig: OhMyOpenCodeConfig + pluginConfig: OhMyOpenAgentConfig firstMessageVariantGate: { shouldOverride: (sessionID: string) => boolean markApplied: (sessionID: string) => void diff --git a/src/plugin/available-categories.ts b/src/plugin/available-categories.ts index dc51836d5..5dc421b56 100644 --- a/src/plugin/available-categories.ts +++ b/src/plugin/available-categories.ts @@ -1,24 +1,20 @@ import type { AvailableCategory } from "../agents/dynamic-agent-prompt-builder" -import type { OhMyOpenCodeConfig } from "../config" +import type { OhMyOpenAgentConfig } from "../config" import { CATEGORY_DESCRIPTIONS } from "../tools/delegate-task/constants" import { mergeCategories } from "../shared/merge-categories" -export function createAvailableCategories( - pluginConfig: OhMyOpenCodeConfig, -): AvailableCategory[] { - const categories = mergeCategories(pluginConfig.categories) +export function createAvailableCategories(pluginConfig: OhMyOpenAgentConfig): AvailableCategory[] { const categories = mergeCategories(pluginConfig.categories) - return Object.entries(categories).map(([name, categoryConfig]) => { - const model = - typeof categoryConfig.model === "string" ? categoryConfig.model : undefined +return Object.entries(categories).map(([name, categoryConfig]) => { + const model = + typeof categoryConfig.model === "string" ? categoryConfig.model : undefined - return { - name, - description: - pluginConfig.categories?.[name]?.description ?? - CATEGORY_DESCRIPTIONS[name] ?? - "General tasks", - model, - } - }) -} + return { + name, + description: + pluginConfig.categories?.[name]?.description ?? + CATEGORY_DESCRIPTIONS[name] ?? + "General tasks", + model, + } +}) } diff --git a/src/plugin/chat-message.ts b/src/plugin/chat-message.ts index 750eaf667..f37c133c9 100644 --- a/src/plugin/chat-message.ts +++ b/src/plugin/chat-message.ts @@ -1,4 +1,4 @@ -import type { OhMyOpenCodeConfig } from "../config" +import type { OhMyOpenAgentConfig } from "../config" import type { PluginContext } from "./types" import { hasConnectedProvidersCache } from "../shared" @@ -37,7 +37,7 @@ function isStartWorkHookOutput(value: unknown): value is StartWorkHookOutput { export function createChatMessageHandler(args: { ctx: PluginContext - pluginConfig: OhMyOpenCodeConfig + pluginConfig: OhMyOpenAgentConfig firstMessageVariantGate: FirstMessageVariantGate hooks: CreatedHooks }): ( diff --git a/src/plugin/event.ts b/src/plugin/event.ts index 45765c025..3c60c35f2 100644 --- a/src/plugin/event.ts +++ b/src/plugin/event.ts @@ -1,4 +1,4 @@ -import type { OhMyOpenCodeConfig } from "../config"; +import type { OhMyOpenAgentConfig } from "../config"; import type { PluginContext } from "./types"; import { @@ -107,7 +107,7 @@ function applyUserConfiguredFallbackChain( sessionID: string, agentName: string, currentProviderID: string, - pluginConfig: OhMyOpenCodeConfig, + pluginConfig: OhMyOpenAgentConfig, ): void { const agentKey = getAgentConfigKey(agentName); const configuredFallbackModels = getFallbackModelsForSession(sessionID, agentKey, pluginConfig); @@ -127,7 +127,7 @@ function isCompactionAgent(agent: string): boolean { type EventInput = Parameters["event"]>>[0]; export function createEventHandler(args: { ctx: PluginContext; - pluginConfig: OhMyOpenCodeConfig; + pluginConfig: OhMyOpenAgentConfig; firstMessageVariantGate: FirstMessageVariantGate; managers: Managers; hooks: CreatedHooks; diff --git a/src/plugin/hooks/create-continuation-hooks.ts b/src/plugin/hooks/create-continuation-hooks.ts index 5dee1724c..a27037b69 100644 --- a/src/plugin/hooks/create-continuation-hooks.ts +++ b/src/plugin/hooks/create-continuation-hooks.ts @@ -1,4 +1,4 @@ -import type { HookName, OhMyOpenCodeConfig } from "../../config" +import type { HookName, OhMyOpenAgentConfig } from "../../config" import type { BackgroundManager } from "../../features/background-agent" import type { PluginContext } from "../types" @@ -32,7 +32,7 @@ type SessionRecovery = { export function createContinuationHooks(args: { ctx: PluginContext - pluginConfig: OhMyOpenCodeConfig + pluginConfig: OhMyOpenAgentConfig isHookEnabled: (hookName: HookName) => boolean safeHookEnabled: boolean backgroundManager: BackgroundManager diff --git a/src/plugin/hooks/create-core-hooks.ts b/src/plugin/hooks/create-core-hooks.ts index 4bfd2b4b3..d7517e35a 100644 --- a/src/plugin/hooks/create-core-hooks.ts +++ b/src/plugin/hooks/create-core-hooks.ts @@ -1,4 +1,4 @@ -import type { HookName, OhMyOpenCodeConfig } from "../../config" +import type { HookName, OhMyOpenAgentConfig } from "../../config" import type { PluginContext } from "../types" import type { ModelCacheState } from "../../plugin-state" @@ -8,7 +8,7 @@ import { createTransformHooks } from "./create-transform-hooks" export function createCoreHooks(args: { ctx: PluginContext - pluginConfig: OhMyOpenCodeConfig + pluginConfig: OhMyOpenAgentConfig modelCacheState: ModelCacheState isHookEnabled: (hookName: HookName) => boolean safeHookEnabled: boolean diff --git a/src/plugin/hooks/create-session-hooks.ts b/src/plugin/hooks/create-session-hooks.ts index daa5e4ff5..cfd2d9721 100644 --- a/src/plugin/hooks/create-session-hooks.ts +++ b/src/plugin/hooks/create-session-hooks.ts @@ -1,4 +1,4 @@ -import type { OhMyOpenCodeConfig, HookName } from "../../config" +import type { OhMyOpenAgentConfig, HookName } from "../../config" import type { ModelCacheState } from "../../plugin-state" import type { PluginContext } from "../types" @@ -64,7 +64,7 @@ export type SessionHooks = { export function createSessionHooks(args: { ctx: PluginContext - pluginConfig: OhMyOpenCodeConfig + pluginConfig: OhMyOpenAgentConfig modelCacheState: ModelCacheState isHookEnabled: (hookName: HookName) => boolean safeHookEnabled: boolean diff --git a/src/plugin/hooks/create-skill-hooks.ts b/src/plugin/hooks/create-skill-hooks.ts index b0514d583..88557c508 100644 --- a/src/plugin/hooks/create-skill-hooks.ts +++ b/src/plugin/hooks/create-skill-hooks.ts @@ -1,5 +1,5 @@ import type { AvailableSkill } from "../../agents/dynamic-agent-prompt-builder" -import type { HookName, OhMyOpenCodeConfig } from "../../config" +import type { HookName, OhMyOpenAgentConfig } from "../../config" import type { LoadedSkill } from "../../features/opencode-skill-loader/types" import type { PluginContext } from "../types" @@ -13,7 +13,7 @@ export type SkillHooks = { export function createSkillHooks(args: { ctx: PluginContext - pluginConfig: OhMyOpenCodeConfig + pluginConfig: OhMyOpenAgentConfig isHookEnabled: (hookName: HookName) => boolean safeHookEnabled: boolean mergedSkills: LoadedSkill[] diff --git a/src/plugin/hooks/create-tool-guard-hooks.ts b/src/plugin/hooks/create-tool-guard-hooks.ts index 1c79f6949..135b35cf1 100644 --- a/src/plugin/hooks/create-tool-guard-hooks.ts +++ b/src/plugin/hooks/create-tool-guard-hooks.ts @@ -1,4 +1,4 @@ -import type { HookName, OhMyOpenCodeConfig } from "../../config" +import type { HookName, OhMyOpenAgentConfig } from "../../config" import type { ModelCacheState } from "../../plugin-state" import type { PluginContext } from "../types" @@ -41,7 +41,7 @@ export type ToolGuardHooks = { export function createToolGuardHooks(args: { ctx: PluginContext - pluginConfig: OhMyOpenCodeConfig + pluginConfig: OhMyOpenAgentConfig modelCacheState: ModelCacheState isHookEnabled: (hookName: HookName) => boolean safeHookEnabled: boolean diff --git a/src/plugin/hooks/create-transform-hooks.ts b/src/plugin/hooks/create-transform-hooks.ts index d593efae7..00b6f958c 100644 --- a/src/plugin/hooks/create-transform-hooks.ts +++ b/src/plugin/hooks/create-transform-hooks.ts @@ -1,4 +1,4 @@ -import type { OhMyOpenCodeConfig } from "../../config" +import type { OhMyOpenAgentConfig } from "../../config" import type { PluginContext } from "../types" import { @@ -21,7 +21,7 @@ export type TransformHooks = { export function createTransformHooks(args: { ctx: PluginContext - pluginConfig: OhMyOpenCodeConfig + pluginConfig: OhMyOpenAgentConfig isHookEnabled: (hookName: string) => boolean safeHookEnabled?: boolean }): TransformHooks { diff --git a/src/plugin/skill-context.test.ts b/src/plugin/skill-context.test.ts index 4c80b2b61..4ed493119 100644 --- a/src/plugin/skill-context.test.ts +++ b/src/plugin/skill-context.test.ts @@ -3,7 +3,7 @@ import { mkdirSync, rmSync, writeFileSync } from "node:fs" import { tmpdir } from "node:os" import { join } from "node:path" -import { OhMyOpenCodeConfigSchema } from "../config" +import { OhMyOpenAgentConfigSchema } from "../config" import * as mcpLoader from "../features/claude-code-mcp-loader" import * as skillLoader from "../features/opencode-skill-loader" import { createSkillContext } from "./skill-context" @@ -60,7 +60,7 @@ describe("createSkillContext", () => { "getSystemMcpServerNames", ).mockReturnValue(new Set()) - const pluginConfig = OhMyOpenCodeConfigSchema.parse({ + const pluginConfig = OhMyOpenAgentConfigSchema.parse({ browser_automation_engine: { provider: "agent-browser" }, }) diff --git a/src/plugin/skill-context.ts b/src/plugin/skill-context.ts index 05a72d688..1f2bf5634 100644 --- a/src/plugin/skill-context.ts +++ b/src/plugin/skill-context.ts @@ -1,5 +1,5 @@ import type { AvailableSkill } from "../agents/dynamic-agent-prompt-builder" -import type { OhMyOpenCodeConfig } from "../config" +import type { OhMyOpenAgentConfig } from "../config" import type { BrowserAutomationProvider } from "../config/schema/browser-automation" import type { LoadedSkill, @@ -49,7 +49,7 @@ function filterProviderGatedSkills( export async function createSkillContext(args: { directory: string - pluginConfig: OhMyOpenCodeConfig + pluginConfig: OhMyOpenAgentConfig }): Promise { const { directory, pluginConfig } = args diff --git a/src/plugin/tool-registry.ts b/src/plugin/tool-registry.ts index f58053801..a3fd1a980 100644 --- a/src/plugin/tool-registry.ts +++ b/src/plugin/tool-registry.ts @@ -3,7 +3,7 @@ import type { ToolDefinition } from "@opencode-ai/plugin" import type { AvailableCategory, } from "../agents/dynamic-agent-prompt-builder" -import type { OhMyOpenCodeConfig } from "../config" +import type { OhMyOpenAgentConfig } from "../config" import type { PluginContext, ToolsRecord } from "./types" import { @@ -41,7 +41,7 @@ export type ToolRegistryResult = { export function createToolRegistry(args: { ctx: PluginContext - pluginConfig: OhMyOpenCodeConfig + pluginConfig: OhMyOpenAgentConfig managers: Pick skillContext: SkillContext availableCategories: AvailableCategory[] diff --git a/src/plugin/ultrawork-model-override.ts b/src/plugin/ultrawork-model-override.ts index 282c86142..5d8d0b553 100644 --- a/src/plugin/ultrawork-model-override.ts +++ b/src/plugin/ultrawork-model-override.ts @@ -1,4 +1,4 @@ -import type { OhMyOpenCodeConfig } from "../config" +import type { OhMyOpenAgentConfig } from "../config" import type { AgentOverrides } from "../config/schema/agent-overrides" import { getSessionAgent } from "../features/claude-code-session-state" import { log } from "../shared" @@ -58,7 +58,7 @@ function getMessageModel(current: unknown): ModelDescriptor | undefined { } export function resolveUltraworkOverride( - pluginConfig: OhMyOpenCodeConfig, + pluginConfig: OhMyOpenAgentConfig, inputAgentName: string | undefined, output: { message: Record @@ -146,7 +146,7 @@ function applyResolvedUltraworkOverride(args: { } export function applyUltraworkModelOverrideOnMessage( - pluginConfig: OhMyOpenCodeConfig, + pluginConfig: OhMyOpenAgentConfig, inputAgentName: string | undefined, output: { message: Record diff --git a/src/plugin/unstable-agent-babysitter.ts b/src/plugin/unstable-agent-babysitter.ts index 6ab73bbd8..f9061f16f 100644 --- a/src/plugin/unstable-agent-babysitter.ts +++ b/src/plugin/unstable-agent-babysitter.ts @@ -1,4 +1,4 @@ -import type { OhMyOpenCodeConfig } from "../config" +import type { OhMyOpenAgentConfig } from "../config" import type { PluginContext } from "./types" import { createUnstableAgentBabysitterHook } from "../hooks" @@ -7,7 +7,7 @@ import type { BackgroundManager } from "../features/background-agent" export function createUnstableAgentBabysitter(args: { ctx: PluginContext backgroundManager: BackgroundManager - pluginConfig: OhMyOpenCodeConfig + pluginConfig: OhMyOpenAgentConfig }) { const { ctx, backgroundManager, pluginConfig } = args diff --git a/src/shared/agent-variant.test.ts b/src/shared/agent-variant.test.ts index 95f501c54..0c67ad1f1 100644 --- a/src/shared/agent-variant.test.ts +++ b/src/shared/agent-variant.test.ts @@ -1,11 +1,11 @@ import { describe, expect, test } from "bun:test" -import type { OhMyOpenCodeConfig } from "../config" +import type { OhMyOpenAgentConfig } from "../config" import { applyAgentVariant, resolveAgentVariant, resolveVariantForModel } from "./agent-variant" describe("resolveAgentVariant", () => { test("returns undefined when agent name missing", () => { // given - const config = {} as OhMyOpenCodeConfig + const config = {} as OhMyOpenAgentConfig // when const variant = resolveAgentVariant(config) @@ -20,7 +20,7 @@ describe("resolveAgentVariant", () => { agents: { sisyphus: { variant: "low" }, }, - } as OhMyOpenCodeConfig + } as OhMyOpenAgentConfig // when const variant = resolveAgentVariant(config, "sisyphus") @@ -38,7 +38,7 @@ describe("resolveAgentVariant", () => { categories: { ultrabrain: { model: "openai/gpt-5.4", variant: "xhigh" }, }, - } as OhMyOpenCodeConfig + } as OhMyOpenAgentConfig // when const variant = resolveAgentVariant(config, "sisyphus") @@ -55,7 +55,7 @@ describe("applyAgentVariant", () => { agents: { sisyphus: { variant: "low" }, }, - } as OhMyOpenCodeConfig + } as OhMyOpenAgentConfig const message: { variant?: string } = {} // when @@ -71,7 +71,7 @@ describe("applyAgentVariant", () => { agents: { sisyphus: { variant: "low" }, }, - } as OhMyOpenCodeConfig + } as OhMyOpenAgentConfig const message = { variant: "max" } // when @@ -90,7 +90,7 @@ describe("resolveVariantForModel", () => { agents: { sisyphus: { variant: "high" }, }, - } as OhMyOpenCodeConfig + } as OhMyOpenAgentConfig const model = { providerID: "anthropic", modelID: "claude-opus-4-6" } // when @@ -102,7 +102,7 @@ describe("resolveVariantForModel", () => { test("returns correct variant for anthropic provider", () => { // given - const config = {} as OhMyOpenCodeConfig + const config = {} as OhMyOpenAgentConfig const model = { providerID: "anthropic", modelID: "claude-opus-4-6" } // when @@ -114,7 +114,7 @@ describe("resolveVariantForModel", () => { test("returns correct variant for openai provider (hephaestus agent)", () => { // #given hephaestus has openai/gpt-5.3-codex with variant "medium" in its chain - const config = {} as OhMyOpenCodeConfig + const config = {} as OhMyOpenAgentConfig const model = { providerID: "openai", modelID: "gpt-5.3-codex" } // #when @@ -126,7 +126,7 @@ describe("resolveVariantForModel", () => { test("returns medium for openai/gpt-5.4 in sisyphus chain", () => { // #given openai/gpt-5.4 is now in sisyphus fallback chain with variant medium - const config = {} as OhMyOpenCodeConfig + const config = {} as OhMyOpenAgentConfig const model = { providerID: "openai", modelID: "gpt-5.4" } // when @@ -138,7 +138,7 @@ describe("resolveVariantForModel", () => { test("returns undefined for provider not in chain", () => { // given - const config = {} as OhMyOpenCodeConfig + const config = {} as OhMyOpenAgentConfig const model = { providerID: "unknown-provider", modelID: "some-model" } // when @@ -150,7 +150,7 @@ describe("resolveVariantForModel", () => { test("returns undefined for unknown agent", () => { // given - const config = {} as OhMyOpenCodeConfig + const config = {} as OhMyOpenAgentConfig const model = { providerID: "anthropic", modelID: "claude-opus-4-6" } // when @@ -162,7 +162,7 @@ describe("resolveVariantForModel", () => { test("returns variant for zai-coding-plan provider without variant", () => { // given - const config = {} as OhMyOpenCodeConfig + const config = {} as OhMyOpenAgentConfig const model = { providerID: "zai-coding-plan", modelID: "glm-5" } // when @@ -178,7 +178,7 @@ describe("resolveVariantForModel", () => { agents: { "custom-agent": { category: "ultrabrain" }, }, - } as OhMyOpenCodeConfig + } as OhMyOpenAgentConfig const model = { providerID: "openai", modelID: "gpt-5.4" } // when @@ -190,7 +190,7 @@ describe("resolveVariantForModel", () => { test("returns correct variant for oracle agent with openai", () => { // given - const config = {} as OhMyOpenCodeConfig + const config = {} as OhMyOpenAgentConfig const model = { providerID: "openai", modelID: "gpt-5.4" } // when @@ -202,7 +202,7 @@ describe("resolveVariantForModel", () => { test("returns correct variant for oracle agent with anthropic", () => { // given - const config = {} as OhMyOpenCodeConfig + const config = {} as OhMyOpenAgentConfig const model = { providerID: "anthropic", modelID: "claude-opus-4-6" } // when diff --git a/src/shared/agent-variant.ts b/src/shared/agent-variant.ts index 4551e3d3a..c613c323c 100644 --- a/src/shared/agent-variant.ts +++ b/src/shared/agent-variant.ts @@ -1,8 +1,8 @@ -import type { OhMyOpenCodeConfig } from "../config" +import type { OhMyOpenAgentConfig } from "../config" import { AGENT_MODEL_REQUIREMENTS, CATEGORY_MODEL_REQUIREMENTS } from "./model-requirements" export function resolveAgentVariant( - config: OhMyOpenCodeConfig, + config: OhMyOpenAgentConfig, agentName?: string ): string | undefined { if (!agentName) { @@ -33,7 +33,7 @@ export function resolveAgentVariant( } export function resolveVariantForModel( - config: OhMyOpenCodeConfig, + config: OhMyOpenAgentConfig, agentName: string, currentModel: { providerID: string; modelID: string }, ): string | undefined { @@ -87,7 +87,7 @@ function findVariantInChain( } export function applyAgentVariant( - config: OhMyOpenCodeConfig, + config: OhMyOpenAgentConfig, agentName: string | undefined, message: { variant?: string } ): void { diff --git a/src/tools/task/task-create.ts b/src/tools/task/task-create.ts index f1eb41888..81df200c2 100644 --- a/src/tools/task/task-create.ts +++ b/src/tools/task/task-create.ts @@ -1,7 +1,7 @@ import type { PluginInput } from "@opencode-ai/plugin"; import { tool, type ToolDefinition } from "@opencode-ai/plugin/tool"; import { join } from "path"; -import type { OhMyOpenCodeConfig } from "../../config/schema"; +import type { OhMyOpenAgentConfig } from "../../config/schema"; import type { TaskObject } from "./types"; import { TaskObjectSchema, TaskCreateInputSchema } from "./types"; import { @@ -13,7 +13,7 @@ import { import { syncTaskTodoUpdate } from "./todo-sync"; export function createTaskCreateTool( - config: Partial, + config: Partial, ctx?: PluginInput, ): ToolDefinition { return tool({ @@ -58,7 +58,7 @@ Calculate dependencies carefully to maximize parallel execution: async function handleCreate( args: Record, - config: Partial, + config: Partial, ctx: PluginInput | undefined, context: { sessionID: string }, ): Promise { diff --git a/src/tools/task/task-get.ts b/src/tools/task/task-get.ts index 4532d9d46..305bbd633 100644 --- a/src/tools/task/task-get.ts +++ b/src/tools/task/task-get.ts @@ -1,6 +1,6 @@ import { tool, type ToolDefinition } from "@opencode-ai/plugin/tool" import { join } from "path" -import type { OhMyOpenCodeConfig } from "../../config/schema" +import type { OhMyOpenAgentConfig } from "../../config/schema" import { TaskGetInputSchema, TaskObjectSchema } from "./types" import { getTaskDir, readJsonSafe } from "../../features/claude-tasks/storage" @@ -11,7 +11,7 @@ function parseTaskId(id: string): string | null { return id } -export function createTaskGetTool(config: Partial): ToolDefinition { +export function createTaskGetTool(config: Partial): ToolDefinition { return tool({ description: `Retrieve a task by ID. diff --git a/src/tools/task/task-list.ts b/src/tools/task/task-list.ts index 6582d4721..495ad2cf3 100644 --- a/src/tools/task/task-list.ts +++ b/src/tools/task/task-list.ts @@ -1,7 +1,7 @@ import { tool, type ToolDefinition } from "@opencode-ai/plugin/tool" import { join } from "path" import { existsSync, readdirSync } from "fs" -import type { OhMyOpenCodeConfig } from "../../config/schema" +import type { OhMyOpenAgentConfig } from "../../config/schema" import type { TaskObject, TaskStatus } from "./types" import { TaskObjectSchema } from "./types" import { readJsonSafe, getTaskDir } from "../../features/claude-tasks/storage" @@ -14,7 +14,7 @@ interface TaskSummary { blockedBy: string[] } -export function createTaskList(config: Partial): ToolDefinition { +export function createTaskList(config: Partial): ToolDefinition { return tool({ description: `List all active tasks with summary information. diff --git a/src/tools/task/task-update.ts b/src/tools/task/task-update.ts index b56bd9add..cffd9adbe 100644 --- a/src/tools/task/task-update.ts +++ b/src/tools/task/task-update.ts @@ -1,7 +1,7 @@ import type { PluginInput } from "@opencode-ai/plugin"; import { tool, type ToolDefinition } from "@opencode-ai/plugin/tool"; import { join } from "path"; -import type { OhMyOpenCodeConfig } from "../../config/schema"; +import type { OhMyOpenAgentConfig } from "../../config/schema"; import { TaskObjectSchema, TaskUpdateInputSchema } from "./types"; import { getTaskDir, @@ -19,7 +19,7 @@ function parseTaskId(id: string): string | null { } export function createTaskUpdateTool( - config: Partial, + config: Partial, ctx?: PluginInput, ): ToolDefinition { return tool({ @@ -70,7 +70,7 @@ Properly managed dependencies enable maximum parallel execution.`, async function handleUpdate( args: Record, - config: Partial, + config: Partial, ctx: PluginInput | undefined, context: { sessionID: string }, ): Promise {