refactor(tools): unify tool APIs and result handling (#38367)
This commit is contained in:
parent
8cac010bac
commit
79c1544072
133 changed files with 3602 additions and 2770 deletions
|
|
@ -127,8 +127,7 @@ export const make = Effect.fn("PluginHost.make")(function* (plugin: PluginV2.Int
|
|||
),
|
||||
},
|
||||
model: {
|
||||
get: (providerID, modelID) =>
|
||||
catalog.model.get(ProviderV2.ID.make(providerID), ModelV2.ID.make(modelID)),
|
||||
get: (providerID, modelID) => catalog.model.get(ProviderV2.ID.make(providerID), ModelV2.ID.make(modelID)),
|
||||
list: () => response(catalog.model.available()),
|
||||
default: () => response(catalog.model.default()),
|
||||
},
|
||||
|
|
@ -358,7 +357,7 @@ export const make = Effect.fn("PluginHost.make")(function* (plugin: PluginV2.Int
|
|||
Effect.gen(function* () {
|
||||
const registrations: Array<{
|
||||
readonly name: string
|
||||
readonly tool: Tool.AnyTool
|
||||
readonly tool: Tool.Any
|
||||
readonly options?: Tool.RegisterOptions
|
||||
}> = []
|
||||
yield* Effect.sync(() =>
|
||||
|
|
@ -395,25 +394,42 @@ export const make = Effect.fn("PluginHost.make")(function* (plugin: PluginV2.Int
|
|||
})
|
||||
}
|
||||
return toolHooks.hook.after((event) => {
|
||||
const output = {
|
||||
// JS plugin boundary: marshal the canonical outcome out, copy mutations back.
|
||||
const output: Record<string, unknown> = {
|
||||
tool: event.tool,
|
||||
sessionID: event.sessionID,
|
||||
agent: event.agent,
|
||||
messageID: event.messageID,
|
||||
callID: event.callID,
|
||||
input: event.input,
|
||||
result: event.result,
|
||||
output: event.output,
|
||||
status: event.status,
|
||||
content: event.content,
|
||||
metadata: event.metadata,
|
||||
outputPaths: event.outputPaths,
|
||||
...(event.status === "error" ? { error: event.error } : {}),
|
||||
}
|
||||
return Reflect.apply(callback, undefined, [output]).pipe(
|
||||
Effect.tap(() =>
|
||||
Effect.sync(() => {
|
||||
event.result = output.result
|
||||
event.output = output.output
|
||||
event.outputPaths = output.outputPaths
|
||||
}),
|
||||
),
|
||||
Effect.tap(() => {
|
||||
const decoded = Schema.decodeUnknownOption(Tool.ExecuteAfterOutcome)(output)
|
||||
if (decoded._tag === "None")
|
||||
return Effect.logWarning("ignoring invalid execute.after tool outcome", { tool: event.tool })
|
||||
if (decoded.value.status !== event.status)
|
||||
return Effect.logWarning("ignoring execute.after tool status change", { tool: event.tool })
|
||||
return Effect.sync(() => {
|
||||
if (event.status === "completed" && decoded.value.status === "completed") {
|
||||
if (output.content !== event.content) event.content = decoded.value.content
|
||||
if (output.metadata !== event.metadata) event.metadata = decoded.value.metadata
|
||||
if (output.outputPaths !== event.outputPaths) event.outputPaths = decoded.value.outputPaths
|
||||
return
|
||||
}
|
||||
if (event.status === "error" && decoded.value.status === "error") {
|
||||
if (output.error !== event.error) event.error = decoded.value.error
|
||||
if (output.content !== event.content) event.content = decoded.value.content
|
||||
if (output.metadata !== event.metadata) event.metadata = decoded.value.metadata
|
||||
if (output.outputPaths !== event.outputPaths) event.outputPaths = decoded.value.outputPaths
|
||||
}
|
||||
})
|
||||
}),
|
||||
)
|
||||
})
|
||||
},
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ export * as PluginPromise from "./promise"
|
|||
|
||||
import { define } from "@opencode-ai/plugin/v2/effect/plugin"
|
||||
import type { Context, Plugin } from "@opencode-ai/plugin/v2/plugin"
|
||||
import type { AnyTool } from "@opencode-ai/plugin/v2/tool"
|
||||
import type { Any, RegisterOptions } from "@opencode-ai/plugin/v2/tool"
|
||||
import { Agent } from "@opencode-ai/schema/agent"
|
||||
import { Integration } from "@opencode-ai/schema/integration"
|
||||
import { Location } from "@opencode-ai/schema/location"
|
||||
|
|
@ -189,7 +189,8 @@ export function fromPromise(plugin: Plugin) {
|
|||
register(
|
||||
host.tool.transform((draft) =>
|
||||
callback({
|
||||
add: (tool: AnyTool) => draft.add(tool.name, fromPromiseTool(tool), tool.options),
|
||||
add: (name: string, tool: Any, options?: RegisterOptions) =>
|
||||
draft.add(name, fromPromiseTool(tool), options),
|
||||
}),
|
||||
),
|
||||
),
|
||||
|
|
@ -302,19 +303,8 @@ function wireEvent(value: unknown): unknown {
|
|||
return wire(value)
|
||||
}
|
||||
|
||||
function fromPromiseTool(tool: AnyTool) {
|
||||
if ("jsonSchema" in tool)
|
||||
return Tool.make({
|
||||
...tool,
|
||||
execute: (input, context) =>
|
||||
Effect.promise(() =>
|
||||
tool.execute(input, {
|
||||
...context,
|
||||
progress: (update) => Effect.runPromise(context.progress(update)),
|
||||
}),
|
||||
),
|
||||
})
|
||||
return Tool.make({
|
||||
function fromPromiseTool(tool: Any): Tool.Any {
|
||||
return {
|
||||
...tool,
|
||||
execute: (input, context) =>
|
||||
Effect.promise(() =>
|
||||
|
|
@ -323,5 +313,5 @@ function fromPromiseTool(tool: AnyTool) {
|
|||
progress: (update) => Effect.runPromise(context.progress(update)),
|
||||
}),
|
||||
),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue