export * as PluginInternal from "./internal" import { makeLocationNode } from "../effect/app-node" import { httpClient } from "../effect/app-node-platform" import type { PluginContext } from "@opencode-ai/plugin/v2/effect" import { Context, Effect, Layer, Scope } from "effect" import { AgentV2 } from "../agent" import { Catalog } from "../catalog" import { CommandV2 } from "../command" import { Config } from "../config" import { ConfigAgentPlugin } from "../config/plugin/agent" import { ConfigCommandPlugin } from "../config/plugin/command" import { ConfigExternalPlugin } from "../config/plugin/external" import { ConfigProviderPlugin } from "../config/plugin/provider" import { ConfigReferencePlugin } from "../config/plugin/reference" import { ConfigSkillPlugin } from "../config/plugin/skill" import { EventV2 } from "../event" import { FileMutation } from "../file-mutation" import { FileSystem } from "../filesystem" import { FSUtil } from "../fs-util" import { Global } from "../global" import { Image } from "../image" import { Integration } from "../integration" import { Location } from "../location" import { LocationMutation } from "../location-mutation" import { ModelsDev } from "../models-dev" import { Npm } from "../npm" import { PluginV2 } from "../plugin" import { PluginRuntime } from "../plugin/runtime" import { PermissionV2 } from "../permission" import { QuestionV2 } from "../question" import { Reference } from "../reference" import { Ripgrep } from "../ripgrep" import { SessionInstructions } from "../session/instructions" import { SessionTodo } from "../session/todo" import { Shell } from "../shell" import { SkillV2 } from "../skill" import { State } from "../state" import { ToolRegistry } from "../tool/registry" import { Tools } from "../tool/tools" import { HttpClient } from "effect/unstable/http" import { AgentPlugin } from "./agent" import { CommandPlugin } from "./command" import { ModelsDevPlugin } from "./models-dev" import { ProviderPlugins } from "./provider" import { SdkPlugins } from "./sdk" import { SkillPlugin } from "./skill" import { VariantPlugin } from "./variant" import { ApplyPatchTool } from "../tool/apply-patch" import { EditTool } from "../tool/edit" import { GlobTool } from "../tool/glob" import { GrepTool } from "../tool/grep" import { QuestionTool } from "../tool/question" import { ReadTool } from "../tool/read" import { ReadToolFileSystem } from "../tool/read-filesystem" import { ShellTool } from "../tool/shell" import { SkillTool } from "../tool/skill" import { SubagentTool } from "../tool/subagent" import { TodoWriteTool } from "../tool/todowrite" import { WebFetchTool } from "../tool/webfetch" import { WebSearchTool } from "../tool/websearch" import { WriteTool } from "../tool/write" export type Requirements = | AgentV2.Service | Catalog.Service | CommandV2.Service | Config.Service | EventV2.Service | FileMutation.Service | FileSystem.Service | FSUtil.Service | Global.Service | HttpClient.HttpClient | Image.Service | Integration.Service | Location.Service | LocationMutation.Service | ModelsDev.Service | Npm.Service | PermissionV2.Service | PluginRuntime.Service | QuestionV2.Service | ReadToolFileSystem.Service | Reference.Service | Ripgrep.Service | SessionInstructions.Service | SessionTodo.Service | Shell.Service | SkillV2.Service | Tools.Service | WebSearchTool.ConfigService export interface Plugin { readonly id: string readonly effect: (context: PluginContext) => Effect.Effect } export function define(plugin: Plugin) { return plugin } const layer = Layer.effectDiscard( Effect.gen(function* () { const plugin = yield* PluginV2.Service const sdkPlugins = yield* SdkPlugins.Service const catalog = yield* Catalog.Service const services = Context.mergeAll( Context.make(Catalog.Service, catalog), Context.make(CommandV2.Service, yield* CommandV2.Service), Context.make(Integration.Service, yield* Integration.Service), Context.make(AgentV2.Service, yield* AgentV2.Service), Context.make(Config.Service, yield* Config.Service), Context.make(Location.Service, yield* Location.Service), Context.make(ModelsDev.Service, yield* ModelsDev.Service), Context.make(Npm.Service, yield* Npm.Service), Context.make(EventV2.Service, yield* EventV2.Service), Context.make(FSUtil.Service, yield* FSUtil.Service), Context.make(FileSystem.Service, yield* FileSystem.Service), Context.make(Global.Service, yield* Global.Service), Context.make(HttpClient.HttpClient, yield* HttpClient.HttpClient), Context.make(LocationMutation.Service, yield* LocationMutation.Service), Context.make(FileMutation.Service, yield* FileMutation.Service), Context.make(Image.Service, yield* Image.Service), Context.make(PermissionV2.Service, yield* PermissionV2.Service), Context.make(QuestionV2.Service, yield* QuestionV2.Service), Context.make(ReadToolFileSystem.Service, yield* ReadToolFileSystem.Service), Context.make(SessionInstructions.Service, yield* SessionInstructions.Service), Context.make(SessionTodo.Service, yield* SessionTodo.Service), Context.make(SkillV2.Service, yield* SkillV2.Service), Context.make(Reference.Service, yield* Reference.Service), Context.make(Ripgrep.Service, yield* Ripgrep.Service), Context.make(Shell.Service, yield* Shell.Service), Context.make(Tools.Service, yield* Tools.Service), Context.make(PluginRuntime.Service, yield* PluginRuntime.Service), Context.make(WebSearchTool.ConfigService, yield* WebSearchTool.ConfigService), ) const add = (input: Plugin) => plugin.add(PluginV2.ID.make(input.id), (context: PluginContext) => input.effect(context).pipe(Effect.provide(services)), ) yield* catalog.initial.discover( State.batch( Effect.gen(function* () { yield* add(ConfigReferencePlugin.Plugin) yield* add(AgentPlugin.Plugin) yield* add(CommandPlugin.Plugin) yield* add(SkillPlugin.Plugin) yield* add(ModelsDevPlugin) yield* add(ConfigExternalPlugin.Plugin) yield* add(ApplyPatchTool.Plugin) yield* add(EditTool.Plugin) yield* add(GlobTool.Plugin) yield* add(GrepTool.Plugin) yield* add(QuestionTool.Plugin) yield* add(ReadTool.Plugin) yield* add(ShellTool.Plugin) yield* add(SkillTool.Plugin) yield* add(SubagentTool.Plugin) yield* add(TodoWriteTool.Plugin) yield* add(WebFetchTool.Plugin) yield* add(WebSearchTool.Plugin) yield* add(WriteTool.Plugin) yield* add(ConfigAgentPlugin.Plugin) yield* add(ConfigCommandPlugin.Plugin) yield* add(ConfigSkillPlugin.Plugin) for (const item of ProviderPlugins) yield* add(item) yield* add(ConfigProviderPlugin.Plugin) yield* add(VariantPlugin.Plugin) // Embedder-contributed plugins are added last so they layer over config. for (const plugin of sdkPlugins.all()) yield* add(plugin) }), ), ).pipe( Effect.withSpan("PluginInternal.boot"), Effect.forkScoped({ startImmediately: true }), ) }), ) export const node = makeLocationNode({ name: "plugin-internal", layer, deps: [ Catalog.node, CommandV2.node, PluginV2.node, Integration.node, AgentV2.node, Config.node, Location.node, LocationMutation.node, FileMutation.node, Image.node, ModelsDev.node, Npm.node, EventV2.node, FSUtil.node, FileSystem.node, Global.node, httpClient, PermissionV2.node, QuestionV2.node, ReadToolFileSystem.node, SessionInstructions.node, SessionTodo.node, SkillV2.node, Reference.node, Ripgrep.node, Shell.node, ToolRegistry.toolsNode, PluginRuntime.node, SdkPlugins.node, WebSearchTool.configNode, ], })