fix(plugin): reload late SDK plugins (#35576)
This commit is contained in:
parent
06dcf3f221
commit
2830176972
26 changed files with 1187 additions and 922 deletions
|
|
@ -61,6 +61,12 @@ const GlobalMessage = EventV2.ephemeral({
|
|||
text: Schema.String,
|
||||
},
|
||||
})
|
||||
const CountMessage = EventV2.ephemeral({
|
||||
type: "test.count",
|
||||
schema: {
|
||||
count: Schema.Number,
|
||||
},
|
||||
})
|
||||
|
||||
const VersionedMessage = EventV2.durable({
|
||||
type: "test.versioned",
|
||||
|
|
@ -90,6 +96,26 @@ const it = testEffect(
|
|||
const itWithoutLocation = testEffect(AppNodeBuilder.build(LayerNode.group([Database.node, EventV2.node])))
|
||||
|
||||
describe("EventV2", () => {
|
||||
it.effect("subscribes to multiple event definitions with a discriminated payload union", () =>
|
||||
Effect.gen(function* () {
|
||||
const events = yield* EventV2.Service
|
||||
// @ts-expect-error multi-definition subscriptions require at least one definition
|
||||
events.subscribe([])
|
||||
const fiber = yield* events
|
||||
.subscribe([Message, CountMessage])
|
||||
.pipe(Stream.take(2), Stream.runCollect, Effect.forkScoped)
|
||||
yield* Effect.yieldNow
|
||||
|
||||
yield* events.publish(Message, { text: "hello" })
|
||||
yield* events.publish(CountMessage, { count: 2 })
|
||||
|
||||
const received = Array.from(yield* Fiber.join(fiber)).map((event) =>
|
||||
event.type === "test.message" ? event.data.text : event.data.count,
|
||||
)
|
||||
expect(received).toEqual(["hello", 2])
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("publishes events with the current location", () =>
|
||||
Effect.gen(function* () {
|
||||
const events = yield* EventV2.Service
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { AgentV2 } from "@opencode-ai/core/agent"
|
|||
import type { PermissionV2 } from "@opencode-ai/core/permission"
|
||||
import { SessionMessage } from "@opencode-ai/core/session/message"
|
||||
import { ToolRegistry } from "@opencode-ai/core/tool/registry"
|
||||
import { Tool } from "@opencode-ai/core/tool/tool"
|
||||
import { Tools } from "@opencode-ai/core/tool/tools"
|
||||
import type { PluginContext } from "@opencode-ai/plugin/v2/effect"
|
||||
import { Effect, type Scope } from "effect"
|
||||
|
|
@ -49,7 +50,24 @@ export const registerToolPlugin = <R>(plugin: {
|
|||
const tools = yield* Tools.Service
|
||||
const context: Pick<PluginContext, "tool"> = {
|
||||
tool: {
|
||||
register: tools.register,
|
||||
transform: (callback) =>
|
||||
Effect.gen(function* () {
|
||||
const registrations: Array<{
|
||||
readonly name: string
|
||||
readonly tool: Tool.AnyTool
|
||||
readonly options?: Tool.RegisterOptions
|
||||
}> = []
|
||||
callback({
|
||||
add: (name, tool, options) => {
|
||||
registrations.push({ name, tool, ...(options ? { options } : {}) })
|
||||
},
|
||||
})
|
||||
yield* Effect.forEach(
|
||||
registrations,
|
||||
(registration) => tools.register({ [registration.name]: registration.tool }, registration.options),
|
||||
{ discard: true },
|
||||
)
|
||||
}),
|
||||
execute: {
|
||||
before: () => Effect.die("registerToolPlugin does not support tool hooks"),
|
||||
after: () => Effect.die("registerToolPlugin does not support tool hooks"),
|
||||
|
|
|
|||
|
|
@ -165,14 +165,17 @@ describe("PluginV2", () => {
|
|||
id: "tool-plugin",
|
||||
effect: (ctx) =>
|
||||
ctx.tool
|
||||
.register({
|
||||
plugin_tool: Tool.make({
|
||||
description: "Plugin tool",
|
||||
input: Schema.Struct({}),
|
||||
output: Schema.Struct({ ok: Schema.Boolean }),
|
||||
execute: () => Effect.succeed({ ok: true }),
|
||||
}),
|
||||
})
|
||||
.transform((draft) =>
|
||||
draft.add(
|
||||
"plugin_tool",
|
||||
Tool.make({
|
||||
description: "Plugin tool",
|
||||
input: Schema.Struct({}),
|
||||
output: Schema.Struct({ ok: Schema.Boolean }),
|
||||
execute: () => Effect.succeed({ ok: true }),
|
||||
}),
|
||||
),
|
||||
)
|
||||
.pipe(Effect.orDie),
|
||||
})
|
||||
|
||||
|
|
@ -202,13 +205,13 @@ describe("PluginV2", () => {
|
|||
const plugin = define({
|
||||
id: "grouped-tools",
|
||||
effect: (ctx) =>
|
||||
Effect.gen(function* () {
|
||||
yield* ctx.tool.register({ plain: tool("Plain") }).pipe(Effect.orDie)
|
||||
yield* ctx.tool.register({ "look/up": tool("Lookup") }, { group: "context 7" }).pipe(Effect.orDie)
|
||||
yield* ctx.tool
|
||||
.register({ search: tool("Search") }, { group: "context 7", deferred: true })
|
||||
.pipe(Effect.orDie)
|
||||
}),
|
||||
ctx.tool
|
||||
.transform((draft) => {
|
||||
draft.add("plain", tool("Plain"))
|
||||
draft.add("look/up", tool("Lookup"), { group: "context 7" })
|
||||
draft.add("search", tool("Search"), { group: "context 7", deferred: true })
|
||||
})
|
||||
.pipe(Effect.orDie),
|
||||
})
|
||||
|
||||
yield* plugins.activate([{ plugin }])
|
||||
|
|
@ -236,14 +239,17 @@ describe("PluginV2", () => {
|
|||
effect: (ctx) =>
|
||||
Effect.gen(function* () {
|
||||
yield* ctx.tool
|
||||
.register({
|
||||
echo: Tool.make({
|
||||
description: "Echo",
|
||||
input: Schema.Struct({ text: Schema.String }),
|
||||
output: Schema.Struct({ text: Schema.String }),
|
||||
execute: ({ text }) => Effect.sync(() => executed.push({ text })).pipe(Effect.as({ text })),
|
||||
}),
|
||||
})
|
||||
.transform((draft) =>
|
||||
draft.add(
|
||||
"echo",
|
||||
Tool.make({
|
||||
description: "Echo",
|
||||
input: Schema.Struct({ text: Schema.String }),
|
||||
output: Schema.Struct({ text: Schema.String }),
|
||||
execute: ({ text }) => Effect.sync(() => executed.push({ text })).pipe(Effect.as({ text })),
|
||||
}),
|
||||
),
|
||||
)
|
||||
.pipe(Effect.orDie)
|
||||
|
||||
yield* ctx.tool.execute
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ export function host(overrides: Overrides = {}): PluginContext {
|
|||
reload: () => Effect.die("unused skill.reload"),
|
||||
},
|
||||
tool: overrides.tool ?? {
|
||||
register: () => Effect.die("unused tool.register"),
|
||||
transform: () => Effect.die("unused tool.transform"),
|
||||
execute: {
|
||||
before: () => Effect.die("unused tool.execute.before"),
|
||||
after: () => Effect.die("unused tool.execute.after"),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue