Plugins no longer receive shell access or server URL to prevent unauthorized execution and limit plugin sandbox surface area.
232 lines
6.1 KiB
TypeScript
232 lines
6.1 KiB
TypeScript
import type {
|
|
Event,
|
|
createOpencodeClient,
|
|
Project,
|
|
Model,
|
|
Provider,
|
|
Permission,
|
|
UserMessage,
|
|
Message,
|
|
Part,
|
|
Auth,
|
|
Config,
|
|
} from "@opencode-ai/sdk"
|
|
|
|
import { type ToolDefinition } from "./tool.js"
|
|
|
|
export * from "./tool.js"
|
|
|
|
export type ProviderContext = {
|
|
source: "env" | "config" | "custom" | "api"
|
|
info: Provider
|
|
options: Record<string, any>
|
|
}
|
|
|
|
export type PluginInput = {
|
|
client: ReturnType<typeof createOpencodeClient>
|
|
project: Project
|
|
directory: string
|
|
worktree: string
|
|
}
|
|
|
|
export type Plugin = (input: PluginInput) => Promise<Hooks>
|
|
|
|
export type AuthHook = {
|
|
provider: string
|
|
loader?: (auth: () => Promise<Auth>, provider: Provider) => Promise<Record<string, any>>
|
|
methods: (
|
|
| {
|
|
type: "oauth"
|
|
label: string
|
|
prompts?: Array<
|
|
| {
|
|
type: "text"
|
|
key: string
|
|
message: string
|
|
placeholder?: string
|
|
validate?: (value: string) => string | undefined
|
|
condition?: (inputs: Record<string, string>) => boolean
|
|
}
|
|
| {
|
|
type: "select"
|
|
key: string
|
|
message: string
|
|
options: Array<{
|
|
label: string
|
|
value: string
|
|
hint?: string
|
|
}>
|
|
condition?: (inputs: Record<string, string>) => boolean
|
|
}
|
|
>
|
|
authorize(inputs?: Record<string, string>): Promise<AuthOuathResult>
|
|
}
|
|
| {
|
|
type: "api"
|
|
label: string
|
|
prompts?: Array<
|
|
| {
|
|
type: "text"
|
|
key: string
|
|
message: string
|
|
placeholder?: string
|
|
validate?: (value: string) => string | undefined
|
|
condition?: (inputs: Record<string, string>) => boolean
|
|
}
|
|
| {
|
|
type: "select"
|
|
key: string
|
|
message: string
|
|
options: Array<{
|
|
label: string
|
|
value: string
|
|
hint?: string
|
|
}>
|
|
condition?: (inputs: Record<string, string>) => boolean
|
|
}
|
|
>
|
|
authorize?(inputs?: Record<string, string>): Promise<
|
|
| {
|
|
type: "success"
|
|
key: string
|
|
provider?: string
|
|
}
|
|
| {
|
|
type: "failed"
|
|
}
|
|
>
|
|
}
|
|
)[]
|
|
}
|
|
|
|
export type AuthOuathResult = { url: string; instructions: string } & (
|
|
| {
|
|
method: "auto"
|
|
callback(): Promise<
|
|
| ({
|
|
type: "success"
|
|
provider?: string
|
|
} & (
|
|
| {
|
|
refresh: string
|
|
access: string
|
|
expires: number
|
|
accountId?: string
|
|
}
|
|
| { key: string }
|
|
))
|
|
| {
|
|
type: "failed"
|
|
}
|
|
>
|
|
}
|
|
| {
|
|
method: "code"
|
|
callback(code: string): Promise<
|
|
| ({
|
|
type: "success"
|
|
provider?: string
|
|
} & (
|
|
| {
|
|
refresh: string
|
|
access: string
|
|
expires: number
|
|
accountId?: string
|
|
}
|
|
| { key: string }
|
|
))
|
|
| {
|
|
type: "failed"
|
|
}
|
|
>
|
|
}
|
|
)
|
|
|
|
export interface Hooks {
|
|
event?: (input: { event: Event }) => Promise<void>
|
|
config?: (input: Config) => Promise<void>
|
|
tool?: {
|
|
[key: string]: ToolDefinition
|
|
}
|
|
auth?: AuthHook
|
|
/**
|
|
* Called when a new message is received
|
|
*/
|
|
"chat.message"?: (
|
|
input: {
|
|
sessionID: string
|
|
agent?: string
|
|
model?: { providerID: string; modelID: string }
|
|
messageID?: string
|
|
variant?: string
|
|
},
|
|
output: { message: UserMessage; parts: Part[] },
|
|
) => Promise<void>
|
|
/**
|
|
* Modify parameters sent to LLM
|
|
*/
|
|
"chat.params"?: (
|
|
input: { sessionID: string; agent: string; model: Model; provider: ProviderContext; message: UserMessage },
|
|
output: { temperature: number; topP: number; topK: number; options: Record<string, any> },
|
|
) => Promise<void>
|
|
"chat.headers"?: (
|
|
input: { sessionID: string; agent: string; model: Model; provider: ProviderContext; message: UserMessage },
|
|
output: { headers: Record<string, string> },
|
|
) => Promise<void>
|
|
"permission.ask"?: (input: Permission, output: { status: "ask" | "deny" | "allow" }) => Promise<void>
|
|
"command.execute.before"?: (
|
|
input: { command: string; sessionID: string; arguments: string },
|
|
output: { parts: Part[] },
|
|
) => Promise<void>
|
|
"tool.execute.before"?: (
|
|
input: { tool: string; sessionID: string; callID: string },
|
|
output: { args: any },
|
|
) => Promise<void>
|
|
"shell.env"?: (
|
|
input: { cwd: string; sessionID?: string; callID?: string },
|
|
output: { env: Record<string, string> },
|
|
) => Promise<void>
|
|
"tool.execute.after"?: (
|
|
input: { tool: string; sessionID: string; callID: string; args: any },
|
|
output: {
|
|
title: string
|
|
output: string
|
|
metadata: any
|
|
},
|
|
) => Promise<void>
|
|
"experimental.chat.messages.transform"?: (
|
|
input: {},
|
|
output: {
|
|
messages: {
|
|
info: Message
|
|
parts: Part[]
|
|
}[]
|
|
},
|
|
) => Promise<void>
|
|
"experimental.chat.system.transform"?: (
|
|
input: { sessionID?: string; model: Model },
|
|
output: {
|
|
system: string[]
|
|
},
|
|
) => Promise<void>
|
|
/**
|
|
* Called before session compaction starts. Allows plugins to customize
|
|
* the compaction prompt.
|
|
*
|
|
* - `context`: Additional context strings appended to the default prompt
|
|
* - `prompt`: If set, replaces the default compaction prompt entirely
|
|
*/
|
|
"experimental.session.compacting"?: (
|
|
input: { sessionID: string },
|
|
output: { context: string[]; prompt?: string },
|
|
) => Promise<void>
|
|
"experimental.text.complete"?: (
|
|
input: { sessionID: string; messageID: string; partID: string },
|
|
output: { text: string },
|
|
) => Promise<void>
|
|
/**
|
|
* Modify tool definitions (description and parameters) sent to LLM
|
|
*/
|
|
"tool.definition"?: (input: { toolID: string }, output: { description: string; parameters: any }) => Promise<void>
|
|
}
|