blob: 5351538e3d41ddbec2bf57720fb977a144896851 [file] [log] [blame]
Philip Zeyligerc17ffe32025-06-05 19:49:13 -07001package claudetool
2
3import (
4 "context"
5 "encoding/json"
6 "fmt"
7 "strings"
8 "time"
9
10 "sketch.dev/llm"
11 "sketch.dev/skabandclient"
12)
13
14// CreateSessionHistoryTools creates the session history tools when skaband is available
15func CreateSessionHistoryTools(skabandClient *skabandclient.SkabandClient, sessionID, currentRepo string) []*llm.Tool {
16 if skabandClient == nil {
17 return nil
18 }
19
20 return []*llm.Tool{
21 listRecentSketchSessionsTool(skabandClient, sessionID, currentRepo),
22 readSketchSessionTool(skabandClient, sessionID),
23 }
24}
25
26func listRecentSketchSessionsTool(client *skabandclient.SkabandClient, sessionID, currentRepo string) *llm.Tool {
27 return &llm.Tool{
28 Name: "list_recent_sketch_sessions",
29 Description: fmt.Sprintf(`Lists recent Sketch sessions%s. Use this tool when the user refers to previous sketch sessions, asks about recent work, or wants to see their session history. This helps you understand what work has been done previously and can provide context for continuing or reviewing past sessions.`, func() string {
30 if currentRepo != "" {
31 return " for the current repository (" + currentRepo + ")"
32 }
33 return ""
34 }()),
35 InputSchema: json.RawMessage(`{
36 "type": "object",
37 "properties": {},
38 "required": []
39 }`),
40 Run: func(ctx context.Context, input json.RawMessage) ([]llm.Content, error) {
41 // Use 60 second timeout for skaband requests
42 ctxWithTimeout, cancel := context.WithTimeout(ctx, 60*time.Second)
43 defer cancel()
44
45 markdownTable, err := client.ListRecentSketchSessionsMarkdown(ctxWithTimeout, currentRepo, sessionID)
46 if err != nil {
47 return nil, fmt.Errorf("failed to list recent sessions: %w", err)
48 }
49
50 // Check if no sessions found (markdown will contain "No sessions found")
51 if strings.Contains(markdownTable, "No sessions found") {
52 return llm.TextContent("No recent sketch sessions found."), nil
53 }
54
55 // Use the markdown table from the server
56 var result strings.Builder
57 result.WriteString("Recent sketch sessions:\n\n")
58 result.WriteString(markdownTable)
59 result.WriteString("\n\nUse the `read_sketch_session` tool with a session ID to see the full conversation history.")
60
61 return llm.TextContent(result.String()), nil
62 },
63 }
64}
65
66func readSketchSessionTool(client *skabandclient.SkabandClient, sessionID string) *llm.Tool {
67 return &llm.Tool{
68 Name: "read_sketch_session",
69 Description: `Reads the full conversation history of a specific Sketch session. Use this tool when the user mentions a specific sketch session ID, wants to review what was done in a previous session, or needs to understand the context from a past conversation to continue work.`,
70 InputSchema: json.RawMessage(`{
71 "type": "object",
72 "properties": {
73 "session_id": {
74 "type": "string",
75 "description": "The ID of the sketch session to read"
76 }
77 },
78 "required": ["session_id"]
79 }`),
80 Run: func(ctx context.Context, input json.RawMessage) ([]llm.Content, error) {
81 // Use 60 second timeout for skaband requests
82 ctxWithTimeout, cancel := context.WithTimeout(ctx, 60*time.Second)
83 defer cancel()
84
85 var params struct {
86 SessionID string `json:"session_id"`
87 }
88 if err := json.Unmarshal(input, &params); err != nil {
89 return nil, fmt.Errorf("failed to parse input: %w", err)
90 }
91
92 if params.SessionID == "" {
93 return nil, fmt.Errorf("session_id is required")
94 }
95
96 formattedResponse, err := client.ReadSketchSession(ctxWithTimeout, params.SessionID, sessionID)
97 if err != nil {
98 return nil, fmt.Errorf("failed to read session: %w", err)
99 }
100
101 // Server now returns formatted text directly
102 return llm.TextContent(*formattedResponse), nil
103 },
104 }
105}