import * as vscode from 'vscode'; import * as fs from 'fs'; import * as os from 'os'; import * as path from 'path'; import { createAgent, createCommand, createSnippet, deleteAgent, deleteCommand, deleteSnippet, getAgentSources, getCommandSources, getSnippet, updateAgent, updateCommand, updateSnippet, type AgentScope, type CommandScope, AGENT_SCOPE, COMMAND_SCOPE, discoverSkills, mergeDiscoveredSkills, getSkillSources, createSkill, updateSkill, deleteSkill, readSkillSupportingFile, writeSkillSupportingFile, deleteSkillSupportingFile, type SkillScope, type DiscoveredSkill, SKILL_SCOPE, listMcpConfigs, listPluginDirFiles, listPluginEntries, getPluginEntry, createPluginEntry, updatePluginEntry, deletePluginEntry, readPluginDirFile, writePluginDirFile, deletePluginDirFile, queryPluginRegistry, listSnippets, getMcpConfig, createMcpConfig, updateMcpConfig, deleteMcpConfig, expandSnippets, type SnippetScope, } from './opencodeConfig'; import { getSkillsCatalog, scanSkillsRepository as scanSkillsRepositoryFromGit, installSkillsFromRepository as installSkillsFromGit, type SkillsCatalogSourceConfig, } from './skillsCatalog'; import type { BridgeContext, BridgeResponse } from './bridge'; type BridgeMessageInput = { id: string; type: string; payload?: unknown; }; type ConfigRuntimeDeps = { readSettings: (ctx?: BridgeContext) => Record; persistSettings: (changes: Record, ctx?: BridgeContext) => Promise>; readMagicPromptOverrides: () => { version: number; overrides: Record }; saveMagicPromptOverride: (id: string, text: string) => Promise<{ version: number; overrides: Record }>; resetMagicPromptOverride: (id: string) => Promise<{ version: number; overrides: Record }>; resetAllMagicPromptOverrides: () => Promise<{ version: number; overrides: Record }>; fetchOpenCodeSkillsFromApi: (ctx: BridgeContext | undefined, workingDirectory?: string) => Promise; clientReloadDelayMs: number; }; const AGENTS_MD_PATH = path.join(os.homedir(), '.config', 'opencode', 'AGENTS.md'); const MAX_BEHAVIOR_PROMPT_SIZE = 1024 * 1024; const resolveWorkingDirectory = (ctx: BridgeContext | undefined, directory?: string): string | undefined => ( (typeof directory === 'string' && directory.trim()) ? directory.trim() : (ctx?.manager?.getWorkingDirectory() || vscode.workspace.workspaceFolders?.[0]?.uri.fsPath) ); const pluginMutationPayload = async ( ctx: BridgeContext | undefined, deps: ConfigRuntimeDeps, label: string, ) => { try { await ctx?.manager?.restart(); return { success: true, requiresReload: true, message: `${label}. Reloading interface…`, reloadDelayMs: deps.clientReloadDelayMs, reloadFailed: false, }; } catch (error) { return { success: true, requiresReload: false, message: `${label}, but OpenCode reload failed.`, reloadDelayMs: deps.clientReloadDelayMs, reloadFailed: true, warning: error instanceof Error ? error.message : String(error), }; } }; const parseSkillsCatalogSources = (settings: Record): SkillsCatalogSourceConfig[] => { const rawCatalogs = (settings as { skillCatalogs?: unknown }).skillCatalogs; if (!Array.isArray(rawCatalogs)) { return []; } return rawCatalogs .map((entry) => { if (!entry || typeof entry !== 'object') return null; const candidate = entry as Record; const id = typeof candidate.id === 'string' ? candidate.id.trim() : ''; const label = typeof candidate.label === 'string' ? candidate.label.trim() : ''; const source = typeof candidate.source === 'string' ? candidate.source.trim() : ''; const subpath = typeof candidate.subpath === 'string' ? candidate.subpath.trim() : ''; if (!id || !label || !source) return null; const normalized: SkillsCatalogSourceConfig = { id, label, description: source, source, ...(subpath ? { defaultSubpath: subpath } : {}), }; return normalized; }) .filter((value): value is SkillsCatalogSourceConfig => value !== null); }; const resolveDiscoveredSkills = async ( deps: ConfigRuntimeDeps, ctx: BridgeContext | undefined, workingDirectory?: string, ): Promise => mergeDiscoveredSkills( (await deps.fetchOpenCodeSkillsFromApi(ctx, workingDirectory)) || [], discoverSkills(workingDirectory), ); export async function handleConfigBridgeMessage( message: BridgeMessageInput, ctx: BridgeContext | undefined, deps: ConfigRuntimeDeps, ): Promise { const { id, type, payload } = message; switch (type) { case 'api:config/opencode-resolution:get': { const debugInfo = ctx?.manager?.getDebugInfo(); const configuredFromWorkspace = vscode.workspace.getConfiguration('openchamber').get('opencodeBinary'); const configured = typeof configuredFromWorkspace === 'string' && configuredFromWorkspace.trim().length > 0 ? configuredFromWorkspace.trim() : null; const resolved = debugInfo?.cliPath ?? null; const source = (() => { if (!resolved) return null; if (configured && configured === resolved) return 'settings'; const envBinary = typeof process.env.OPENCODE_BINARY === 'string' ? process.env.OPENCODE_BINARY.trim() : ''; if (envBinary && envBinary === resolved) return 'env'; return 'path'; })(); return { id, type, success: true, data: { configured, resolved, resolvedDir: resolved ? path.dirname(resolved) : null, source, detectedNow: resolved, detectedSourceNow: source, shim: null, viaWsl: false, wslBinary: null, wslPath: null, wslDistro: null, node: process.execPath || null, bun: null, }, }; } case 'api:config/settings:get': { const settings = deps.readSettings(ctx); return { id, type, success: true, data: settings }; } case 'api:config/settings:save': { const changes = (payload as Record) || {}; const updated = await deps.persistSettings(changes, ctx); return { id, type, success: true, data: updated }; } case 'api:behavior/agents-md:get': { try { const content = await fs.promises.readFile(AGENTS_MD_PATH, 'utf8'); return { id, type, success: true, data: { content, exists: true } }; } catch (error) { if ((error as NodeJS.ErrnoException)?.code === 'ENOENT') { return { id, type, success: true, data: { content: '', exists: false } }; } throw error; } } case 'api:behavior/agents-md:save': { const request = (payload || {}) as { content?: unknown }; const content = typeof request.content === 'string' ? request.content : ''; if (content.length > MAX_BEHAVIOR_PROMPT_SIZE) { return { id, type, success: false, error: `Content exceeds maximum size of ${MAX_BEHAVIOR_PROMPT_SIZE} bytes` }; } await fs.promises.mkdir(path.dirname(AGENTS_MD_PATH), { recursive: true }); await fs.promises.writeFile(AGENTS_MD_PATH, content, 'utf8'); await ctx?.manager?.restart(); return { id, type, success: true, data: { success: true } }; } case 'api:magic-prompts:get': { return { id, type, success: true, data: deps.readMagicPromptOverrides() }; } case 'api:magic-prompts:save': { const request = (payload || {}) as { id?: string; text?: string }; const promptId = typeof request.id === 'string' ? request.id : ''; if (!promptId) { return { id, type, success: false, error: 'Prompt id is required' }; } if (typeof request.text !== 'string') { return { id, type, success: false, error: 'Prompt text is required' }; } const data = await deps.saveMagicPromptOverride(promptId, request.text); return { id, type, success: true, data }; } case 'api:magic-prompts:reset': { const request = (payload || {}) as { id?: string }; const promptId = typeof request.id === 'string' ? request.id : ''; if (!promptId) { return { id, type, success: false, error: 'Prompt id is required' }; } const data = await deps.resetMagicPromptOverride(promptId); return { id, type, success: true, data }; } case 'api:magic-prompts:reset-all': { const data = await deps.resetAllMagicPromptOverrides(); return { id, type, success: true, data }; } case 'api:config/reload': { await ctx?.manager?.restart(); return { id, type, success: true, data: { restarted: true } }; } case 'api:config/agents': { const { method, name, body, directory } = (payload || {}) as { method?: string; name?: string; body?: Record; directory?: string; }; const agentName = typeof name === 'string' ? name.trim() : ''; if (!agentName) { return { id, type, success: false, error: 'Agent name is required' }; } const workingDirectory = resolveWorkingDirectory(ctx, directory); const normalizedMethod = typeof method === 'string' && method.trim() ? method.trim().toUpperCase() : 'GET'; if (normalizedMethod === 'GET') { const sources = getAgentSources(agentName, workingDirectory); const scope = sources.md.exists ? sources.md.scope : (sources.json.exists ? sources.json.scope : null); return { id, type, success: true, data: { name: agentName, sources, scope, isBuiltIn: !sources.md.exists && !sources.json.exists }, }; } if (normalizedMethod === 'POST') { const scopeValue = body?.scope as string | undefined; const scope: AgentScope | undefined = scopeValue === 'project' ? AGENT_SCOPE.PROJECT : scopeValue === 'user' ? AGENT_SCOPE.USER : undefined; createAgent(agentName, (body || {}) as Record, workingDirectory, scope); await ctx?.manager?.restart(); return { id, type, success: true, data: { success: true, requiresReload: true, message: `Agent ${agentName} created successfully. Reloading interface…`, reloadDelayMs: deps.clientReloadDelayMs, }, }; } if (normalizedMethod === 'PATCH') { updateAgent(agentName, (body || {}) as Record, workingDirectory); await ctx?.manager?.restart(); return { id, type, success: true, data: { success: true, requiresReload: true, message: `Agent ${agentName} updated successfully. Reloading interface…`, reloadDelayMs: deps.clientReloadDelayMs, }, }; } if (normalizedMethod === 'DELETE') { const scopeValue = body?.scope as string | undefined; const scope: AgentScope | undefined = scopeValue === 'project' ? AGENT_SCOPE.PROJECT : scopeValue === 'user' ? AGENT_SCOPE.USER : undefined; deleteAgent(agentName, workingDirectory, scope); await ctx?.manager?.restart(); return { id, type, success: true, data: { success: true, requiresReload: true, message: `Agent ${agentName} deleted successfully. Reloading interface…`, reloadDelayMs: deps.clientReloadDelayMs, }, }; } return { id, type, success: false, error: `Unsupported method: ${normalizedMethod}` }; } case 'api:config/commands': { const { method, name, body, directory } = (payload || {}) as { method?: string; name?: string; body?: Record; directory?: string; }; const commandName = typeof name === 'string' ? name.trim() : ''; if (!commandName) { return { id, type, success: false, error: 'Command name is required' }; } const workingDirectory = resolveWorkingDirectory(ctx, directory); const normalizedMethod = typeof method === 'string' && method.trim() ? method.trim().toUpperCase() : 'GET'; if (normalizedMethod === 'GET') { const sources = getCommandSources(commandName, workingDirectory); const scope = sources.md.exists ? sources.md.scope : (sources.json.exists ? sources.json.scope : null); return { id, type, success: true, data: { name: commandName, sources, scope, isBuiltIn: !sources.md.exists && !sources.json.exists }, }; } if (normalizedMethod === 'POST') { const scopeValue = body?.scope as string | undefined; const scope: CommandScope | undefined = scopeValue === 'project' ? COMMAND_SCOPE.PROJECT : scopeValue === 'user' ? COMMAND_SCOPE.USER : undefined; createCommand(commandName, (body || {}) as Record, workingDirectory, scope); await ctx?.manager?.restart(); return { id, type, success: true, data: { success: true, requiresReload: true, message: `Command ${commandName} created successfully. Reloading interface…`, reloadDelayMs: deps.clientReloadDelayMs, }, }; } if (normalizedMethod === 'PATCH') { updateCommand(commandName, (body || {}) as Record, workingDirectory); await ctx?.manager?.restart(); return { id, type, success: true, data: { success: true, requiresReload: true, message: `Command ${commandName} updated successfully. Reloading interface…`, reloadDelayMs: deps.clientReloadDelayMs, }, }; } if (normalizedMethod === 'DELETE') { deleteCommand(commandName, workingDirectory); await ctx?.manager?.restart(); return { id, type, success: true, data: { success: true, requiresReload: true, message: `Command ${commandName} deleted successfully. Reloading interface…`, reloadDelayMs: deps.clientReloadDelayMs, }, }; } return { id, type, success: false, error: `Unsupported method: ${normalizedMethod}` }; } case 'api:config/mcp': { const { method, name, body, directory } = (payload || {}) as { method?: string; name?: string; body?: Record; directory?: string; }; const normalizedMethod = typeof method === 'string' && method.trim() ? method.trim().toUpperCase() : 'GET'; const mcpName = typeof name === 'string' ? name.trim() : ''; const workingDirectory = resolveWorkingDirectory(ctx, directory); if (normalizedMethod === 'GET' && !mcpName) { const configs = listMcpConfigs(workingDirectory); return { id, type, success: true, data: configs }; } if (!mcpName) { return { id, type, success: false, error: 'MCP server name is required' }; } if (normalizedMethod === 'GET') { const config = getMcpConfig(mcpName, workingDirectory); if (!config) { return { id, type, success: false, error: `MCP server "${mcpName}" not found` }; } return { id, type, success: true, data: config }; } if (normalizedMethod === 'POST') { const scope = body?.scope as 'user' | 'project' | undefined; createMcpConfig(mcpName, (body || {}) as Record, workingDirectory, scope); await ctx?.manager?.restart(); return { id, type, success: true, data: { success: true, requiresReload: true, message: `MCP server "${mcpName}" created. Reloading interface…`, reloadDelayMs: deps.clientReloadDelayMs, }, }; } if (normalizedMethod === 'PATCH') { updateMcpConfig(mcpName, (body || {}) as Record, workingDirectory); await ctx?.manager?.restart(); return { id, type, success: true, data: { success: true, requiresReload: true, message: `MCP server "${mcpName}" updated. Reloading interface…`, reloadDelayMs: deps.clientReloadDelayMs, }, }; } if (normalizedMethod === 'DELETE') { deleteMcpConfig(mcpName, workingDirectory); await ctx?.manager?.restart(); return { id, type, success: true, data: { success: true, requiresReload: true, message: `MCP server "${mcpName}" deleted. Reloading interface…`, reloadDelayMs: deps.clientReloadDelayMs, }, }; } return { id, type, success: false, error: `Unsupported method: ${normalizedMethod}` }; } case 'api:config/plugins': { const { method, target, pluginId, body, directory, specs, refresh } = (payload || {}) as { method?: string; target?: 'list' | 'registry' | 'entry' | 'file'; pluginId?: string; body?: Record; directory?: string; specs?: string[]; refresh?: boolean; }; const normalizedMethod = typeof method === 'string' && method.trim() ? method.trim().toUpperCase() : 'GET'; const workingDirectory = resolveWorkingDirectory(ctx, directory); if ((target === 'list' || !target) && normalizedMethod === 'GET') { return { id, type, success: true, data: { entries: listPluginEntries(workingDirectory), files: listPluginDirFiles(workingDirectory), }, }; } if (target === 'registry' && normalizedMethod === 'GET') { const data = await queryPluginRegistry(Array.isArray(specs) ? specs : [], { refresh: refresh === true, workingDirectory, }); return { id, type, success: true, data }; } if (target === 'entry') { if (normalizedMethod === 'GET') { if (!pluginId) return { id, type, success: false, error: 'Plugin entry id is required' }; const entry = getPluginEntry(pluginId, workingDirectory); if (!entry) return { id, type, success: false, error: 'Plugin entry not found' }; return { id, type, success: true, data: entry }; } if (normalizedMethod === 'POST') { createPluginEntry(body || {}, workingDirectory); } else if (normalizedMethod === 'PATCH') { if (!pluginId) return { id, type, success: false, error: 'Plugin entry id is required' }; updatePluginEntry(pluginId, body || {}, workingDirectory); } else if (normalizedMethod === 'DELETE') { if (!pluginId) return { id, type, success: false, error: 'Plugin entry id is required' }; deletePluginEntry(pluginId, workingDirectory); } else { return { id, type, success: false, error: `Unsupported method: ${normalizedMethod}` }; } return { id, type, success: true, data: await pluginMutationPayload(ctx, deps, 'Plugin entry changed'), }; } if (target === 'file') { if (normalizedMethod === 'GET') { if (!pluginId) return { id, type, success: false, error: 'Plugin file id is required' }; const file = readPluginDirFile(pluginId, workingDirectory); if (!file) return { id, type, success: false, error: 'Plugin file not found' }; return { id, type, success: true, data: file }; } if (normalizedMethod === 'POST') { writePluginDirFile(body || {}, workingDirectory); } else if (normalizedMethod === 'PUT') { if (!pluginId) return { id, type, success: false, error: 'Plugin file id is required' }; const existing = readPluginDirFile(pluginId, workingDirectory); if (!existing) return { id, type, success: false, error: 'Plugin file not found' }; writePluginDirFile({ fileName: existing.fileName, scope: existing.scope, content: body?.content }, workingDirectory, { overwrite: true }); } else if (normalizedMethod === 'DELETE') { if (!pluginId) return { id, type, success: false, error: 'Plugin file id is required' }; deletePluginDirFile(pluginId, workingDirectory); } else { return { id, type, success: false, error: `Unsupported method: ${normalizedMethod}` }; } return { id, type, success: true, data: await pluginMutationPayload(ctx, deps, 'Plugin file changed'), }; } return { id, type, success: false, error: 'Unsupported plugin config request' }; } case 'api:config/snippets': { const { method, name, body, directory } = (payload || {}) as { method?: string; name?: string; body?: Record; directory?: string; }; const normalizedMethod = typeof method === 'string' && method.trim() ? method.trim().toUpperCase() : 'GET'; const snippetName = typeof name === 'string' ? name.trim() : ''; const workingDirectory = resolveWorkingDirectory(ctx, directory); if (normalizedMethod === 'GET' && !snippetName) { return { id, type, success: true, data: listSnippets(workingDirectory) }; } if (normalizedMethod === 'POST' && !snippetName) { return { id, type, success: true, data: { text: expandSnippets(typeof body?.text === 'string' ? body.text : '', workingDirectory) } }; } if (!snippetName) { return { id, type, success: false, error: 'Snippet name is required' }; } if (normalizedMethod === 'GET') { const snippet = getSnippet(snippetName, workingDirectory); if (!snippet) return { id, type, success: false, error: `Snippet "${snippetName}" not found` }; return { id, type, success: true, data: snippet }; } if (normalizedMethod === 'POST') { const scope = body?.scope === 'project' ? 'project' : 'global'; const snippet = createSnippet(snippetName, (body || {}) as Record, workingDirectory, scope as SnippetScope); return { id, type, success: true, data: { success: true, snippet } }; } if (normalizedMethod === 'PATCH') { const snippet = updateSnippet(snippetName, (body || {}) as Record, workingDirectory); return { id, type, success: true, data: { success: true, snippet } }; } if (normalizedMethod === 'DELETE') { deleteSnippet(snippetName, workingDirectory); return { id, type, success: true, data: { success: true } }; } return { id, type, success: false, error: `Unsupported method: ${normalizedMethod}` }; } case 'api:config/skills': { const { method, name, body } = (payload || {}) as { method?: string; name?: string; body?: Record }; const workingDirectory = ctx?.manager?.getWorkingDirectory() || vscode.workspace.workspaceFolders?.[0]?.uri.fsPath; const normalizedMethod = typeof method === 'string' && method.trim() ? method.trim().toUpperCase() : 'GET'; if (!name && normalizedMethod === 'GET') { const skills = await resolveDiscoveredSkills(deps, ctx, workingDirectory); return { id, type, success: true, data: { skills } }; } const skillName = typeof name === 'string' ? name.trim() : ''; if (!skillName) { return { id, type, success: false, error: 'Skill name is required' }; } if (normalizedMethod === 'GET') { const discoveredSkill = (await resolveDiscoveredSkills(deps, ctx, workingDirectory)) .find((skill) => skill.name === skillName); const sources = getSkillSources(skillName, workingDirectory, discoveredSkill || null); return { id, type, success: true, data: { name: skillName, sources, scope: sources.md.scope, source: sources.md.source }, }; } if (normalizedMethod === 'POST') { const scopeValue = body?.scope as string | undefined; const sourceValue = body?.source as string | undefined; const scope: SkillScope | undefined = scopeValue === 'project' ? SKILL_SCOPE.PROJECT : scopeValue === 'user' ? SKILL_SCOPE.USER : undefined; const normalizedSource = sourceValue === 'agents' ? 'agents' : 'opencode'; createSkill(skillName, { ...(body || {}), source: normalizedSource } as Record, workingDirectory, scope); await ctx?.manager?.restart(); return { id, type, success: true, data: { success: true, requiresReload: true, message: `Skill ${skillName} created successfully. Reloading interface…`, reloadDelayMs: deps.clientReloadDelayMs, }, }; } if (normalizedMethod === 'PATCH') { updateSkill(skillName, (body || {}) as Record, workingDirectory); await ctx?.manager?.restart(); return { id, type, success: true, data: { success: true, requiresReload: true, message: `Skill ${skillName} updated successfully. Reloading interface…`, reloadDelayMs: deps.clientReloadDelayMs, }, }; } if (normalizedMethod === 'DELETE') { deleteSkill(skillName, workingDirectory); await ctx?.manager?.restart(); return { id, type, success: true, data: { success: true, requiresReload: true, message: `Skill ${skillName} deleted successfully. Reloading interface…`, reloadDelayMs: deps.clientReloadDelayMs, }, }; } return { id, type, success: false, error: `Unsupported method: ${normalizedMethod}` }; } case 'api:config/skills:catalog': { const refresh = Boolean((payload as { refresh?: boolean } | undefined)?.refresh); const workingDirectory = ctx?.manager?.getWorkingDirectory() || vscode.workspace.workspaceFolders?.[0]?.uri.fsPath; const settings = deps.readSettings(ctx); const additionalSources = parseSkillsCatalogSources(settings); const installedSkills = await resolveDiscoveredSkills(deps, ctx, workingDirectory); const data = await getSkillsCatalog(workingDirectory, refresh, additionalSources, installedSkills); return { id, type, success: true, data }; } case 'api:config/skills:scan': { const body = (payload || {}) as { source?: string; subpath?: string; gitIdentityId?: string }; const data = await scanSkillsRepositoryFromGit({ source: String(body.source || ''), subpath: body.subpath, }); return { id, type, success: true, data }; } case 'api:config/skills:install': { const body = (payload || {}) as { source?: string; subpath?: string; scope?: 'user' | 'project'; targetSource?: 'opencode' | 'agents'; selections?: Array<{ skillDir: string }>; conflictPolicy?: 'prompt' | 'skipAll' | 'overwriteAll'; conflictDecisions?: Record; }; const workingDirectory = ctx?.manager?.getWorkingDirectory() || vscode.workspace.workspaceFolders?.[0]?.uri.fsPath; const data = await installSkillsFromGit({ source: String(body.source || ''), subpath: body.subpath, scope: body.scope === 'project' ? 'project' : 'user', targetSource: body.targetSource === 'agents' ? 'agents' : 'opencode', workingDirectory: body.scope === 'project' ? workingDirectory : undefined, selections: Array.isArray(body.selections) ? body.selections : [], conflictPolicy: body.conflictPolicy, conflictDecisions: body.conflictDecisions, }); if (data.ok) { const installed = data.installed || []; const skipped = data.skipped || []; const requiresReload = installed.length > 0; if (requiresReload) { await ctx?.manager?.restart(); } return { id, type, success: true, data: { ok: true, installed, skipped, requiresReload, message: requiresReload ? 'Skills installed successfully. Reloading interface…' : 'No skills were installed', reloadDelayMs: requiresReload ? deps.clientReloadDelayMs : undefined, }, }; } return { id, type, success: true, data }; } case 'api:config/skills/files': { const { method, name, filePath, content } = (payload || {}) as { method?: string; name?: string; filePath?: string; content?: string; }; const workingDirectory = ctx?.manager?.getWorkingDirectory() || vscode.workspace.workspaceFolders?.[0]?.uri.fsPath; const skillName = typeof name === 'string' ? name.trim() : ''; if (!skillName) { return { id, type, success: false, error: 'Skill name is required' }; } const relativePath = typeof filePath === 'string' ? filePath.trim() : ''; if (!relativePath) { return { id, type, success: false, error: 'File path is required' }; } const discoveredSkill = (await resolveDiscoveredSkills(deps, ctx, workingDirectory)) .find((skill) => skill.name === skillName); const sources = getSkillSources(skillName, workingDirectory, discoveredSkill || null); if (!sources.md.dir) { return { id, type, success: false, error: `Skill "${skillName}" not found` }; } const skillDir = sources.md.dir; const normalizedMethod = typeof method === 'string' && method.trim() ? method.trim().toUpperCase() : 'GET'; if (normalizedMethod === 'GET') { const fileContent = readSkillSupportingFile(skillDir, relativePath); if (fileContent === null) { return { id, type, success: false, error: `File "${relativePath}" not found in skill "${skillName}"` }; } return { id, type, success: true, data: { content: fileContent } }; } if (normalizedMethod === 'PUT') { writeSkillSupportingFile(skillDir, relativePath, content || ''); return { id, type, success: true, data: { success: true } }; } if (normalizedMethod === 'DELETE') { deleteSkillSupportingFile(skillDir, relativePath); return { id, type, success: true, data: { success: true } }; } return { id, type, success: false, error: `Unsupported method: ${normalizedMethod}` }; } default: return null; } }