mirror of
https://gitee.com/zhangsken/opencode.git
synced 2026-10-16 10:30:01 +08:00
6189181c4e
On each primary request, compare the tool calls in the outgoing history with the tools the request actually offers. When calls made by a different model name tools this model does not have, add one reminder before the prompt and persist it as a synthetic message, recording which tools it named so later requests and later switches to models with the same tools do not repeat it. Runs after the patch plugin so it sees the editing tools left for this model.
291 lines
9.7 KiB
TypeScript
291 lines
9.7 KiB
TypeScript
export * as PluginInternal from "./internal.js"
|
|
|
|
import { LLMClient } from "@opencode/ai"
|
|
import type { Plugin } from "@opencode/plugin/effect/plugin"
|
|
import { LayerNode } from "@opencode/util/effect/layer-node"
|
|
import { httpClient } from "@opencode/util/effect/app-node-platform"
|
|
import { AppProcess } from "@opencode/util/process"
|
|
import { Context, Effect, Scope } from "effect"
|
|
import { HttpClient } from "effect/unstable/http"
|
|
import { Agent } from "../agent.js"
|
|
import { Model } from "../model.js"
|
|
import { Provider } from "../provider.js"
|
|
import { Command } from "../command.js"
|
|
import { Config } from "../config.js"
|
|
import { Credential } from "../credential.js"
|
|
import { llmClient } from "../effect/app-node-platform.js"
|
|
import { ConfigAgentPlugin } from "../config/plugin/agent.js"
|
|
import { ConfigCommandPlugin } from "../config/plugin/command.js"
|
|
import { ConfigCompactionPlugin } from "../config/plugin/compaction.js"
|
|
import { ConfigFormatterPlugin } from "../config/plugin/formatter.js"
|
|
import { ConfigImagePlugin } from "../config/plugin/image.js"
|
|
import { ConfigInstructionPlugin } from "../config/plugin/instruction.js"
|
|
import { ConfigLocationWatcherPlugin } from "../config/plugin/location-watcher.js"
|
|
import { ConfigMcpPlugin } from "../config/plugin/mcp.js"
|
|
import { ConfigProviderPlugin } from "../config/plugin/provider.js"
|
|
import { ConfigPolicyPlugin } from "../config/plugin/policy.js"
|
|
import { ConfigReferencePlugin } from "../config/plugin/reference.js"
|
|
import { ConfigShellPlugin } from "../config/plugin/shell.js"
|
|
import { ConfigSnapshotPlugin } from "../config/plugin/snapshot.js"
|
|
import { ConfigSkillPlugin } from "../config/plugin/skill.js"
|
|
import { ConfigCompatibilityPlugin } from "../config/plugin/compatibility.js"
|
|
import { ConfigToolOutputPlugin } from "../config/plugin/tool-output.js"
|
|
import { ConfigWebSearchPlugin } from "../config/plugin/websearch.js"
|
|
import { ConfigWorktreePlugin } from "../config/plugin/worktree.js"
|
|
import { Worktree } from "../worktree.js"
|
|
import { WorktreeStrategies } from "../worktree/strategies.js"
|
|
import { Bus } from "../bus.js"
|
|
import { Environment } from "../environment/index.js"
|
|
import { FileAccess } from "../file-access.js"
|
|
import { FileMutation } from "../file-mutation.js"
|
|
import { Formatter } from "../formatter.js"
|
|
import { Form } from "../form.js"
|
|
import { FileSystem } from "../filesystem.js"
|
|
import { LocationWatcherPolicy } from "../filesystem/location-watcher-policy.js"
|
|
import { FSUtil } from "@opencode/util/fs-util"
|
|
import { Global } from "@opencode/util/global"
|
|
import { Image } from "../image.js"
|
|
import { InstructionDiscovery } from "../instruction-discovery.js"
|
|
import { Integration } from "../integration.js"
|
|
import { Job } from "../job.js"
|
|
import { KV } from "../kv.js"
|
|
import { Location } from "../location.js"
|
|
import { ManagedPolicy } from "../managed-policy.js"
|
|
import { ModelsDev } from "../models-dev.js"
|
|
import { Mcp } from "../mcp/index.js"
|
|
import { Npm } from "@opencode/util/npm"
|
|
import { Permission } from "../permission.js"
|
|
import { Reference } from "../reference.js"
|
|
import { WebSearch } from "../websearch.js"
|
|
import { Ripgrep } from "../ripgrep.js"
|
|
import { Session } from "../session.js"
|
|
import { SessionCompaction } from "../session/compaction.js"
|
|
import { SessionInstructions } from "../session/instructions.js"
|
|
import { Shell } from "../shell.js"
|
|
import { ShellSelect } from "../shell/select.js"
|
|
import { Snapshot } from "../snapshot.js"
|
|
import { Skill } from "../skill.js"
|
|
import { SkillDiscovery } from "../skill/discovery.js"
|
|
import { Watcher } from "../filesystem/watcher.js"
|
|
import { PatchTool } from "../tool/plugin/patch.js"
|
|
import { EditTool } from "../tool/plugin/edit.js"
|
|
import { GlobTool } from "../tool/plugin/glob.js"
|
|
import { GrepTool } from "../tool/plugin/grep.js"
|
|
import { McpResourceTools } from "../tool/plugin/mcp-resource.js"
|
|
import { OpenCodeTools } from "../tool/plugin/opencode.js"
|
|
import { QuestionTool } from "../tool/plugin/question.js"
|
|
import { ReadToolFileSystem } from "../tool/read-filesystem.js"
|
|
import { ReadTool } from "../tool/plugin/read.js"
|
|
import { ShellTool } from "../tool/plugin/shell.js"
|
|
import { SkillTool } from "../tool/plugin/skill.js"
|
|
import { SubagentTool } from "../tool/plugin/subagent.js"
|
|
import { Tool } from "../tool.js"
|
|
import { ToolOutput } from "../tool-output.js"
|
|
import { WebFetchTool } from "../tool/plugin/webfetch.js"
|
|
import { WebSearchTool } from "../tool/plugin/websearch.js"
|
|
import { WellKnown } from "../wellknown.js"
|
|
import { WriteTool } from "../tool/plugin/write.js"
|
|
import { AgentPlugin } from "./agent.js"
|
|
import BrowserPlugin from "@opencode/plugin-browser"
|
|
import { CommandPlugin } from "./command.js"
|
|
import { NativeCompactionPlugin } from "./compaction.js"
|
|
import { IdentityPlugin } from "./identity.js"
|
|
import { PlanPlugin } from "./plan.js"
|
|
import { ModelSwitchPlugin } from "./model-switch.js"
|
|
import { ModelsDevPlugin } from "./models-dev.js"
|
|
import { McpCodeModeDefaultsPlugin } from "./mcp-codemode-defaults.js"
|
|
import { ProviderPlugins } from "./provider.js"
|
|
import { OpencodePlugin } from "./provider/opencode.js"
|
|
import { WebSearchPlugins } from "./websearch/index.js"
|
|
import { SkillPlugin } from "./skill.js"
|
|
import { VcsHgPlugin } from "./vcs/hg.js"
|
|
import { ToolInputRepairPlugin } from "./tool-input-repair.js"
|
|
import { OptimizePlugin } from "./optimize.js"
|
|
import { VcsGitPlugin } from "./vcs/git.js"
|
|
import { WarmingPlugin } from "./warming.js"
|
|
import { WellKnownPlugin } from "../wellknown/plugin.js"
|
|
|
|
const services = [
|
|
Agent.Service,
|
|
AppProcess.Service,
|
|
Provider.Service,
|
|
Model.Service,
|
|
Command.Service,
|
|
Config.Service,
|
|
Credential.Service,
|
|
Bus.Service,
|
|
Environment.Service,
|
|
FileAccess.Service,
|
|
FileMutation.Service,
|
|
Formatter.Service,
|
|
LocationWatcherPolicy.Service,
|
|
FileSystem.Service,
|
|
FSUtil.Service,
|
|
Global.Service,
|
|
HttpClient.HttpClient,
|
|
Image.Service,
|
|
InstructionDiscovery.Service,
|
|
Integration.Service,
|
|
Job.Service,
|
|
KV.Service,
|
|
LLMClient.Service,
|
|
Location.Service,
|
|
ManagedPolicy.Service,
|
|
ModelsDev.Service,
|
|
Mcp.Service,
|
|
Npm.Service,
|
|
Permission.Service,
|
|
Form.Service,
|
|
ReadToolFileSystem.Service,
|
|
Reference.Service,
|
|
WebSearch.Service,
|
|
Ripgrep.Service,
|
|
Session.Service,
|
|
SessionCompaction.Service,
|
|
SessionInstructions.Service,
|
|
Shell.Service,
|
|
ShellSelect.Service,
|
|
Snapshot.Service,
|
|
Skill.Service,
|
|
SkillDiscovery.Service,
|
|
Tool.Service,
|
|
ToolOutput.Service,
|
|
Watcher.Service,
|
|
WellKnown.Service,
|
|
Worktree.Service,
|
|
WorktreeStrategies.Service,
|
|
] as const
|
|
|
|
export type Requirements = Context.Service.Identifier<(typeof services)[number]>
|
|
|
|
export const requirements = LayerNode.group([
|
|
Agent.node,
|
|
AppProcess.node,
|
|
Provider.node,
|
|
Model.node,
|
|
Command.node,
|
|
Config.node,
|
|
Credential.node,
|
|
Bus.node,
|
|
Environment.node,
|
|
FileAccess.node,
|
|
FileMutation.node,
|
|
Formatter.node,
|
|
LocationWatcherPolicy.node,
|
|
FileSystem.node,
|
|
FSUtil.node,
|
|
Global.node,
|
|
httpClient,
|
|
Image.node,
|
|
InstructionDiscovery.node,
|
|
Integration.node,
|
|
Job.node,
|
|
KV.node,
|
|
llmClient,
|
|
Location.node,
|
|
ManagedPolicy.node,
|
|
ModelsDev.node,
|
|
Mcp.node,
|
|
Npm.node,
|
|
Permission.node,
|
|
Form.node,
|
|
ReadToolFileSystem.node,
|
|
Reference.node,
|
|
WebSearch.node,
|
|
Ripgrep.node,
|
|
Session.node,
|
|
SessionCompaction.node,
|
|
SessionInstructions.node,
|
|
Shell.node,
|
|
ShellSelect.node,
|
|
Snapshot.node,
|
|
Skill.node,
|
|
SkillDiscovery.node,
|
|
Tool.node,
|
|
ToolOutput.node,
|
|
Watcher.node,
|
|
WellKnown.node,
|
|
Worktree.node,
|
|
WorktreeStrategies.node,
|
|
])
|
|
|
|
export type InternalPlugin = Plugin<Requirements | Scope.Scope>
|
|
|
|
const pre = [
|
|
ToolInputRepairPlugin.Plugin,
|
|
ConfigWorktreePlugin.Plugin,
|
|
BrowserPlugin,
|
|
ConfigMcpPlugin.Plugin,
|
|
McpCodeModeDefaultsPlugin.Plugin,
|
|
WellKnownPlugin.Plugin,
|
|
VcsGitPlugin.Plugin,
|
|
AgentPlugin.Plugin,
|
|
PlanPlugin.Plugin,
|
|
CommandPlugin.Plugin,
|
|
SkillPlugin.Plugin,
|
|
VcsHgPlugin.Plugin,
|
|
ModelsDevPlugin,
|
|
NativeCompactionPlugin.Plugin,
|
|
...ProviderPlugins,
|
|
...WebSearchPlugins,
|
|
PatchTool.Plugin,
|
|
// Sees the editing tools the patch plugin left for this model.
|
|
ModelSwitchPlugin.Plugin,
|
|
// Render model prompts after the patch plugin selects the available editing tools.
|
|
...OptimizePlugin.Plugins,
|
|
IdentityPlugin.Plugin,
|
|
EditTool.Plugin,
|
|
GlobTool.Plugin,
|
|
GrepTool.Plugin,
|
|
OpenCodeTools.Plugin,
|
|
McpResourceTools.Plugin,
|
|
QuestionTool.Plugin,
|
|
ReadTool.Plugin,
|
|
ShellTool.Plugin,
|
|
SkillTool.Plugin,
|
|
SubagentTool.Plugin,
|
|
WebFetchTool.Plugin,
|
|
WebSearchTool.Plugin,
|
|
WriteTool.Plugin,
|
|
WarmingPlugin.Plugin,
|
|
] as const satisfies readonly InternalPlugin[]
|
|
|
|
const post = [
|
|
ConfigInstructionPlugin.Plugin,
|
|
ConfigReferencePlugin.Plugin,
|
|
ConfigAgentPlugin.Plugin,
|
|
ConfigCommandPlugin.Plugin,
|
|
ConfigCompactionPlugin.Plugin,
|
|
ConfigFormatterPlugin.Plugin,
|
|
ConfigImagePlugin.Plugin,
|
|
ConfigLocationWatcherPlugin.Plugin,
|
|
ConfigShellPlugin.Plugin,
|
|
ConfigSnapshotPlugin.Plugin,
|
|
ConfigToolOutputPlugin.Plugin,
|
|
ConfigCompatibilityPlugin.Plugin,
|
|
ConfigSkillPlugin.Plugin,
|
|
ConfigProviderPlugin.Plugin,
|
|
ConfigWebSearchPlugin.Plugin,
|
|
ConfigPolicyPlugin.Plugin,
|
|
] as const satisfies readonly InternalPlugin[]
|
|
|
|
// Repository config must not switch off policy enforcement or the Console connection that delivers
|
|
// organization statements, so plugin remove operations skip these IDs.
|
|
export const guarded: ReadonlySet<string> = new Set([OpencodePlugin.id, ConfigPolicyPlugin.Plugin.id])
|
|
|
|
export const list = Effect.fn("PluginInternal.list")(function* () {
|
|
// Capture only services; activation supplies the child Scope and batching context.
|
|
const context = Context.pick(...services)(yield* Effect.context<Requirements>())
|
|
const resolve = (plugins: readonly InternalPlugin[]) =>
|
|
plugins.map(
|
|
(plugin): Plugin => ({
|
|
id: plugin.id,
|
|
effect: (host) => plugin.effect(host).pipe(Effect.provide(context)),
|
|
}),
|
|
)
|
|
return {
|
|
pre: resolve(pre),
|
|
post: resolve(post),
|
|
}
|
|
})
|