blob: f5bf0e7f99287846e918c564a6338886433f244a [file] [log] [blame]
Josh Bleecher Snyder31785ae2025-05-06 01:50:58 +00001package claudetool
2
3import (
4 "context"
5 _ "embed"
6 "encoding/json"
7 "fmt"
8 "log/slog"
9 "strings"
10 "text/template"
11
12 "sketch.dev/llm"
13 "sketch.dev/llm/conversation"
14)
15
16// KnowledgeBase provides on-demand specialized knowledge to the agent.
17var KnowledgeBase = &llm.Tool{
18 Name: kbName,
19 Description: kbDescription,
20 InputSchema: llm.MustSchema(kbInputSchema),
21 Run: kbRun,
22}
23
24// TODO: BYO knowledge bases? could do that for strings.Lines, for example.
25// TODO: support Q&A mode instead of reading full text in?
26
27const (
28 kbName = "knowledge_base"
29 kbDescription = `Retrieve specialized information that you need but don't have in your context.
30
31When to use this tool:
32
33For the "sketch" topic:
34- The user is asking how to USE Sketch itself (not asking Sketch to perform a task)
35- The user has questions about Sketch functionality, setup, or capabilities
36- The user needs help with Sketch-specific concepts like running commands, secrets management, git integration
37- The query is about "How do I do X in Sketch?" or "Is it possible to Y in Sketch?" or just "Help"
38- The user is confused about how a Sketch feature works or how to access it
Pokey Rule6525d822025-05-15 14:55:28 +010039- You need to know how to interact with the host machine, ed forwarding a port or pulling changes that the user has made outside of Sketch
Josh Bleecher Snyder31785ae2025-05-06 01:50:58 +000040
41For the "strings_lines" topic:
42- Any mentions of strings.Lines in the code, by the codereview, or by the user
43- When implementing code that iterates over lines in a Go string
44
45Available topics:
46- sketch: documentation on Sketch usage
47- strings_lines: details about the Go strings.Lines API
48`
49
50 kbInputSchema = `
51{
52 "type": "object",
53 "required": ["topic"],
54 "properties": {
55 "topic": {
56 "type": "string",
57 "description": "Topic to retrieve information about",
58 "enum": ["sketch", "strings_lines"]
59 }
60 }
61}
62`
63)
64
65type kbInput struct {
66 Topic string `json:"topic"`
67}
68
69//go:embed kb/sketch.txt
70var sketchContent string
71
72//go:embed kb/strings_lines.txt
73var stringsLinesContent string
74
75var sketchTemplate = template.Must(template.New("sketch").Parse(sketchContent))
76
77func kbRun(ctx context.Context, m json.RawMessage) ([]llm.Content, error) {
78 var input kbInput
79 if err := json.Unmarshal(m, &input); err != nil {
80 return nil, err
81 }
82
83 // Sanitize topic name (simple lowercase conversion for now)
84 topic := strings.ToLower(strings.TrimSpace(input.Topic))
85 slog.InfoContext(ctx, "knowledge base request", "topic", topic)
86
87 // Process content based on topic
88 switch input.Topic {
89 case "sketch":
90 info := conversation.ToolCallInfoFromContext(ctx)
91 sessionID, _ := info.Convo.ExtraData["session_id"].(string)
92 branch, _ := info.Convo.ExtraData["branch"].(string)
93 dot := struct {
94 SessionID string
95 Branch string
96 }{
97 SessionID: sessionID,
98 Branch: branch,
99 }
100 buf := new(strings.Builder)
101 if err := sketchTemplate.Execute(buf, dot); err != nil {
102 return nil, fmt.Errorf("template execution error: %w", err)
103 }
104 return llm.TextContent(buf.String()), nil
105 case "strings_lines":
106 // No special processing for other topics
107 return llm.TextContent(stringsLinesContent), nil
108 default:
109 return nil, fmt.Errorf("unknown topic: %s", input.Topic)
110 }
111}