]> git.giacomolli.uk - onechat/blobdiff - prompt.go
Store the subagents and read them with zoom
[onechat] / prompt.go
index 373aab632818b73ae802eb1767f53befda1b9f6c..71671c510caa6b0c3ec837de6555f1ecc5807e76 100644 (file)
--- a/prompt.go
+++ b/prompt.go
@@ -9,17 +9,17 @@ const (
        // promptName stands for the name of the agent in promptText.
        promptName = "{name}"
 
-       // taskSentence is the sentence of promptText that gets instructionsClause
-       // when the user has instructions.
-       taskSentence = "Do the user's tasks yourself, with your tools."
+       // promptTaskSentence is the sentence of promptText that gets
+       // promptInstructionsClause when the user has instructions.
+       promptTaskSentence = "Do the user's tasks yourself, with your tools."
 
-       // instructionsClause points to the instructions of the user at the end
-       // of the prompt.
-       instructionsClause = ", following the user's instructions\nat the end of this prompt: who they are, how their files are organized and how\nthey want work done"
+       // promptInstructionsClause points to the instructions of the user at
+       // the end of the prompt.
+       promptInstructionsClause = ", following the user's instructions\nat the end of this prompt: who they are, how their files are organized and how\nthey want work done"
 
-       // instructionsHeading starts the instructions of the user after
+       // promptInstructionsHeading starts the instructions of the user after
        // promptText.
-       instructionsHeading = "\n\n# The user's instructions\n\n"
+       promptInstructionsHeading = "\n\n# The user's instructions\n\n"
 )
 
 // promptText is the system prompt of the reference design, nearly word for
@@ -58,6 +58,7 @@ long for one message is split over several in a row.
 Tools:
 - zoom(id, n) opens line id+n into the two lines it was made from;
 - zoom(id, 1) gives message id whole
+- zoom("Name") gives an agent's whole chat
 - date(id) gives the date and time of message id
 
 # Turns
@@ -126,23 +127,24 @@ func prompt(name, instructions string) string {
                return text
        }
 
-       text = strings.Replace(text, taskSentence, strings.TrimSuffix(taskSentence, ".")+instructionsClause+".", 1)
+       text = strings.Replace(text, promptTaskSentence, strings.TrimSuffix(promptTaskSentence, ".")+promptInstructionsClause+".", 1)
 
-       return text + instructionsHeading + instructions
+       return text + promptInstructionsHeading + instructions
 }
 
-// agentTools returns the function tools of every call: zoom, date, shell,
+// promptTools returns the function tools of every call: zoom, date, shell,
 // read, write, and edit. A compaction sends them too and never calls them,
 // because a change of the tools ends the shared prompt cache.
-func agentTools() []Tool {
-       return []Tool{
+func promptTools() []ModelTool {
+       return []ModelTool{
                {
                        Type:        "function",
                        Name:        "zoom",
-                       Description: "Open the line id+n of the view into the two lines of n/2 under it; n = 1 gives the message whole.",
-                       Parameters: objectSchema(map[string]any{
-                               "id": integerSchema("The first message of the line: a multiple of n."),
-                               "n":  integerSchema("The number of messages of the line: a power of 2."),
+                       Description: "Open the line id+n of the view into the two lines of n/2 under it; n = 1 gives the message whole. With an agent's name, give that agent's whole chat.",
+                       Parameters: promptObjectSchema(map[string]any{
+                               "id":   promptIntegerSchema("The first message of the line: a multiple of n."),
+                               "n":    promptIntegerSchema("The number of messages of the line: a power of 2."),
+                               "name": promptNullableStringSchema("The name of an agent whose whole chat to give, or null for the line id+n."),
                        }),
                        Strict: true,
                },
@@ -150,8 +152,8 @@ func agentTools() []Tool {
                        Type:        "function",
                        Name:        "date",
                        Description: "The date and time of message id.",
-                       Parameters: objectSchema(map[string]any{
-                               "id": integerSchema("The message."),
+                       Parameters: promptObjectSchema(map[string]any{
+                               "id": promptIntegerSchema("The message."),
                        }),
                        Strict: true,
                },
@@ -159,8 +161,8 @@ func agentTools() []Tool {
                        Type:        "function",
                        Name:        "shell",
                        Description: "Run a command with bash, as the user, in the working directory, with no input. Gives its output and error output, and its exit status when it fails.",
-                       Parameters: objectSchema(map[string]any{
-                               "command": stringSchema("The bash command."),
+                       Parameters: promptObjectSchema(map[string]any{
+                               "command": promptStringSchema("The bash command."),
                        }),
                        Strict: true,
                },
@@ -168,8 +170,8 @@ func agentTools() []Tool {
                        Type:        "function",
                        Name:        "read",
                        Description: "Read a text file.",
-                       Parameters: objectSchema(map[string]any{
-                               "path": stringSchema("The file, absolute or relative to the working directory."),
+                       Parameters: promptObjectSchema(map[string]any{
+                               "path": promptStringSchema("The file, absolute or relative to the working directory."),
                        }),
                        Strict: true,
                },
@@ -177,9 +179,9 @@ func agentTools() []Tool {
                        Type:        "function",
                        Name:        "write",
                        Description: "Write a text file whole, replacing it when it exists. Makes the missing directories.",
-                       Parameters: objectSchema(map[string]any{
-                               "path": stringSchema("The file, absolute or relative to the working directory."),
-                               "text": stringSchema("The whole new content."),
+                       Parameters: promptObjectSchema(map[string]any{
+                               "path": promptStringSchema("The file, absolute or relative to the working directory."),
+                               "text": promptStringSchema("The whole new content."),
                        }),
                        Strict: true,
                },
@@ -187,19 +189,19 @@ func agentTools() []Tool {
                        Type:        "function",
                        Name:        "edit",
                        Description: "Replace the one occurrence of old in a text file with new.",
-                       Parameters: objectSchema(map[string]any{
-                               "path": stringSchema("The file, absolute or relative to the working directory."),
-                               "old":  stringSchema("The exact text to replace. It must occur once in the file."),
-                               "new":  stringSchema("The text that replaces old."),
+                       Parameters: promptObjectSchema(map[string]any{
+                               "path": promptStringSchema("The file, absolute or relative to the working directory."),
+                               "old":  promptStringSchema("The exact text to replace. It must occur once in the file."),
+                               "new":  promptStringSchema("The text that replaces old."),
                        }),
                        Strict: true,
                },
        }
 }
 
-// objectSchema returns a strict JSON schema of an object whose properties are
-// all required.
-func objectSchema(properties map[string]any) map[string]any {
+// promptObjectSchema returns a strict JSON schema of an object whose properties
+// are all required.
+func promptObjectSchema(properties map[string]any) map[string]any {
        required := make([]string, 0, len(properties))
        for name := range properties {
                required = append(required, name)
@@ -215,16 +217,24 @@ func objectSchema(properties map[string]any) map[string]any {
        }
 }
 
-// integerSchema returns the JSON schema of an integer.
-func integerSchema(description string) map[string]any {
+// promptIntegerSchema returns the JSON schema of an integer.
+func promptIntegerSchema(description string) map[string]any {
        return map[string]any{
                "type":        "integer",
                "description": description,
        }
 }
 
-// stringSchema returns the JSON schema of a string.
-func stringSchema(description string) map[string]any {
+// promptNullableStringSchema returns the JSON schema of a string or null.
+func promptNullableStringSchema(description string) map[string]any {
+       return map[string]any{
+               "type":        []string{"string", "null"},
+               "description": description,
+       }
+}
+
+// promptStringSchema returns the JSON schema of a string.
+func promptStringSchema(description string) map[string]any {
        return map[string]any{
                "type":        "string",
                "description": description,