feat(plugin): add v2 effect host (#33111)
This commit is contained in:
@@ -10,6 +10,7 @@ import { PermissionV2 } from "@opencode-ai/core/permission"
|
||||
import { AbsolutePath } from "@opencode-ai/core/schema"
|
||||
import { tmpdir } from "../fixture/tmpdir"
|
||||
import { testEffect } from "../lib/effect"
|
||||
import { agentHost, host } from "../plugin/host"
|
||||
|
||||
const it = testEffect(Layer.mergeAll(AgentV2.locationLayer, FSUtil.defaultLayer))
|
||||
const decode = Schema.decodeUnknownSync(Config.Info)
|
||||
@@ -19,9 +20,7 @@ describe("ConfigAgentPlugin.Plugin", () => {
|
||||
Effect.gen(function* () {
|
||||
const agents = yield* AgentV2.Service
|
||||
const build = AgentV2.ID.make("build")
|
||||
const defaults = yield* agents.transform()
|
||||
|
||||
yield* defaults((editor) =>
|
||||
yield* agents.transform((editor) =>
|
||||
editor.update(build, (agent) => {
|
||||
agent.mode = "primary"
|
||||
agent.permissions.push({ action: "bash", resource: "*", effect: "allow" })
|
||||
@@ -68,9 +67,8 @@ describe("ConfigAgentPlugin.Plugin", () => {
|
||||
]),
|
||||
})
|
||||
|
||||
yield* ConfigAgentPlugin.Plugin.effect.pipe(
|
||||
yield* ConfigAgentPlugin.Plugin.effect(host({ agent: agentHost(agents) })).pipe(
|
||||
Effect.provideService(Config.Service, config),
|
||||
Effect.provideService(AgentV2.Service, agents),
|
||||
)
|
||||
|
||||
const buildAgent = yield* agents.get(build)
|
||||
@@ -150,9 +148,8 @@ describe("ConfigAgentPlugin.Plugin", () => {
|
||||
]),
|
||||
})
|
||||
|
||||
yield* ConfigAgentPlugin.Plugin.effect.pipe(
|
||||
yield* ConfigAgentPlugin.Plugin.effect(host({ agent: agentHost(agents) })).pipe(
|
||||
Effect.provideService(Config.Service, config),
|
||||
Effect.provideService(AgentV2.Service, agents),
|
||||
)
|
||||
|
||||
const reviewer = yield* agents.get(AgentV2.ID.make("reviewer"))
|
||||
@@ -177,8 +174,7 @@ describe("ConfigAgentPlugin.Plugin", () => {
|
||||
Effect.gen(function* () {
|
||||
const agents = yield* AgentV2.Service
|
||||
const build = AgentV2.ID.make("build")
|
||||
const defaults = yield* agents.transform()
|
||||
yield* defaults((editor) => editor.update(build, () => {}))
|
||||
yield* agents.transform((editor) => editor.update(build, () => {}))
|
||||
|
||||
const config = Config.Service.of({
|
||||
entries: () =>
|
||||
@@ -190,9 +186,8 @@ describe("ConfigAgentPlugin.Plugin", () => {
|
||||
]),
|
||||
})
|
||||
|
||||
yield* ConfigAgentPlugin.Plugin.effect.pipe(
|
||||
yield* ConfigAgentPlugin.Plugin.effect(host({ agent: agentHost(agents) })).pipe(
|
||||
Effect.provideService(Config.Service, config),
|
||||
Effect.provideService(AgentV2.Service, agents),
|
||||
)
|
||||
|
||||
expect(yield* agents.get(build)).toBeUndefined()
|
||||
@@ -251,9 +246,8 @@ Use native v2 fields.`,
|
||||
]),
|
||||
})
|
||||
|
||||
yield* ConfigAgentPlugin.Plugin.effect.pipe(
|
||||
yield* ConfigAgentPlugin.Plugin.effect(host({ agent: agentHost(agents) })).pipe(
|
||||
Effect.provideService(Config.Service, config),
|
||||
Effect.provideService(AgentV2.Service, agents),
|
||||
)
|
||||
|
||||
expect(yield* agents.get(AgentV2.ID.make("reviewer"))).toMatchObject({
|
||||
|
||||
@@ -11,6 +11,7 @@ import { ProviderV2 } from "@opencode-ai/core/provider"
|
||||
import { AbsolutePath } from "@opencode-ai/core/schema"
|
||||
import { tmpdir } from "../fixture/tmpdir"
|
||||
import { testEffect } from "../lib/effect"
|
||||
import { host } from "../plugin/host"
|
||||
|
||||
const it = testEffect(Layer.mergeAll(CommandV2.locationLayer, FSUtil.defaultLayer))
|
||||
const decode = Schema.decodeUnknownSync(Config.Info)
|
||||
@@ -41,8 +42,7 @@ Review files`,
|
||||
})
|
||||
|
||||
const command = yield* CommandV2.Service
|
||||
yield* ConfigCommandPlugin.Plugin.effect.pipe(
|
||||
Effect.provideService(CommandV2.Service, command),
|
||||
yield* ConfigCommandPlugin.Plugin.effect(host({ command })).pipe(
|
||||
Effect.provideService(
|
||||
Config.Service,
|
||||
Config.Service.of({
|
||||
|
||||
@@ -7,7 +7,8 @@ import { Integration } from "@opencode-ai/core/integration"
|
||||
import { ModelV2 } from "@opencode-ai/core/model"
|
||||
import { PluginV2 } from "@opencode-ai/core/plugin"
|
||||
import { ProviderV2 } from "@opencode-ai/core/provider"
|
||||
import { it, withEnv } from "../plugin/provider-helper"
|
||||
import { it, required, withEnv } from "../plugin/provider-helper"
|
||||
import { catalogHost, host, integrationHost } from "../plugin/host"
|
||||
|
||||
function request(headers: Record<string, string>, variant?: string) {
|
||||
return {
|
||||
@@ -58,14 +59,14 @@ describe("ConfigProviderPlugin.Plugin", () => {
|
||||
|
||||
yield* plugin.add({
|
||||
...ConfigProviderPlugin.Plugin,
|
||||
effect: ConfigProviderPlugin.Plugin.effect.pipe(
|
||||
effect: ConfigProviderPlugin.Plugin.effect(
|
||||
host({ catalog: catalogHost(catalog), integration: integrationHost(integrations) }),
|
||||
).pipe(
|
||||
Effect.provideService(Config.Service, config),
|
||||
Effect.provideService(Catalog.Service, catalog),
|
||||
Effect.provideService(Integration.Service, integrations),
|
||||
),
|
||||
})
|
||||
|
||||
const model = yield* catalog.model.get(providerID, modelID)
|
||||
const model = required(yield* catalog.model.get(providerID, modelID))
|
||||
expect(model.variants).toMatchObject([
|
||||
{
|
||||
id: "high",
|
||||
@@ -119,14 +120,14 @@ describe("ConfigProviderPlugin.Plugin", () => {
|
||||
|
||||
yield* plugin.add({
|
||||
...ConfigProviderPlugin.Plugin,
|
||||
effect: ConfigProviderPlugin.Plugin.effect.pipe(
|
||||
effect: ConfigProviderPlugin.Plugin.effect(
|
||||
host({ catalog: catalogHost(catalog), integration: integrationHost(integrations) }),
|
||||
).pipe(
|
||||
Effect.provideService(Config.Service, config),
|
||||
Effect.provideService(Catalog.Service, catalog),
|
||||
Effect.provideService(Integration.Service, integrations),
|
||||
),
|
||||
})
|
||||
|
||||
const model = yield* catalog.model.get(providerID, modelID)
|
||||
const model = required(yield* catalog.model.get(providerID, modelID))
|
||||
expect(model.variants[0]).toMatchObject({
|
||||
id: "high",
|
||||
body: {},
|
||||
@@ -222,16 +223,16 @@ describe("ConfigProviderPlugin.Plugin", () => {
|
||||
|
||||
yield* plugin.add({
|
||||
...ConfigProviderPlugin.Plugin,
|
||||
effect: ConfigProviderPlugin.Plugin.effect.pipe(
|
||||
effect: ConfigProviderPlugin.Plugin.effect(
|
||||
host({ catalog: catalogHost(catalog), integration: integrationHost(integrations) }),
|
||||
).pipe(
|
||||
Effect.provideService(Config.Service, config),
|
||||
Effect.provideService(Catalog.Service, catalog),
|
||||
Effect.provideService(Integration.Service, integrations),
|
||||
),
|
||||
})
|
||||
|
||||
const provider = yield* catalog.provider.get(providerID)
|
||||
const model = yield* catalog.model.get(providerID, modelID)
|
||||
expect(Option.getOrUndefined(yield* catalog.model.default())?.id).toBe(ModelV2.ID.make("default"))
|
||||
const provider = required(yield* catalog.provider.get(providerID))
|
||||
const model = required(yield* catalog.model.get(providerID, modelID))
|
||||
expect((yield* catalog.model.default())?.id).toBe(ModelV2.ID.make("default"))
|
||||
expect(provider.name).toBe("Renamed")
|
||||
expect((yield* integrations.get(Integration.ID.make("custom")))?.methods).toContainEqual({
|
||||
type: "env",
|
||||
|
||||
@@ -9,6 +9,7 @@ import { AbsolutePath } from "@opencode-ai/core/schema"
|
||||
import { SkillV2 } from "@opencode-ai/core/skill"
|
||||
import { location } from "../fixture/location"
|
||||
import { testEffect } from "../lib/effect"
|
||||
import { host } from "../plugin/host"
|
||||
|
||||
const it = testEffect(Layer.empty)
|
||||
const decode = Schema.decodeUnknownSync(Config.Info)
|
||||
@@ -18,16 +19,33 @@ describe("ConfigSkillPlugin.Plugin", () => {
|
||||
Effect.gen(function* () {
|
||||
const directory = AbsolutePath.make("/repo/packages/app")
|
||||
const sources: SkillV2.Source[] = []
|
||||
const transform = Effect.fnUntraced(function* () {
|
||||
return Effect.fnUntraced(function* (update: (editor: SkillV2.Editor) => void) {
|
||||
update({
|
||||
source: (source) => sources.push(source),
|
||||
list: () => sources,
|
||||
})
|
||||
const transform = Effect.fnUntraced(function* (update: (draft: SkillV2.Draft) => void | Effect.Effect<void>) {
|
||||
const result = update({
|
||||
source: (source) => {
|
||||
sources.push(source)
|
||||
},
|
||||
list: () => sources,
|
||||
})
|
||||
if (Effect.isEffect(result)) yield* result
|
||||
const dispose = Effect.sync(() => {
|
||||
sources.length = 0
|
||||
})
|
||||
yield* Effect.addFinalizer(() => dispose)
|
||||
return { dispose }
|
||||
})
|
||||
|
||||
yield* ConfigSkillPlugin.Plugin.effect.pipe(
|
||||
yield* ConfigSkillPlugin.Plugin.effect(
|
||||
host({
|
||||
location: location({ directory }),
|
||||
path: { ...host().path, home: "/home/test" },
|
||||
skill: SkillV2.Service.of({
|
||||
transform,
|
||||
rebuild: () => Effect.void,
|
||||
sources: () => Effect.succeed(sources),
|
||||
list: () => Effect.succeed([]),
|
||||
}),
|
||||
}),
|
||||
).pipe(
|
||||
Effect.provideService(
|
||||
Config.Service,
|
||||
Config.Service.of({
|
||||
@@ -43,16 +61,6 @@ describe("ConfigSkillPlugin.Plugin", () => {
|
||||
]),
|
||||
}),
|
||||
),
|
||||
Effect.provideService(Global.Service, Global.Service.of(Global.make({ home: "/home/test" }))),
|
||||
Effect.provideService(Location.Service, Location.Service.of(location({ directory }))),
|
||||
Effect.provideService(
|
||||
SkillV2.Service,
|
||||
SkillV2.Service.of({
|
||||
transform,
|
||||
sources: () => Effect.succeed(sources),
|
||||
list: () => Effect.succeed([]),
|
||||
}),
|
||||
),
|
||||
)
|
||||
|
||||
expect(sources).toEqual([
|
||||
|
||||
Reference in New Issue
Block a user