2026-02-27 14:46:12 +00:00
|
|
|
import { initConfigContext } from "./cli/config-manager/config-context"
|
2026-02-08 16:25:25 +09:00
|
|
|
import type { Plugin } from "@opencode-ai/plugin"
|
|
|
|
|
|
|
|
|
|
import type { HookName } from "./config"
|
|
|
|
|
|
|
|
|
|
import { createHooks } from "./create-hooks"
|
|
|
|
|
import { createManagers } from "./create-managers"
|
|
|
|
|
import { createTools } from "./create-tools"
|
|
|
|
|
import { createPluginInterface } from "./plugin-interface"
|
|
|
|
|
|
|
|
|
|
import { loadPluginConfig } from "./plugin-config"
|
|
|
|
|
import { createModelCacheState } from "./plugin-state"
|
|
|
|
|
import { createFirstMessageVariantGate } from "./shared/first-message-variant"
|
|
|
|
|
import { injectServerAuthIntoClient, log } from "./shared"
|
|
|
|
|
import { startTmuxCheck } from "./tools"
|
2025-12-03 11:49:33 +09:00
|
|
|
|
|
|
|
|
const OhMyOpenCodePlugin: Plugin = async (ctx) => {
|
2026-02-27 14:46:12 +00:00
|
|
|
// Initialize config context for plugin runtime (prevents warnings from hooks)
|
|
|
|
|
initConfigContext("opencode", null)
|
2026-02-02 15:04:53 +09:00
|
|
|
log("[OhMyOpenCodePlugin] ENTRY - plugin loading", {
|
|
|
|
|
directory: ctx.directory,
|
2026-02-08 16:25:25 +09:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
injectServerAuthIntoClient(ctx.client)
|
|
|
|
|
startTmuxCheck()
|
2026-01-04 21:16:49 +09:00
|
|
|
|
2026-02-08 16:25:25 +09:00
|
|
|
const pluginConfig = loadPluginConfig(ctx.directory, ctx)
|
|
|
|
|
const disabledHooks = new Set(pluginConfig.disabled_hooks ?? [])
|
2026-02-06 17:36:40 +09:00
|
|
|
|
2026-02-08 16:25:25 +09:00
|
|
|
const isHookEnabled = (hookName: HookName): boolean => !disabledHooks.has(hookName)
|
|
|
|
|
const safeHookEnabled = pluginConfig.experimental?.safe_hook_creation ?? true
|
|
|
|
|
|
|
|
|
|
const firstMessageVariantGate = createFirstMessageVariantGate()
|
2026-01-25 15:34:10 +09:00
|
|
|
|
|
|
|
|
const tmuxConfig = {
|
|
|
|
|
enabled: pluginConfig.tmux?.enabled ?? false,
|
2026-02-02 15:04:53 +09:00
|
|
|
layout: pluginConfig.tmux?.layout ?? "main-vertical",
|
2026-01-25 15:34:10 +09:00
|
|
|
main_pane_size: pluginConfig.tmux?.main_pane_size ?? 60,
|
2026-01-26 12:02:37 +09:00
|
|
|
main_pane_min_width: pluginConfig.tmux?.main_pane_min_width ?? 120,
|
|
|
|
|
agent_pane_min_width: pluginConfig.tmux?.agent_pane_min_width ?? 40,
|
2026-01-07 11:44:03 -03:00
|
|
|
}
|
2025-12-13 11:48:22 +09:00
|
|
|
|
2026-02-08 16:25:25 +09:00
|
|
|
const modelCacheState = createModelCacheState()
|
2026-01-28 18:46:51 +09:00
|
|
|
|
2026-02-08 16:25:25 +09:00
|
|
|
const managers = createManagers({
|
2026-01-09 02:24:43 +09:00
|
|
|
ctx,
|
2026-01-02 11:35:56 +09:00
|
|
|
pluginConfig,
|
2026-02-08 16:25:25 +09:00
|
|
|
tmuxConfig,
|
2026-01-02 11:35:56 +09:00
|
|
|
modelCacheState,
|
2026-02-16 00:58:46 +02:00
|
|
|
backgroundNotificationHookEnabled: isHookEnabled("background-notification"),
|
2026-02-08 16:25:25 +09:00
|
|
|
})
|
2026-02-01 22:42:28 +09:00
|
|
|
|
2026-02-08 16:25:25 +09:00
|
|
|
const toolsResult = await createTools({
|
|
|
|
|
ctx,
|
|
|
|
|
pluginConfig,
|
|
|
|
|
managers,
|
|
|
|
|
})
|
2026-02-06 16:18:44 +09:00
|
|
|
|
2026-02-08 16:25:25 +09:00
|
|
|
const hooks = createHooks({
|
|
|
|
|
ctx,
|
|
|
|
|
pluginConfig,
|
2026-02-17 10:33:17 +09:00
|
|
|
modelCacheState,
|
2026-02-08 16:25:25 +09:00
|
|
|
backgroundManager: managers.backgroundManager,
|
|
|
|
|
isHookEnabled,
|
|
|
|
|
safeHookEnabled,
|
|
|
|
|
mergedSkills: toolsResult.mergedSkills,
|
|
|
|
|
availableSkills: toolsResult.availableSkills,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const pluginInterface = createPluginInterface({
|
|
|
|
|
ctx,
|
|
|
|
|
pluginConfig,
|
|
|
|
|
firstMessageVariantGate,
|
|
|
|
|
managers,
|
|
|
|
|
hooks,
|
|
|
|
|
tools: toolsResult.filteredTools,
|
|
|
|
|
})
|
2026-02-06 16:18:44 +09:00
|
|
|
|
2025-12-03 11:49:33 +09:00
|
|
|
return {
|
2026-02-08 16:25:25 +09:00
|
|
|
...pluginInterface,
|
2026-02-01 16:47:50 +09:00
|
|
|
|
2026-02-06 17:49:26 +09:00
|
|
|
"experimental.session.compacting": async (
|
|
|
|
|
_input: { sessionID: string },
|
|
|
|
|
output: { context: string[] },
|
|
|
|
|
): Promise<void> => {
|
2026-03-08 02:23:51 +09:00
|
|
|
await hooks.compactionContextInjector?.capture(_input.sessionID)
|
2026-02-08 16:25:25 +09:00
|
|
|
await hooks.compactionTodoPreserver?.capture(_input.sessionID)
|
2026-02-17 02:14:01 +09:00
|
|
|
await hooks.claudeCodeHooks?.["experimental.session.compacting"]?.(
|
|
|
|
|
_input,
|
|
|
|
|
output,
|
|
|
|
|
)
|
|
|
|
|
if (hooks.compactionContextInjector) {
|
2026-03-08 02:23:51 +09:00
|
|
|
output.context.push(hooks.compactionContextInjector.inject(_input.sessionID))
|
2026-02-01 16:47:50 +09:00
|
|
|
}
|
|
|
|
|
},
|
2026-02-08 16:25:25 +09:00
|
|
|
}
|
|
|
|
|
}
|
2025-12-03 11:49:33 +09:00
|
|
|
|
2026-02-08 16:25:25 +09:00
|
|
|
export default OhMyOpenCodePlugin
|
2025-12-05 02:32:33 +09:00
|
|
|
|
2025-12-05 02:54:09 +09:00
|
|
|
export type {
|
|
|
|
|
OhMyOpenCodeConfig,
|
|
|
|
|
AgentName,
|
|
|
|
|
AgentOverrideConfig,
|
|
|
|
|
AgentOverrides,
|
|
|
|
|
McpName,
|
2025-12-13 03:10:39 +00:00
|
|
|
HookName,
|
2025-12-28 17:30:27 +09:00
|
|
|
BuiltinCommandName,
|
2026-02-08 16:25:25 +09:00
|
|
|
} from "./config"
|
2025-12-19 02:19:54 +09:00
|
|
|
|
|
|
|
|
// NOTE: Do NOT export functions from main index.ts!
|
|
|
|
|
// OpenCode treats ALL exports as plugin instances and calls them.
|
|
|
|
|
// Config error utilities are available via "./shared/config-errors" for internal use only.
|
2026-02-08 16:25:25 +09:00
|
|
|
export type { ConfigLoadError } from "./shared/config-errors"
|