package main import ( "encoding/json" "os" "path/filepath" "testing" "github.com/stretchr/testify/require" ) func TestNewAgentKeepsItsIDAcrossOpens(t *testing.T) { dir := filepath.Join(t.TempDir(), "agent") agent, err := openAgent(dir) require.NoError(t, err) require.Len(t, agent.config.ID, 2*agentIDBytes) require.Equal(t, "gpt-6.1-sol", agent.config.Model) require.True(t, filepath.IsAbs(agent.config.Workdir)) again, err := openAgent(dir) require.NoError(t, err) require.Equal(t, agent.config, again.config) info, err := os.Stat(dir) require.NoError(t, err) require.Equal(t, os.FileMode(0o700), info.Mode().Perm()) } func TestNewAgentsGetDifferentIDs(t *testing.T) { first, err := openAgent(t.TempDir()) require.NoError(t, err) second, err := openAgent(t.TempDir()) require.NoError(t, err) require.Equal(t, first.config.Name, second.config.Name) require.NotEqual(t, first.CacheKey(), second.CacheKey()) } func TestRenamedAgentKeepsItsCacheKey(t *testing.T) { dir := t.TempDir() agent, err := openAgent(dir) require.NoError(t, err) key := agent.CacheKey() require.Equal(t, "onechat-"+agent.config.ID, key) config := agent.config config.Name = "Lena" agentWriteTestConfig(t, dir, config) renamed, err := openAgent(dir) require.NoError(t, err) require.Equal(t, "Lena", renamed.config.Name) require.Equal(t, key, renamed.CacheKey()) } func TestAgentConfigErrors(t *testing.T) { testCases := []struct { name string config string err string }{ { name: "unknown field", config: `{"id": "00112233445566778899aabbccddeeff", "nmae": "Lena"}`, err: `unknown field "nmae"`, }, { name: "missing id", config: `{"name": "Lena"}`, err: "id must be 32 hexadecimal digits", }, { name: "relative workdir", config: `{"id": "00112233445566778899aabbccddeeff", "workdir": "src"}`, err: `workdir "src" is not an absolute path`, }, { name: "name of two lines", config: `{"id": "00112233445566778899aabbccddeeff", "name": "Le\nna"}`, err: "name must be one line of text", }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { dir := t.TempDir() require.NoError(t, os.WriteFile(filepath.Join(dir, "config.json"), []byte(tc.config), 0o600)) _, err := openAgent(dir) require.ErrorContains(t, err, tc.err) }) } } func TestAgentPromptReadsTheInstructionsEachTime(t *testing.T) { dir := t.TempDir() agent, err := openAgent(dir) require.NoError(t, err) text, err := agent.Prompt() require.NoError(t, err) require.Equal(t, prompt(agent.config.Name, filepath.Join(dir, agentInstructionsFileName), ""), text) require.NoError(t, os.WriteFile(filepath.Join(dir, agentInstructionsFileName), []byte("I am Lena.\n"), 0o600)) text, err = agent.Prompt() require.NoError(t, err) require.Equal(t, prompt(agent.config.Name, filepath.Join(dir, agentInstructionsFileName), "I am Lena."), text) } func TestAgentPromptUsesAnAbsoluteInstructionsPath(t *testing.T) { dir := t.TempDir() workdir, err := os.Getwd() require.NoError(t, err) relative, err := filepath.Rel(workdir, dir) require.NoError(t, err) require.False(t, filepath.IsAbs(relative)) agent, err := openAgent(relative) require.NoError(t, err) text, err := agent.Prompt() require.NoError(t, err) require.Contains(t, text, "The user's instructions live in the file "+filepath.Join(dir, agentInstructionsFileName)+",") } // agentWriteTestConfig writes config as the config.json of the agent in dir. func agentWriteTestConfig(t *testing.T, dir string, config AgentConfig) { t.Helper() data, err := json.Marshal(config) require.NoError(t, err) require.NoError(t, os.WriteFile(filepath.Join(dir, "config.json"), data, 0o600)) }