Files

1 line
8.5 KiB
JSON

{"repo": "ccq1/termiagent", "files": {"internal/config/config_test.go": {"d76d62f1f8003c5d87680831b3ee5daa7b055885": {"t": 1785746067.1693203, "n": 4117, "h": "86769f8b7e9ffb94", "c": "package config\n\nimport (\n\t\"encoding/json\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestLoadCreatesDefaultUserConfigAndTaskDirectory(t *testing.T) {\n\thome := t.TempDir()\n\tt.Setenv(\"HOME\", home)\n\tt.Setenv(\"TERMI_CONFIG\", \"\")\n\tt.Setenv(\"TERMI_ENDPOINT\", \"\")\n\tt.Setenv(\"TERMI_MODEL\", \"\")\n\tt.Setenv(\"TERMI_API_KEY\", \"\")\n\tt.Setenv(\"TERMI_PROXY\", \"\")\n\n\tcfg, err := Load()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\twantConfig := filepath.Join(home, \".termi\", \"config.json\")\n\tif cfg.ConfigPath != wantConfig || cfg.TaskDir != filepath.Join(home, \".termi\", \"tasks\") {\n\t\tt.Fatalf(\"unexpected user paths: %#v\", cfg)\n\t}\n\tinfo, err := os.Stat(wantConfig)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif info.Mode().Perm() != 0o600 {\n\t\tt.Fatalf(\"config mode=%o\", info.Mode().Perm())\n\t}\n\tdata, err := os.ReadFile(wantConfig)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tvar stored map[string]any\n\tif err := json.Unmarshal(data, &stored); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif stored[\"version\"] != float64(4) || stored[\"max_model_output_tokens\"] != float64(4096) || stored[\"auto_review\"] == nil || stored[\"models\"] == nil || stored[\"memories\"] == nil || stored[\"mcp\"] == nil || stored[\"plugins\"] == nil {\n\t\tt.Fatalf(\"config is not future-ready: %s\", data)\n\t}\n\tmemorySettings, ok := stored[\"memories\"].(map[string]any)\n\tif !ok || len(memorySettings) != 1 || memorySettings[\"enabled\"] != false {\n\t\tt.Fatalf(\"memory config is not a single global switch: %s\", data)\n\t}\n\tif cfg.UILanguage != \"zh-CN\" || cfg.ModelLanguage != \"zh-CN\" || stored[\"ui_language\"] != \"zh-CN\" || stored[\"model_output_language\"] != \"zh-CN\" {\n\t\tt.Fatalf(\"language defaults are missing: cfg=%#v stored=%s\", cfg, data)\n\t}\n\tif cfg.Memories.UseMemories || cfg.Memories.GenerateMemories || !cfg.Memories.DisableOnExternalContext || cfg.Memories.MaxInjectedChars != 6000 {\n\t\tt.Fatalf(\"memory defaults are missing: %#v\", cfg.Memories)\n\t}\n\tif stat, err := os.Stat(cfg.TaskDir); err != nil || !stat.IsDir() {\n\t\tt.Fatalf(\"tasks directory missing: stat=%v err=%v\", stat, err)\n\t}\n}\n\nfunc TestLoadMigratesLegacyModelEndpointToProvider(t *testing.T) {\n\thome := t.TempDir()\n\tt.Setenv(\"HOME\", home)\n\tconfigDir := filepath.Join(home, \".termi\")\n\tif err := os.MkdirAll(configDir, 0o700); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tlegacy := `{\"version\":1,\"active_model\":\"deep\",\"models\":[{\"id\":\"deep\",\"name\":\"DeepSeek\",\"endpoint\":\"https://api.deepseek.com\",\"model\":\"deepseek-v4-flash\",\"api_key\":\"secret\",\"proxy\":\"direct\",\"max_tokens\":2048}],\"memories\":{\"use_memories\":true}}`\n\tif err := os.WriteFile(filepath.Join(configDir, \"config.json\"), []byte(legacy), 0o600); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tcfg, err := Load()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif cfg.Version != 4 || len(cfg.Providers) != 0 || cfg.Models[0].Provider != \"deepseek\" || cfg.Models[0].ContextWindow != 128000 {\n\t\tt.Fatalf(\"legacy config was not migrated: %#v\", cfg)\n\t}\n\tif cfg.APIKey != \"secret\" || cfg.ProviderType != \"deepseek\" || cfg.Thinking != \"auto\" {\n\t\tt.Fatalf(\"active provider was not resolved: %#v\", cfg)\n\t}\n\tif !cfg.Memories.Enabled || !cfg.Memories.UseMemories || !cfg.Memories.GenerateMemories || !cfg.Memories.DisableOnExternalContext {\n\t\tt.Fatalf(\"legacy split memory settings were not unified: %#v\", cfg.Memories)\n\t}\n\tif err := Save(cfg); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tsaved, err := os.ReadFile(cfg.ConfigPath)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif strings.Count(string(saved), `\"secret\"`) != 1 || strings.Contains(string(saved), `\"endpoint\"`) || strings.Contains(string(saved), `\"provider_id\"`) {\n\t\tt.Fatalf(\"legacy provider secrets were duplicated after migration: %s\", saved)\n\t}\n}\n\nfunc TestConfiguredRequiresModelAndCompatibleEndpoint(t *testing.T) {\n\tcfg := Config{ProviderType: \"openai_compatible\", Model: \"qwen3-coder\"}\n\tif cfg.Configured() {\n\t\tt.Fatal(\"compatible model without an endpoint should not be configured\")\n\t}\n\tcfg.Endpoint = \"http://localhost:8000/v1\"\n\tif !cfg.Configured() {\n\t\tt.Fatal(\"keyless compatible endpoint should be configured\")\n\t}\n\tcfg.ProviderType, cfg.Endpoint = \"deepseek\", DefaultProviderBaseURL(\"deepseek\")\n\tif !cfg.Configured() {\n\t\tt.Fatal(\"built-in provider should be configured\")\n\t}\n}\n"}, "fe88c5bf48824a8d19250e42cf82586ff00b6e86": {"t": 1785759453.338773, "n": 3579, "h": "5559792f54b1eada", "c": "package config\n\nimport (\n\t\"encoding/json\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestLoadCreatesDefaultUserConfigAndTaskDirectory(t *testing.T) {\n\thome := t.TempDir()\n\tt.Setenv(\"HOME\", home)\n\tt.Setenv(\"TERMI_CONFIG\", \"\")\n\tt.Setenv(\"TERMI_ENDPOINT\", \"\")\n\tt.Setenv(\"TERMI_MODEL\", \"\")\n\tt.Setenv(\"TERMI_API_KEY\", \"\")\n\tt.Setenv(\"TERMI_PROXY\", \"\")\n\n\tcfg, err := Load()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\twantConfig := filepath.Join(home, \".termi\", \"config.json\")\n\tif cfg.ConfigPath != wantConfig || cfg.TaskDir != filepath.Join(home, \".termi\", \"tasks\") {\n\t\tt.Fatalf(\"unexpected user paths: %#v\", cfg)\n\t}\n\tinfo, err := os.Stat(wantConfig)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif info.Mode().Perm() != 0o600 {\n\t\tt.Fatalf(\"config mode=%o\", info.Mode().Perm())\n\t}\n\tdata, err := os.ReadFile(wantConfig)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tvar stored map[string]any\n\tif err := json.Unmarshal(data, &stored); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif stored[\"version\"] != float64(4) || stored[\"max_model_output_tokens\"] != float64(4096) || stored[\"auto_review\"] == nil || stored[\"models\"] == nil || stored[\"memories\"] == nil || stored[\"mcp\"] == nil || stored[\"plugins\"] == nil {\n\t\tt.Fatalf(\"config is not future-ready: %s\", data)\n\t}\n\tmemorySettings, ok := stored[\"memories\"].(map[string]any)\n\tif !ok || len(memorySettings) != 1 || memorySettings[\"enabled\"] != false {\n\t\tt.Fatalf(\"memory config is not a single global switch: %s\", data)\n\t}\n\tif cfg.UILanguage != \"zh-CN\" || cfg.ModelLanguage != \"zh-CN\" || stored[\"ui_language\"] != \"zh-CN\" || stored[\"model_output_language\"] != \"zh-CN\" {\n\t\tt.Fatalf(\"language defaults are missing: cfg=%#v stored=%s\", cfg, data)\n\t}\n\tif cfg.Memories.UseMemories || cfg.Memories.GenerateMemories || !cfg.Memories.DisableOnExternalContext || cfg.Memories.MaxInjectedChars != 6000 {\n\t\tt.Fatalf(\"memory defaults are missing: %#v\", cfg.Memories)\n\t}\n\tif stat, err := os.Stat(cfg.TaskDir); err != nil || !stat.IsDir() {\n\t\tt.Fatalf(\"tasks directory missing: stat=%v err=%v\", stat, err)\n\t}\n}\n\nfunc TestLoadMigratesLegacyModelEndpointToProvider(t *testing.T) {\n\thome := t.TempDir()\n\tt.Setenv(\"HOME\", home)\n\tconfigDir := filepath.Join(home, \".termi\")\n\tif err := os.MkdirAll(configDir, 0o700); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tlegacy := `{\"version\":1,\"active_model\":\"deep\",\"models\":[{\"id\":\"deep\",\"name\":\"DeepSeek\",\"endpoint\":\"https://api.deepseek.com\",\"model\":\"deepseek-v4-flash\",\"api_key\":\"secret\",\"proxy\":\"direct\",\"max_tokens\":2048}],\"memories\":{\"use_memories\":true}}`\n\tif err := os.WriteFile(filepath.Join(configDir, \"config.json\"), []byte(legacy), 0o600); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tcfg, err := Load()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif cfg.Version != 4 || len(cfg.Providers) != 0 || cfg.Models[0].Provider != \"deepseek\" || cfg.Models[0].ContextWindow != 128000 {\n\t\tt.Fatalf(\"legacy config was not migrated: %#v\", cfg)\n\t}\n\tif cfg.APIKey != \"secret\" || cfg.ProviderType != \"deepseek\" || cfg.Thinking != \"auto\" {\n\t\tt.Fatalf(\"active provider was not resolved: %#v\", cfg)\n\t}\n\tif !cfg.Memories.Enabled || !cfg.Memories.UseMemories || !cfg.Memories.GenerateMemories || !cfg.Memories.DisableOnExternalContext {\n\t\tt.Fatalf(\"legacy split memory settings were not unified: %#v\", cfg.Memories)\n\t}\n\tif err := Save(cfg); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tsaved, err := os.ReadFile(cfg.ConfigPath)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif strings.Count(string(saved), `\"secret\"`) != 1 || strings.Contains(string(saved), `\"endpoint\"`) || strings.Contains(string(saved), `\"provider_id\"`) {\n\t\tt.Fatalf(\"legacy provider secrets were duplicated after migration: %s\", saved)\n\t}\n}\n"}}}}