feat: add Claude Code plugin support (#240)

This commit is contained in:
Lukin
2025-12-27 17:56:40 +08:00
committed by GitHub
parent 1fc7fe7122
commit 2246d1c5ef
18 changed files with 748 additions and 49 deletions

View File

@@ -1,6 +1,7 @@
import type { ToolDefinition } from "@opencode-ai/plugin"
import { ast_grep_search, ast_grep_replace } from "./tools"
export const builtinTools = {
export const builtinTools: Record<string, ToolDefinition> = {
ast_grep_search,
ast_grep_replace,
}

View File

@@ -1,4 +1,4 @@
import { tool } from "@opencode-ai/plugin/tool"
import { tool, type ToolDefinition } from "@opencode-ai/plugin/tool"
import { CLI_LANGUAGES } from "./constants"
import { runSg } from "./cli"
import { formatSearchResult, formatReplaceResult } from "./utils"
@@ -32,7 +32,7 @@ function getEmptyResultHint(pattern: string, lang: CliLanguage): string | null {
return null
}
export const ast_grep_search = tool({
export const ast_grep_search: ToolDefinition = tool({
description:
"Search code patterns across filesystem using AST-aware matching. Supports 25 languages. " +
"Use meta-variables: $VAR (single node), $$$ (multiple nodes). " +
@@ -75,7 +75,7 @@ export const ast_grep_search = tool({
},
})
export const ast_grep_replace = tool({
export const ast_grep_replace: ToolDefinition = tool({
description:
"Replace code patterns across filesystem with AST-aware rewriting. " +
"Dry-run by default. Use meta-variables in rewrite to preserve matched content. " +

View File

@@ -1,4 +1,4 @@
import { tool, type PluginInput } from "@opencode-ai/plugin"
import { tool, type PluginInput, type ToolDefinition } from "@opencode-ai/plugin"
import { existsSync, readdirSync } from "node:fs"
import { join } from "node:path"
import type { BackgroundManager, BackgroundTask } from "../../features/background-agent"
@@ -37,7 +37,7 @@ function formatDuration(start: Date, end?: Date): string {
}
}
export function createBackgroundTask(manager: BackgroundManager) {
export function createBackgroundTask(manager: BackgroundManager): ToolDefinition {
return tool({
description: BACKGROUND_TASK_DESCRIPTION,
args: {
@@ -217,7 +217,7 @@ Session ID: ${task.sessionID}
${textContent || "(No text output)"}`
}
export function createBackgroundOutput(manager: BackgroundManager, client: OpencodeClient) {
export function createBackgroundOutput(manager: BackgroundManager, client: OpencodeClient): ToolDefinition {
return tool({
description: BACKGROUND_OUTPUT_DESCRIPTION,
args: {
@@ -283,7 +283,7 @@ export function createBackgroundOutput(manager: BackgroundManager, client: Openc
})
}
export function createBackgroundCancel(manager: BackgroundManager, client: OpencodeClient) {
export function createBackgroundCancel(manager: BackgroundManager, client: OpencodeClient): ToolDefinition {
return tool({
description: BACKGROUND_CANCEL_DESCRIPTION,
args: {

View File

@@ -1,4 +1,4 @@
import { tool, type PluginInput } from "@opencode-ai/plugin"
import { tool, type PluginInput, type ToolDefinition } from "@opencode-ai/plugin"
import { ALLOWED_AGENTS, CALL_OMO_AGENT_DESCRIPTION } from "./constants"
import type { CallOmoAgentArgs } from "./types"
import type { BackgroundManager } from "../../features/background-agent"
@@ -7,7 +7,7 @@ import { log } from "../../shared/logger"
export function createCallOmoAgent(
ctx: PluginInput,
backgroundManager: BackgroundManager
) {
): ToolDefinition {
const agentDescriptions = ALLOWED_AGENTS.map(
(name) => `- ${name}: Specialized agent for ${name} tasks`
).join("\n")

View File

@@ -1,8 +1,8 @@
import { tool } from "@opencode-ai/plugin/tool"
import { tool, type ToolDefinition } from "@opencode-ai/plugin/tool"
import { runRgFiles } from "./cli"
import { formatGlobResult } from "./utils"
export const glob = tool({
export const glob: ToolDefinition = tool({
description:
"Fast file pattern matching tool with safety limits (60s timeout, 100 file limit). " +
"Supports glob patterns like \"**/*.js\" or \"src/**/*.ts\". " +

View File

@@ -1,8 +1,8 @@
import { tool } from "@opencode-ai/plugin/tool"
import { tool, type ToolDefinition } from "@opencode-ai/plugin/tool"
import { runRg } from "./cli"
import { formatGrepResult } from "./utils"
export const grep = tool({
export const grep: ToolDefinition = tool({
description:
"Fast content search tool with safety limits (60s timeout, 10MB output). " +
"Searches file contents using regular expressions. " +

View File

@@ -37,7 +37,7 @@ import {
createBackgroundCancel,
} from "./background-task"
import type { PluginInput } from "@opencode-ai/plugin"
import type { PluginInput, ToolDefinition } from "@opencode-ai/plugin"
import type { BackgroundManager } from "../features/background-agent"
type OpencodeClient = PluginInput["client"]
@@ -45,7 +45,7 @@ type OpencodeClient = PluginInput["client"]
export { createCallOmoAgent } from "./call-omo-agent"
export { createLookAt } from "./look-at"
export function createBackgroundTools(manager: BackgroundManager, client: OpencodeClient) {
export function createBackgroundTools(manager: BackgroundManager, client: OpencodeClient): Record<string, ToolDefinition> {
return {
background_task: createBackgroundTask(manager),
background_output: createBackgroundOutput(manager, client),
@@ -53,7 +53,7 @@ export function createBackgroundTools(manager: BackgroundManager, client: Openco
}
}
export const builtinTools = {
export const builtinTools: Record<string, ToolDefinition> = {
lsp_hover,
lsp_goto_definition,
lsp_find_references,

View File

@@ -1,4 +1,4 @@
import { tool } from "@opencode-ai/plugin/tool"
import { tool, type ToolDefinition } from "@opencode-ai/plugin/tool"
import { BLOCKED_TMUX_SUBCOMMANDS, DEFAULT_TIMEOUT_MS, INTERACTIVE_BASH_DESCRIPTION } from "./constants"
import { getCachedTmuxPath } from "./utils"
@@ -47,7 +47,7 @@ export function tokenizeCommand(cmd: string): string[] {
return tokens
}
export const interactive_bash = tool({
export const interactive_bash: ToolDefinition = tool({
description: INTERACTIVE_BASH_DESCRIPTION,
args: {
tmux_command: tool.schema.string().describe("The tmux command to execute (without 'tmux' prefix)"),

View File

@@ -1,5 +1,5 @@
import { extname, basename } from "node:path"
import { tool, type PluginInput } from "@opencode-ai/plugin"
import { tool, type PluginInput, type ToolDefinition } from "@opencode-ai/plugin"
import { LOOK_AT_DESCRIPTION, MULTIMODAL_LOOKER_AGENT } from "./constants"
import type { LookAtArgs } from "./types"
import { log } from "../../shared/logger"
@@ -28,7 +28,7 @@ function inferMimeType(filePath: string): string {
return mimeTypes[ext] || "application/octet-stream"
}
export function createLookAt(ctx: PluginInput) {
export function createLookAt(ctx: PluginInput): ToolDefinition {
return tool({
description: LOOK_AT_DESCRIPTION,
args: {

View File

@@ -1,4 +1,4 @@
import { tool } from "@opencode-ai/plugin/tool"
import { tool, type ToolDefinition } from "@opencode-ai/plugin/tool"
import { getAllServers } from "./config"
import {
DEFAULT_MAX_REFERENCES,
@@ -34,7 +34,7 @@ import type {
export const lsp_hover = tool({
export const lsp_hover: ToolDefinition = tool({
description: "Get type info, docs, and signature for a symbol at position.",
args: {
filePath: tool.schema.string(),
@@ -55,7 +55,7 @@ export const lsp_hover = tool({
},
})
export const lsp_goto_definition = tool({
export const lsp_goto_definition: ToolDefinition = tool({
description: "Jump to symbol definition. Find WHERE something is defined.",
args: {
filePath: tool.schema.string(),
@@ -92,7 +92,7 @@ export const lsp_goto_definition = tool({
},
})
export const lsp_find_references = tool({
export const lsp_find_references: ToolDefinition = tool({
description: "Find ALL usages/references of a symbol across the entire workspace.",
args: {
filePath: tool.schema.string(),
@@ -129,7 +129,7 @@ export const lsp_find_references = tool({
},
})
export const lsp_document_symbols = tool({
export const lsp_document_symbols: ToolDefinition = tool({
description: "Get hierarchical outline of all symbols in a file.",
args: {
filePath: tool.schema.string(),
@@ -167,7 +167,7 @@ export const lsp_document_symbols = tool({
},
})
export const lsp_workspace_symbols = tool({
export const lsp_workspace_symbols: ToolDefinition = tool({
description: "Search symbols by name across ENTIRE workspace.",
args: {
filePath: tool.schema.string(),
@@ -202,7 +202,7 @@ export const lsp_workspace_symbols = tool({
},
})
export const lsp_diagnostics = tool({
export const lsp_diagnostics: ToolDefinition = tool({
description: "Get errors, warnings, hints from language server BEFORE running build.",
args: {
filePath: tool.schema.string(),
@@ -249,7 +249,7 @@ export const lsp_diagnostics = tool({
},
})
export const lsp_servers = tool({
export const lsp_servers: ToolDefinition = tool({
description: "List available LSP servers and installation status.",
args: {},
execute: async (_args, context) => {
@@ -271,7 +271,7 @@ export const lsp_servers = tool({
},
})
export const lsp_prepare_rename = tool({
export const lsp_prepare_rename: ToolDefinition = tool({
description: "Check if rename is valid. Use BEFORE lsp_rename.",
args: {
filePath: tool.schema.string(),
@@ -295,7 +295,7 @@ export const lsp_prepare_rename = tool({
},
})
export const lsp_rename = tool({
export const lsp_rename: ToolDefinition = tool({
description: "Rename symbol across entire workspace. APPLIES changes to all files.",
args: {
filePath: tool.schema.string(),
@@ -318,7 +318,7 @@ export const lsp_rename = tool({
},
})
export const lsp_code_actions = tool({
export const lsp_code_actions: ToolDefinition = tool({
description: "Get available quick fixes, refactorings, and source actions (organize imports, fix all).",
args: {
filePath: tool.schema.string(),
@@ -362,7 +362,7 @@ export const lsp_code_actions = tool({
},
})
export const lsp_code_action_resolve = tool({
export const lsp_code_action_resolve: ToolDefinition = tool({
description: "Resolve and APPLY a code action from lsp_code_actions.",
args: {
filePath: tool.schema.string(),

View File

@@ -1,4 +1,4 @@
import { tool } from "@opencode-ai/plugin/tool"
import { tool, type ToolDefinition } from "@opencode-ai/plugin/tool"
import {
SESSION_LIST_DESCRIPTION,
SESSION_READ_DESCRIPTION,
@@ -9,7 +9,7 @@ import { getAllSessions, getSessionInfo, readSessionMessages, readSessionTodos,
import { filterSessionsByDate, formatSessionInfo, formatSessionList, formatSessionMessages, formatSearchResults, searchInSession } from "./utils"
import type { SessionListArgs, SessionReadArgs, SessionSearchArgs, SessionInfoArgs } from "./types"
export const session_list = tool({
export const session_list: ToolDefinition = tool({
description: SESSION_LIST_DESCRIPTION,
args: {
limit: tool.schema.number().optional().describe("Maximum number of sessions to return"),
@@ -35,7 +35,7 @@ export const session_list = tool({
},
})
export const session_read = tool({
export const session_read: ToolDefinition = tool({
description: SESSION_READ_DESCRIPTION,
args: {
session_id: tool.schema.string().describe("Session ID to read"),
@@ -64,7 +64,7 @@ export const session_read = tool({
},
})
export const session_search = tool({
export const session_search: ToolDefinition = tool({
description: SESSION_SEARCH_DESCRIPTION,
args: {
query: tool.schema.string().describe("Search query string"),
@@ -87,7 +87,7 @@ export const session_search = tool({
},
})
export const session_info = tool({
export const session_info: ToolDefinition = tool({
description: SESSION_INFO_DESCRIPTION,
args: {
session_id: tool.schema.string().describe("Session ID to inspect"),

View File

@@ -1,4 +1,4 @@
import { tool } from "@opencode-ai/plugin"
import { tool, type ToolDefinition } from "@opencode-ai/plugin"
import { existsSync, readdirSync, readFileSync } from "fs"
import { join, basename, dirname } from "path"
import { parseFrontmatter, resolveCommandsInText, resolveFileReferencesInText, sanitizeModelField } from "../../shared"
@@ -127,7 +127,7 @@ function formatCommandList(commands: CommandInfo[]): string {
return lines.join("\n")
}
export const slashcommand = tool({
export const slashcommand: ToolDefinition = tool({
description: `Execute a slash command within the main conversation.
When you use this tool, the slash command gets expanded to a full prompt that provides detailed instructions on how to complete the task.