X-Git-Url: https://git.giacomolli.uk/onechat/blobdiff_plain/02cdaff8be27f37f44db8892bb12554f2d702323..6e3e9c5c10f3d35bae7e9846334974a09418aef7:/prompt.go diff --git a/prompt.go b/prompt.go index 546a86b..71671c5 100644 --- 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() []ModelTool { +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() []ModelTool { 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() []ModelTool { 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() []ModelTool { 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() []ModelTool { 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() []ModelTool { 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,