feat(plugin): support dynamic Effect tools
This commit is contained in:
parent
5e2e0d6965
commit
7832a677fb
4 changed files with 49 additions and 1 deletions
|
|
@ -317,6 +317,13 @@ export const make = Effect.fn("PluginHost.make")(function* (plugin: PluginV2.Int
|
|||
add: (name, tool, options) => {
|
||||
registrations.push({ name, tool, ...(options ? { options } : {}) })
|
||||
},
|
||||
addDynamic: (name, config, options) => {
|
||||
registrations.push({
|
||||
name,
|
||||
tool: Tool.make(config),
|
||||
...(options ? { options } : {}),
|
||||
})
|
||||
},
|
||||
}),
|
||||
)
|
||||
yield* Effect.forEach(
|
||||
|
|
|
|||
|
|
@ -59,6 +59,9 @@ export const registerToolPlugin = <R>(plugin: {
|
|||
add: (name, tool, options) => {
|
||||
registrations.push({ name, tool, ...(options ? { options } : {}) })
|
||||
},
|
||||
addDynamic: (name, config, options) => {
|
||||
registrations.push({ name, tool: Tool.make(config), ...(options ? { options } : {}) })
|
||||
},
|
||||
})
|
||||
yield* Effect.forEach(
|
||||
registrations,
|
||||
|
|
|
|||
|
|
@ -274,6 +274,42 @@ describe("PluginV2", () => {
|
|||
}),
|
||||
)
|
||||
|
||||
it.effect("registers dynamic Effect tools through the host context", () =>
|
||||
Effect.gen(function* () {
|
||||
const plugins = yield* PluginV2.Service
|
||||
const registry = yield* ToolRegistry.Service
|
||||
const plugin = EffectPlugin.define({
|
||||
id: "dynamic-tool-plugin",
|
||||
effect: (ctx) =>
|
||||
ctx.tool
|
||||
.transform((draft) =>
|
||||
draft.addDynamic(
|
||||
"dynamic_tool",
|
||||
{
|
||||
description: "Dynamic plugin tool",
|
||||
jsonSchema: {
|
||||
type: "object",
|
||||
properties: { value: { type: "string" } },
|
||||
required: ["value"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
execute: (input) =>
|
||||
Effect.succeed({
|
||||
structured: input,
|
||||
content: [{ type: "text", text: "dynamic output" }],
|
||||
}),
|
||||
},
|
||||
{ codemode: false },
|
||||
),
|
||||
)
|
||||
.pipe(Effect.orDie),
|
||||
})
|
||||
|
||||
yield* plugins.activate([versioned(plugin)])
|
||||
expect((yield* registry.materialize()).definitions.map((tool) => tool.name)).toContain("dynamic_tool")
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("groups tool names and routes codemode registrations through execute", () =>
|
||||
Effect.gen(function* () {
|
||||
const plugins = yield* PluginV2.Service
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ export type DynamicOutput = {
|
|||
* time (MCP servers, plugin manifests). Input is passed through as `unknown`;
|
||||
* `execute` returns the already-projected structured value and model content.
|
||||
*/
|
||||
type DynamicConfig = {
|
||||
export type DynamicConfig = {
|
||||
readonly description: string
|
||||
readonly jsonSchema: JsonSchema.JsonSchema
|
||||
readonly outputSchema?: JsonSchema.JsonSchema
|
||||
|
|
@ -284,6 +284,8 @@ export interface RegisterOptions {
|
|||
|
||||
export interface ToolDraft {
|
||||
add(name: string, tool: AnyTool, options?: RegisterOptions): void
|
||||
/** Registers a dynamic Effect tool without importing the host's Tool module. */
|
||||
addDynamic(name: string, config: DynamicConfig, options?: RegisterOptions): void
|
||||
}
|
||||
|
||||
export interface ToolHooks {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue