refactor(core): unify v2 tool architecture (#31168)

This commit is contained in:
Kit Langton
2026-06-06 20:49:12 -04:00
committed by GitHub
parent effd27b239
commit 660a00d317
46 changed files with 2314 additions and 2058 deletions
+31 -27
View File
@@ -1,9 +1,11 @@
export * as TodoWriteTool from "./todowrite"
import { Tool, ToolFailure, toolText } from "@opencode-ai/llm"
import { Cause, Effect, Layer, Schema } from "effect"
import { ToolFailure, toolText } from "@opencode-ai/llm"
import { Effect, Layer, Schema } from "effect"
import { PermissionV2 } from "../permission"
import { SessionTodo } from "../session/todo"
import { ToolRegistry } from "./registry"
import { Tool } from "./tool"
import { Tools } from "./tools"
export const name = "todowrite"
@@ -18,33 +20,35 @@ export type Success = typeof Success.Type
export const toModelOutput = (output: Success) => JSON.stringify(output.todos, null, 2)
const definition = Tool.make({
description:
"Create and maintain a structured task list for the current coding session. Use it to track progress during multi-step work and keep todo statuses current.",
parameters: Parameters,
success: Success,
toModelOutput: ({ output }) => [toolText({ type: "text", text: toModelOutput(output) })],
})
export const layer = Layer.effectDiscard(
Effect.gen(function* () {
const registry = yield* ToolRegistry.Service
const tools = yield* Tools.Service
const todos = yield* SessionTodo.Service
const permission = yield* PermissionV2.Service
yield* registry.contribute((editor) =>
editor.set(name, {
tool: definition,
execute: ({ parameters, sessionID, assertPermission }) =>
Effect.gen(function* () {
yield* assertPermission({ action: name, resources: ["*"], save: ["*"] })
yield* todos.update({ sessionID, todos: parameters.todos })
return { todos: parameters.todos }
}).pipe(
Effect.catchCause((cause) =>
Effect.fail(new ToolFailure({ message: "Unable to update todos", error: Cause.squash(cause) })),
),
),
}),
)
yield* tools
.register({
[name]: Tool.make({
description:
"Create and maintain a structured task list for the current coding session. Use it to track progress during multi-step work and keep todo statuses current.",
input: Parameters,
output: Success,
toModelOutput: ({ output }) => [toolText({ type: "text", text: toModelOutput(output) })],
execute: (input, context) =>
Effect.gen(function* () {
yield* permission.assert({
action: name,
resources: ["*"],
save: ["*"],
sessionID: context.sessionID,
agent: context.agent,
source: { type: "tool", messageID: context.assistantMessageID, callID: context.toolCallID },
})
yield* todos.update({ sessionID: context.sessionID, todos: input.todos })
return { todos: input.todos }
}).pipe(Effect.mapError(() => new ToolFailure({ message: "Unable to update todos" }))),
}),
})
.pipe(Effect.orDie)
}),
)