55 lines
2.0 KiB
TypeScript
55 lines
2.0 KiB
TypeScript
export * as TodoWriteTool from "./todowrite"
|
|
|
|
import { ToolFailure, toolText } from "@opencode-ai/llm"
|
|
import { Effect, Layer, Schema } from "effect"
|
|
import { PermissionV2 } from "../permission"
|
|
import { SessionTodo } from "../session/todo"
|
|
import { Tool } from "./tool"
|
|
import { Tools } from "./tools"
|
|
|
|
export const name = "todowrite"
|
|
|
|
export const Input = Schema.Struct({
|
|
todos: Schema.Array(SessionTodo.Info).annotate({ description: "The updated todo list" }),
|
|
})
|
|
|
|
export const Output = Schema.Struct({
|
|
todos: Schema.Array(SessionTodo.Info),
|
|
})
|
|
export type Output = typeof Output.Type
|
|
|
|
export const toModelOutput = (output: Output) => JSON.stringify(output.todos, null, 2)
|
|
|
|
export const layer = Layer.effectDiscard(
|
|
Effect.gen(function* () {
|
|
const tools = yield* Tools.Service
|
|
const todos = yield* SessionTodo.Service
|
|
const permission = yield* PermissionV2.Service
|
|
|
|
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: Input,
|
|
output: Output,
|
|
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)
|
|
}),
|
|
)
|