agentIDBytes = 16
)
+// Agent is one agent and its directory. The directory holds config.json, the
+// user's instructions in instructions.md, the chat, and the usage file.
+type Agent struct {
+ dir string
+ config AgentConfig
+}
+
+// AgentConfig holds the settings of the config.json of an agent. ID is random,
+// made once when the file is made, and never changes. The cache key comes from
+// the ID, so a rename keeps the prompt cache and two agents with one name do
+// not share a key. Workdir is the directory where the commands of the agent
+// run. Responsibility and Parent are set together for a child agent.
+type AgentConfig struct {
+ Name string `json:"name"`
+ ID string `json:"id"`
+ Model string `json:"model"`
+ Effort string `json:"effort"`
+ Workdir string `json:"workdir"`
+ Responsibility string `json:"responsibility,omitempty"`
+ Parent string `json:"parent,omitempty"`
+}
+
// openAgent reads the config.json of the agent in dir. When the file does not
// exist, it makes the directory and writes the file with the defaults and a new
// ID. A missing field of an existing file takes the default, but the ID must be
config, err := defaultAgentConfig()
if err != nil {
- return nil, err
+ return nil, fmt.Errorf("prepare agent defaults: %w", err)
}
decoder := json.NewDecoder(bytes.NewReader(data))
}, nil
}
-// Agent is one agent and its directory. The directory holds config.json, the
-// user's instructions in instructions.md, the chat, and the usage file.
-type Agent struct {
- dir string
- config AgentConfig
-}
-
// Images returns the shared data-directory image store, also for a child.
func (a *Agent) Images() *ImageStore {
root := a.dir
return &ImageStore{dir: filepath.Join(filepath.Dir(root), imageDirName)}
}
-// CacheKey returns the prompt cache key of every model call of the agent.
-func (a *Agent) CacheKey() string {
- return "onechat-" + a.config.ID
+// Voices returns the shared data-directory audio store, also for a child.
+func (a *Agent) Voices() *VoiceStore {
+ root := a.dir
+ if a.config.Parent != "" {
+ root = filepath.Dir(filepath.Dir(root))
+ }
+
+ return &VoiceStore{dir: filepath.Join(filepath.Dir(root), voiceDirName)}
}
// Prompt returns the system prompt of the agent with the user's instructions
return prompt(a.config.Name, path, instructions), nil
}
+// instructions reads the user's instructions from instructions.md. A missing
+// file means no instructions.
+func (a *Agent) instructions() (string, error) {
+ data, err := os.ReadFile(filepath.Join(a.dir, agentInstructionsFileName))
+ if err != nil && !errors.Is(err, os.ErrNotExist) {
+ return "", fmt.Errorf("read instructions: %w", err)
+ }
+
+ return string(data), nil
+}
+
// Tools returns the tools shared by the turns and compactions of this agent. A
// child has no image output, WhatsApp, child creation, or route tools.
func (a *Agent) Tools() []ModelTool {
return children, nil
}
+// CacheKey returns the prompt cache key of every model call of the agent.
+func (a *Agent) CacheKey() string {
+ return "onechat-" + a.config.ID
+}
+
// CreateChild writes a new direct child with its own ID and the model, effort,
// and working directory of the root. Child and subagent names share a
// namespace. The config is complete before an atomic rename publishes the
return promptSubagent(a.config.Name, instructions), nil
}
-// instructions reads the user's instructions from instructions.md. A missing
-// file means no instructions.
-func (a *Agent) instructions() (string, error) {
- data, err := os.ReadFile(filepath.Join(a.dir, agentInstructionsFileName))
- if err != nil && !errors.Is(err, os.ErrNotExist) {
- return "", fmt.Errorf("read instructions: %w", err)
- }
-
- return string(data), nil
-}
-
-// AgentConfig holds the settings of the config.json of an agent. ID is random,
-// made once when the file is made, and never changes. The cache key comes from
-// the ID, so a rename keeps the prompt cache and two agents with one name do
-// not share a key. Workdir is the directory where the commands of the agent
-// run. Responsibility and Parent are set together for a child agent.
-type AgentConfig struct {
- Name string `json:"name"`
- ID string `json:"id"`
- Model string `json:"model"`
- Effort string `json:"effort"`
- Workdir string `json:"workdir"`
- Responsibility string `json:"responsibility,omitempty"`
- Parent string `json:"parent,omitempty"`
-}
-
// validate makes sure that each setting has a valid value.
func (c AgentConfig) validate() error {
if c.Name == "" || strings.ContainsAny(c.Name, "\r\n") {
return nil
}
+// createAgent writes the config.json of a new agent in dir with the defaults
+// and a new ID.
+func createAgent(dir string) (*Agent, error) {
+ config, err := defaultAgentConfig()
+ if err != nil {
+ return nil, fmt.Errorf("prepare agent defaults: %w", err)
+ }
+
+ return writeAgent(dir, config)
+}
+
+// defaultAgentConfig returns the settings of a new agent, without an ID. The
+// commands run in the home directory of the user.
+func defaultAgentConfig() (AgentConfig, error) {
+ home, err := os.UserHomeDir()
+ if err != nil {
+ return AgentConfig{}, fmt.Errorf("find working directory: %w", err)
+ }
+
+ return AgentConfig{
+ Name: "OneChat",
+ Model: "gpt-6.1-sol",
+ Effort: "medium",
+ Workdir: home,
+ }, nil
+}
+
// agentChildNameValid accepts one word of 2 to 32 ASCII letters with an initial
// capital letter. Child names describe their area.
func agentChildNameValid(name string) bool {
return true
}
-// createAgent writes the config.json of a new agent in dir with the defaults
-// and a new ID.
-func createAgent(dir string) (*Agent, error) {
- config, err := defaultAgentConfig()
- if err != nil {
- return nil, err
- }
-
- return writeAgent(dir, config)
-}
-
// writeAgent gives config a new ID and writes it in dir.
func writeAgent(dir string, config AgentConfig) (*Agent, error) {
id := make([]byte, agentIDBytes)
config: config,
}, nil
}
-
-// defaultAgentConfig returns the settings of a new agent, without an ID. The
-// commands run in the home directory of the user.
-func defaultAgentConfig() (AgentConfig, error) {
- home, err := os.UserHomeDir()
- if err != nil {
- return AgentConfig{}, fmt.Errorf("find working directory: %w", err)
- }
-
- return AgentConfig{
- Name: "OneChat",
- Model: "gpt-6.1-sol",
- Effort: "medium",
- Workdir: home,
- }, nil
-}