import type { Event, createOpencodeClient, Project, Model, Provider, Permission, UserMessage, Message, Part, Config as SDKConfig } from "@opencode-ai/sdk"; import type { Provider as ProviderV2, Model as ModelV2, Auth } from "@opencode-ai/sdk/v2"; import type { BunShell } from "./shell.js"; import { type ToolDefinition } from "./tool.js"; export * from "./tool.js"; export type ProviderContext = { source: "env" | "config" | "custom" | "api"; info: Provider; options: Record; }; export type WorkspaceInfo = { id: string; type: string; name: string; branch: string | null; directory: string | null; extra: unknown | null; projectID: string; }; export type WorkspaceTarget = { type: "local"; directory: string; } | { type: "remote"; url: string | URL; headers?: HeadersInit; }; export type WorkspaceAdapter = { name: string; description: string; configure(config: WorkspaceInfo): WorkspaceInfo | Promise; create(config: WorkspaceInfo, env: Record, from?: WorkspaceInfo): Promise; remove(config: WorkspaceInfo): Promise; target(config: WorkspaceInfo): WorkspaceTarget | Promise; }; export type PluginInput = { client: ReturnType; project: Project; directory: string; worktree: string; experimental_workspace: { register(type: string, adapter: WorkspaceAdapter): void; }; serverUrl: URL; $: BunShell; }; export type PluginOptions = Record; export type Config = Omit & { plugin?: Array; }; export type Plugin = (input: PluginInput, options?: PluginOptions) => Promise; export type PluginModule = { id?: string; server: Plugin; tui?: never; }; type Rule = { key: string; op: "eq" | "neq"; value: string; }; export type AuthHook = { provider: string; loader?: (auth: () => Promise, provider: Provider) => Promise>; methods: ({ type: "oauth"; label: string; prompts?: Array<{ type: "text"; key: string; message: string; placeholder?: string; validate?: (value: string) => string | undefined; /** @deprecated Use `when` instead */ condition?: (inputs: Record) => boolean; when?: Rule; } | { type: "select"; key: string; message: string; options: Array<{ label: string; value: string; hint?: string; }>; /** @deprecated Use `when` instead */ condition?: (inputs: Record) => boolean; when?: Rule; }>; authorize(inputs?: Record): Promise; } | { type: "api"; label: string; prompts?: Array<{ type: "text"; key: string; message: string; placeholder?: string; validate?: (value: string) => string | undefined; /** @deprecated Use `when` instead */ condition?: (inputs: Record) => boolean; when?: Rule; } | { type: "select"; key: string; message: string; options: Array<{ label: string; value: string; hint?: string; }>; /** @deprecated Use `when` instead */ condition?: (inputs: Record) => boolean; when?: Rule; }>; authorize?(inputs?: Record): Promise<{ type: "success"; key: string; provider?: string; metadata?: Record; } | { type: "failed"; }>; })[]; }; export type AuthOAuthResult = { url: string; instructions: string; } & ({ method: "auto"; callback(): Promise<({ type: "success"; provider?: string; } & ({ refresh: string; access: string; expires: number; accountId?: string; enterpriseUrl?: string; } | { key: string; metadata?: Record; })) | { type: "failed"; }>; } | { method: "code"; callback(code: string): Promise<({ type: "success"; provider?: string; } & ({ refresh: string; access: string; expires: number; accountId?: string; enterpriseUrl?: string; } | { key: string; metadata?: Record; })) | { type: "failed"; }>; }); export type ProviderHookContext = { auth?: Auth; }; export type ProviderHook = { id: string; models?: (provider: ProviderV2, ctx: ProviderHookContext) => Promise>; }; /** @deprecated Use AuthOAuthResult instead. */ export type AuthOuathResult = AuthOAuthResult; export interface Hooks { dispose?: () => Promise; event?: (input: { event: Event; }) => Promise; config?: (input: Config) => Promise; tool?: { [key: string]: ToolDefinition; }; auth?: AuthHook; provider?: ProviderHook; /** * 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; /** * 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; maxOutputTokens: number | undefined; options: Record; }) => Promise; "chat.headers"?: (input: { sessionID: string; agent: string; model: Model; provider: ProviderContext; message: UserMessage; }, output: { headers: Record; }) => Promise; "permission.ask"?: (input: Permission, output: { status: "ask" | "deny" | "allow"; }) => Promise; "command.execute.before"?: (input: { command: string; sessionID: string; arguments: string; }, output: { parts: Part[]; }) => Promise; "tool.execute.before"?: (input: { tool: string; sessionID: string; callID: string; }, output: { args: any; }) => Promise; "shell.env"?: (input: { cwd: string; sessionID?: string; callID?: string; }, output: { env: Record; }) => Promise; "tool.execute.after"?: (input: { tool: string; sessionID: string; callID: string; args: any; }, output: { title: string; output: string; metadata: any; }) => Promise; "experimental.chat.messages.transform"?: (input: {}, output: { messages: { info: Message; parts: Part[]; }[]; }) => Promise; "experimental.chat.system.transform"?: (input: { sessionID?: string; model: Model; }, output: { system: string[]; }) => Promise; /** * 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; /** * Called after compaction succeeds and before a synthetic user * auto-continue message is added. * * - `enabled`: Defaults to `true`. Set to `false` to skip the synthetic * user "continue" turn. */ "experimental.compaction.autocontinue"?: (input: { sessionID: string; agent: string; model: Model; provider: ProviderContext; message: UserMessage; overflow: boolean; }, output: { enabled: boolean; }) => Promise; "experimental.text.complete"?: (input: { sessionID: string; messageID: string; partID: string; }, output: { text: string; }) => Promise; /** * Modify tool definitions (description and parameters) sent to LLM */ "tool.definition"?: (input: { toolID: string; }, output: { description: string; parameters: any; }) => Promise; }