feat(plugin): support plugin-provided tools (#34619)

This commit is contained in:
Kit Langton 2026-06-30 13:18:56 -04:00 committed by GitHub
commit 194b0615e0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
52 changed files with 1633 additions and 959 deletions

View file

@ -2,7 +2,6 @@ import fs from "fs/promises"
import path from "path"
import { describe, expect } from "bun:test"
import { DateTime, Effect, Equal, Hash, Layer, Schema } from "effect"
import { Tool } from "@opencode-ai/core/tool/tool"
import { define } from "@opencode-ai/plugin/v2/effect"
import { AgentV2 } from "@opencode-ai/core/agent"
import { Catalog } from "@opencode-ai/core/catalog"
@ -17,7 +16,7 @@ import { SessionV2 } from "@opencode-ai/core/session"
import { SessionRunnerModel } from "@opencode-ai/core/session/runner/model"
import { tmpdir } from "./fixture/tmpdir"
import { testEffect } from "./lib/effect"
import { toolDefinitions } from "./lib/tool"
import { toolDefinitions, waitForTool } from "./lib/tool"
import { FSUtil } from "../src/fs-util"
import { Credential } from "../src/credential"
import { Database } from "../src/database/database"
@ -28,14 +27,11 @@ import { Npm } from "../src/npm"
import { Project } from "../src/project"
import { Reference } from "../src/reference"
import { ToolRegistry } from "../src/tool/registry"
import { ApplicationTools } from "../src/tool/application-tools"
const applicationTools = ApplicationTools.layer
const it = testEffect(
Layer.merge(
Layer.mergeAll(applicationTools, Database.defaultLayer, EventV2.defaultLayer),
Layer.mergeAll(Database.defaultLayer, EventV2.defaultLayer),
locationServiceMapLayer.pipe(
Layer.provide(applicationTools),
Layer.provide(
Layer.mergeAll(
Project.defaultLayer,
@ -83,14 +79,6 @@ describe("LocationServiceMap", () => {
).pipe(
Effect.flatMap(([blocked, allowed]) =>
Effect.gen(function* () {
yield* (yield* ApplicationTools.Service).register({
application_context: Tool.make({
description: "Read application context",
input: Schema.Struct({}),
output: Schema.Struct({ ok: Schema.Boolean }),
execute: () => Effect.succeed({ ok: true }),
}),
})
yield* Effect.promise(() =>
fs.writeFile(
path.join(blocked.path, "opencode.json"),
@ -105,9 +93,12 @@ describe("LocationServiceMap", () => {
yield* Reference.Service
const catalog = yield* Catalog.Service
yield* catalog.transform((editor) => editor.provider.update(ProviderV2.ID.make("test"), () => {}))
const registry = yield* ToolRegistry.Service
yield* waitForTool(registry, "shell")
yield* waitForTool(registry, "subagent")
return {
providers: yield* catalog.provider.all(),
tools: yield* toolDefinitions(yield* ToolRegistry.Service),
tools: yield* toolDefinitions(registry),
}
}).pipe(
Effect.scoped,
@ -119,13 +110,14 @@ describe("LocationServiceMap", () => {
const blockedState = yield* update(blocked.path)
expect(blockedState.providers.some((provider) => provider.id === ProviderV2.ID.make("test"))).toBe(false)
expect(blockedState.tools.map((tool) => tool.name).sort()).toEqual([
"application_context",
"edit",
"glob",
"grep",
"question",
"read",
"shell",
"skill",
"subagent",
"todowrite",
"webfetch",
"websearch",
@ -134,13 +126,14 @@ describe("LocationServiceMap", () => {
const allowedState = yield* update(allowed.path)
expect(allowedState.providers.some((provider) => provider.id === ProviderV2.ID.make("test"))).toBe(true)
expect(allowedState.tools.map((tool) => tool.name).sort()).toEqual([
"application_context",
"edit",
"glob",
"grep",
"question",
"read",
"shell",
"skill",
"subagent",
"todowrite",
"webfetch",
"websearch",