habits.go

 1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
 2//
 3// SPDX-License-Identifier: AGPL-3.0-or-later
 4
 5package tools
 6
 7import (
 8	"context"
 9	"fmt"
10	"strings"
11
12	"git.secluded.site/go-lunatask"
13	"github.com/mark3labs/mcp-go/mcp"
14)
15
16// HandleListHabitsAndActivities handles the list_habits_and_activities tool call.
17func (h *Handlers) HandleListHabitsAndActivities(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
18	var b strings.Builder
19	for _, habit := range h.config.Habits {
20		fmt.Fprintf(&b, "- %s: %s\n", habit.GetName(), habit.GetID())
21	}
22
23	return &mcp.CallToolResult{
24		Content: []mcp.Content{
25			mcp.TextContent{
26				Type: "text",
27				Text: b.String(),
28			},
29		},
30	}, nil
31}
32
33// HandleTrackHabitActivity handles the track_habit_activity tool call.
34func (h *Handlers) HandleTrackHabitActivity(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
35	habitID, ok := request.Params.Arguments["habit_id"].(string)
36	if !ok || habitID == "" {
37		return reportMCPError("Missing or invalid required argument: habit_id")
38	}
39
40	performedOnStr, ok := request.Params.Arguments["performed_on"].(string)
41	if !ok || performedOnStr == "" {
42		return reportMCPError("Missing or invalid required argument: performed_on")
43	}
44
45	performedOn, err := lunatask.ParseDate(performedOnStr)
46	if err != nil {
47		return reportMCPError(fmt.Sprintf("Invalid format for performed_on: '%s'. Must be YYYY-MM-DD.", performedOnStr))
48	}
49
50	client := lunatask.NewClient(h.config.AccessToken)
51	habitRequest := &lunatask.TrackHabitActivityRequest{
52		PerformedOn: performedOn,
53	}
54
55	resp, err := client.TrackHabitActivity(ctx, habitID, habitRequest)
56	if err != nil {
57		return reportMCPError(fmt.Sprintf("Failed to track habit activity: %v", err))
58	}
59
60	return &mcp.CallToolResult{
61		Content: []mcp.Content{
62			mcp.TextContent{
63				Type: "text",
64				Text: fmt.Sprintf("Habit activity tracked successfully. Status: %s, Message: %s", resp.Status, resp.Message),
65			},
66		},
67	}, nil
68}