claudetool: remove knowledge base, focus on about sketch
We should have a more general kb.
Meanwhile, this is important and standalone.
Make it all clearer and sharper.
diff --git a/claudetool/about_sketch.go b/claudetool/about_sketch.go
new file mode 100644
index 0000000..15a4059
--- /dev/null
+++ b/claudetool/about_sketch.go
@@ -0,0 +1,64 @@
+package claudetool
+
+import (
+ "context"
+ _ "embed"
+ "encoding/json"
+ "fmt"
+ "log/slog"
+ "strings"
+ "text/template"
+
+ "sketch.dev/llm"
+ "sketch.dev/llm/conversation"
+)
+
+// AboutSketch provides information about how to use Sketch.
+var AboutSketch = &llm.Tool{
+ Name: "about_sketch",
+ Description: aboutSketchDescription,
+ InputSchema: llm.EmptySchema(),
+ Run: aboutSketchRun,
+}
+
+// TODO: BYO knowledge bases? could do that for strings.Lines, for example.
+// TODO: support Q&A mode instead of reading full text in?
+
+const (
+ aboutSketchDescription = `Provides information about Sketch.
+
+When to use this tool:
+
+- The user is asking how to USE Sketch itself (not asking Sketch to perform a task)
+- The user has questions about Sketch functionality, setup, or capabilities
+- The user needs help with Sketch-specific concepts like running commands, secrets management, git integration
+- The query is about "How do I do X in Sketch?" or "Is it possible to Y in Sketch?" or just "Help"
+- The user is confused about how a Sketch feature works or how to access it
+- You need to know how to interact with the host environment, e.g. port forwarding or pulling changes the user has made outside of Sketch
+`
+)
+
+//go:embed about_sketch.txt
+var aboutSketch string
+
+var aboutSketchTemplate = template.Must(template.New("sketch").Parse(aboutSketch))
+
+func aboutSketchRun(ctx context.Context, m json.RawMessage) ([]llm.Content, error) {
+ slog.InfoContext(ctx, "about_sketch called")
+
+ info := conversation.ToolCallInfoFromContext(ctx)
+ sessionID, _ := info.Convo.ExtraData["session_id"].(string)
+ branch, _ := info.Convo.ExtraData["branch"].(string)
+ dot := struct {
+ SessionID string
+ Branch string
+ }{
+ SessionID: sessionID,
+ Branch: branch,
+ }
+ buf := new(strings.Builder)
+ if err := aboutSketchTemplate.Execute(buf, dot); err != nil {
+ return nil, fmt.Errorf("template execution error: %w", err)
+ }
+ return llm.TextContent(buf.String()), nil
+}
diff --git a/claudetool/kb/sketch.txt b/claudetool/about_sketch.txt
similarity index 100%
rename from claudetool/kb/sketch.txt
rename to claudetool/about_sketch.txt
diff --git a/claudetool/browse/browse.go b/claudetool/browse/browse.go
index 40974e3..fdc83c6 100644
--- a/claudetool/browse/browse.go
+++ b/claudetool/browse/browse.go
@@ -531,7 +531,7 @@
"properties": {
"selector": {
"type": "string",
- "description": "CSS selector for the element to screenshot (optional)"
+ "description": "CSS selector for the element to screenshot (optional)"
},
"format": {
"type": "string",
@@ -961,11 +961,8 @@
return &llm.Tool{
Name: "browser_clear_console_logs",
Description: "Clear all captured browser console logs",
- InputSchema: json.RawMessage(`{
- "type": "object",
- "properties": {}
- }`),
- Run: b.clearConsoleLogsRun,
+ InputSchema: llm.EmptySchema(),
+ Run: b.clearConsoleLogsRun,
}
}
diff --git a/claudetool/codereview/differential.go b/claudetool/codereview/differential.go
index f7ec670..e3a819a 100644
--- a/claudetool/codereview/differential.go
+++ b/claudetool/codereview/differential.go
@@ -31,7 +31,7 @@
Name: "codereview",
Description: `Run an automated code review.`,
// If you modify this, update the termui template for prettier rendering.
- InputSchema: llm.MustSchema(`{"type": "object", "properties": {}}`),
+ InputSchema: llm.EmptySchema(),
Run: r.Run,
}
return spec
diff --git a/claudetool/kb/strings_lines.txt b/claudetool/kb/strings_lines.txt
deleted file mode 100644
index 4d237ae..0000000
--- a/claudetool/kb/strings_lines.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-`strings.Lines` — added in Go 1.24
-
-- `func Lines(s string) iter.Seq[string]`
-- Lazily yields successive newline-terminated substrings of `s`. *Includes* the exact trailing `\n`/`\r\n`; if the input ends without a newline the final element is unterminated.
-- Zero copying: each value is just a slice header into `s`, so iteration is O(1) memory.
-
-Idiomatic loop:
-
-```go
-for line := range strings.Lines(buf) {
- handle(line)
-}
-```
-
-### How it differs from common alternatives
-
-- strings.Split – eager `[]string` allocation; caller chooses the separator (newline usually `"\n"`); separator *removed*, so you lose information about line endings and trailing newline presence.
-- strings.SplitSeq – same lazy `iter.Seq[string]` style as `Lines`, but again the caller supplies the separator and it is dropped; use this for arbitrary delimiters.
-- bufio.Scanner – token-oriented reader for any `io.Reader`. Default split function treats `\n` as the delimiter and strips it, so newline bytes are not preserved. Each token is copied into new memory, and there is a 64 KiB default token-size cap (adjustable). Scanner is the choice when the data is coming from a stream rather than an in-memory string.
-
-Use `strings.Lines` by default when the data is already in a string. (bytes.Lines provides the []byte equivalent.)
-
-Fallback to `Split` if you need a slice of lines in memory, to `SplitSeq` for lazy iteration over other separators, and to `bufio.Scanner` for streaming input where newline bytes are irrelevant.
diff --git a/claudetool/knowledge_base.go b/claudetool/knowledge_base.go
deleted file mode 100644
index f5bf0e7..0000000
--- a/claudetool/knowledge_base.go
+++ /dev/null
@@ -1,111 +0,0 @@
-package claudetool
-
-import (
- "context"
- _ "embed"
- "encoding/json"
- "fmt"
- "log/slog"
- "strings"
- "text/template"
-
- "sketch.dev/llm"
- "sketch.dev/llm/conversation"
-)
-
-// KnowledgeBase provides on-demand specialized knowledge to the agent.
-var KnowledgeBase = &llm.Tool{
- Name: kbName,
- Description: kbDescription,
- InputSchema: llm.MustSchema(kbInputSchema),
- Run: kbRun,
-}
-
-// TODO: BYO knowledge bases? could do that for strings.Lines, for example.
-// TODO: support Q&A mode instead of reading full text in?
-
-const (
- kbName = "knowledge_base"
- kbDescription = `Retrieve specialized information that you need but don't have in your context.
-
-When to use this tool:
-
-For the "sketch" topic:
-- The user is asking how to USE Sketch itself (not asking Sketch to perform a task)
-- The user has questions about Sketch functionality, setup, or capabilities
-- The user needs help with Sketch-specific concepts like running commands, secrets management, git integration
-- The query is about "How do I do X in Sketch?" or "Is it possible to Y in Sketch?" or just "Help"
-- The user is confused about how a Sketch feature works or how to access it
-- 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
-
-For the "strings_lines" topic:
-- Any mentions of strings.Lines in the code, by the codereview, or by the user
-- When implementing code that iterates over lines in a Go string
-
-Available topics:
-- sketch: documentation on Sketch usage
-- strings_lines: details about the Go strings.Lines API
-`
-
- kbInputSchema = `
-{
- "type": "object",
- "required": ["topic"],
- "properties": {
- "topic": {
- "type": "string",
- "description": "Topic to retrieve information about",
- "enum": ["sketch", "strings_lines"]
- }
- }
-}
-`
-)
-
-type kbInput struct {
- Topic string `json:"topic"`
-}
-
-//go:embed kb/sketch.txt
-var sketchContent string
-
-//go:embed kb/strings_lines.txt
-var stringsLinesContent string
-
-var sketchTemplate = template.Must(template.New("sketch").Parse(sketchContent))
-
-func kbRun(ctx context.Context, m json.RawMessage) ([]llm.Content, error) {
- var input kbInput
- if err := json.Unmarshal(m, &input); err != nil {
- return nil, err
- }
-
- // Sanitize topic name (simple lowercase conversion for now)
- topic := strings.ToLower(strings.TrimSpace(input.Topic))
- slog.InfoContext(ctx, "knowledge base request", "topic", topic)
-
- // Process content based on topic
- switch input.Topic {
- case "sketch":
- info := conversation.ToolCallInfoFromContext(ctx)
- sessionID, _ := info.Convo.ExtraData["session_id"].(string)
- branch, _ := info.Convo.ExtraData["branch"].(string)
- dot := struct {
- SessionID string
- Branch string
- }{
- SessionID: sessionID,
- Branch: branch,
- }
- buf := new(strings.Builder)
- if err := sketchTemplate.Execute(buf, dot); err != nil {
- return nil, fmt.Errorf("template execution error: %w", err)
- }
- return llm.TextContent(buf.String()), nil
- case "strings_lines":
- // No special processing for other topics
- return llm.TextContent(stringsLinesContent), nil
- default:
- return nil, fmt.Errorf("unknown topic: %s", input.Topic)
- }
-}