| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- import type { Plugin } from '@opencode-ai/plugin';
- import { getAgentConfigs } from './agents';
- import { BackgroundTaskManager, TmuxSessionManager } from './background';
- import { loadPluginConfig, type TmuxConfig } from './config';
- import {
- createAutoUpdateCheckerHook,
- createPhaseReminderHook,
- createPostReadNudgeHook,
- } from './hooks';
- import { createBuiltinMcps } from './mcp';
- import {
- antigravity_quota,
- ast_grep_replace,
- ast_grep_search,
- createBackgroundTools,
- createSkillTools,
- grep,
- lsp_diagnostics,
- lsp_find_references,
- lsp_goto_definition,
- lsp_rename,
- SkillMcpManager,
- } from './tools';
- import { startTmuxCheck } from './utils';
- import { log } from './utils/logger';
- import { parseList } from './tools/skill/builtin';
- const OhMyOpenCodeLite: Plugin = async (ctx) => {
- const config = loadPluginConfig(ctx.directory);
- const agents = getAgentConfigs(config);
- // Parse tmux config with defaults
- const tmuxConfig: TmuxConfig = {
- enabled: config.tmux?.enabled ?? false,
- layout: config.tmux?.layout ?? 'main-vertical',
- main_pane_size: config.tmux?.main_pane_size ?? 60,
- };
- log('[plugin] initialized with tmux config', {
- tmuxConfig,
- rawTmuxConfig: config.tmux,
- directory: ctx.directory,
- });
- // Start background tmux check if enabled
- if (tmuxConfig.enabled) {
- startTmuxCheck();
- }
- const backgroundManager = new BackgroundTaskManager(ctx, tmuxConfig, config);
- const backgroundTools = createBackgroundTools(
- ctx,
- backgroundManager,
- tmuxConfig,
- config,
- );
- const mcps = createBuiltinMcps(config.disabled_mcps);
- const skillMcpManager = SkillMcpManager.getInstance();
- const skillTools = createSkillTools(skillMcpManager, config);
- // Initialize TmuxSessionManager to handle OpenCode's built-in Task tool sessions
- const tmuxSessionManager = new TmuxSessionManager(ctx, tmuxConfig);
- // Initialize auto-update checker hook
- const autoUpdateChecker = createAutoUpdateCheckerHook(ctx, {
- showStartupToast: true,
- autoUpdate: true,
- });
- // Initialize phase reminder hook for workflow compliance
- const phaseReminderHook = createPhaseReminderHook();
- // Initialize post-read nudge hook
- const postReadNudgeHook = createPostReadNudgeHook();
- return {
- name: 'oh-my-opencode-slim',
- agent: agents,
- tool: {
- ...backgroundTools,
- lsp_goto_definition,
- lsp_find_references,
- lsp_diagnostics,
- lsp_rename,
- grep,
- ast_grep_search,
- ast_grep_replace,
- antigravity_quota,
- ...skillTools,
- },
- mcp: mcps,
- config: async (opencodeConfig: Record<string, unknown>) => {
- (opencodeConfig as { default_agent?: string }).default_agent =
- 'orchestrator';
- // Merge Agent configs
- if (!opencodeConfig.agent) {
- opencodeConfig.agent = { ...agents };
- } else {
- Object.assign(opencodeConfig.agent, agents);
- }
- const configAgent = opencodeConfig.agent as Record<string, any>;
- // Merge MCP configs
- const configMcp = opencodeConfig.mcp as
- | Record<string, unknown>
- | undefined;
- if (!configMcp) {
- opencodeConfig.mcp = { ...mcps };
- } else {
- Object.assign(configMcp, mcps);
- }
- // Get all MCP names from our config
- const allMcpNames = Object.keys(mcps);
- // For each agent, create permission rules based on their mcps list
- for (const [agentName, agentConfig] of Object.entries(agents)) {
- const agentMcps = (agentConfig as { mcps?: string[] })?.mcps;
- if (!agentMcps) continue;
- // Get or create agent permission config
- if (!configAgent[agentName]) {
- configAgent[agentName] = { ...agentConfig };
- }
- const agentPermission = (configAgent[agentName].permission ?? {}) as Record<string, unknown>;
- // Parse mcps list with wildcard and exclusion support
- const allowedMcps = parseList(agentMcps, allMcpNames);
- // Create permission rules for each MCP
- // MCP tools are named as <server>_<tool>, so we use <server>_*
- for (const mcpName of allMcpNames) {
- const sanitizedMcpName = mcpName.replace(/[^a-zA-Z0-9_-]/g, '_');
- const permissionKey = `${sanitizedMcpName}_*`;
- const action = allowedMcps.includes(mcpName) ? 'allow' : 'deny';
- // Only set if not already defined by user
- if (!(permissionKey in agentPermission)) {
- agentPermission[permissionKey] = action;
- }
- }
- // Update agent config with permissions
- configAgent[agentName].permission = agentPermission;
- }
- },
- event: async (input) => {
- // Handle auto-update checking
- await autoUpdateChecker.event(input);
- // Handle tmux pane spawning for OpenCode's Task tool sessions
- await tmuxSessionManager.onSessionCreated(
- input.event as {
- type: string;
- properties?: {
- info?: { id?: string; parentID?: string; title?: string };
- };
- },
- );
- },
- // Inject phase reminder before sending to API (doesn't show in UI)
- 'experimental.chat.messages.transform':
- phaseReminderHook['experimental.chat.messages.transform'],
- // Nudge after file reads to encourage delegation
- 'tool.execute.after': postReadNudgeHook['tool.execute.after'],
- };
- };
- export default OhMyOpenCodeLite;
- export type {
- AgentName,
- AgentOverrideConfig,
- McpName,
- PluginConfig,
- TmuxConfig,
- TmuxLayout,
- } from './config';
- export type { RemoteMcpConfig } from './mcp';
|