<repo><f p="app.go"><![CDATA[package main
import (
 "WAILS_SVELTE_FINAL/internal/common"
 "WAILS_SVELTE_FINAL/internal/config"
 "WAILS_SVELTE_FINAL/internal/service"
 "context"
)
type App struct {
 ctx context.Context
 botService *service.BotService
 settingsService *service.SettingsService
 processorService *service.ProcessorService
 dialogService *service.DialogService
 chatService *service.ChatService
}
func NewApp() *App {
 configManager := config.NewManager()
 return &App{
 botService: service.NewBotService(configManager),
 settingsService: service.NewSettingsService(configManager),
 processorService: service.NewProcessorService(),
 chatService: service.NewChatService(configManager),
 }
}
func (a *App) BuildSystemPrompt(promptTemplate string, xmlFilePath string) *common.Response {
 prompt, err := a.chatService.BuildSystemPrompt(promptTemplate, xmlFilePath)
 if err != nil {
 return common.NewErrorResponse("Failed to build system prompt", err)
 }
 return common.NewSuccessResponse("System prompt built successfully", prompt)
}
func (a *App) ChatWithLLM(messages []common.Message, config *config.BotConfig) *common.Response {
 response, err := a.chatService.ChatWithLLM(messages, config)
 if err != nil {
 return common.NewErrorResponse("Failed to chat with LLM", err)
 }
 return response
}
func (a *App) LoadSettings() *common.Response {
 return a.settingsService.LoadSettings()
}
func (a *App) LoadBots() *common.Response {
 return a.botService.LoadBots()
}
func (a *App) SaveSettings(c *config.Settings) *common.Response {
 return a.settingsService.SaveSettings(c)
}
func (a *App) LoadNewBotPageData() *common.Response {
 return a.botService.LoadNewBotPageData()
}
func (a *App) SaveBotConfig(config config.BotConfig) *common.Response {
 return a.botService.SaveBotConfig(config)
}
func (a *App) ProcessFiles(files []string, name string) *common.Response {
 return a.processorService.ProcessFiles(files, name)
}
func (a *App) OpenFolderDialog() *common.Response {
 return a.dialogService.OpenFolderDialog()
}
func (a *App) GetDirectoryStructure(rootPath string) *common.Response {
 return a.processorService.GetDirectoryStructure(rootPath)
}
func (a *App) startup(ctx context.Context) {
 a.ctx = ctx
 a.dialogService = service.NewDialogService(ctx)
 if err := config.NewManager().Init(); err != nil {
 panic(err)
 }
}]]></f><f p="bot_config.go"><![CDATA[package config
import (
 "encoding/json"
 "fmt"
 "io/fs"
 "os"
 "path/filepath"
 "regexp"
 "strings"
)
func (m *Manager) LoadNewBotPageData() (*NewBotData, error) {
 providers, err := m.loadProviders()
 if err != nil {
 return nil, err
 }
 prompts, err := m.loadPrompts()
 if err != nil {
 return nil, err
 }
 repos, err := m.loadRepositories()
 if err != nil {
 return nil, err
 }
 return &NewBotData{
 Providers: providers,
 SystemPrompts: prompts,
 Repositories: repos,
 }, nil
}
func (m *Manager) LoadBots() ([]BotConfig, error) {
 var bots []BotConfig
 botsPath := m.paths.GetBotPath()
 if err := os.MkdirAll(botsPath, 0755); err != nil {
 return nil, err
 }
 files, err := os.ReadDir(botsPath)
 if err != nil {
 return nil, err
 }
 for _, file := range files {
 if filepath.Ext(file.Name()) != ".json" {
 continue
 }
 filePath := filepath.Join(botsPath, file.Name())
 data, err := os.ReadFile(filePath)
 if err != nil {
 return nil, err
 }
 var bot BotConfig
 if err := json.Unmarshal(data, &bot); err != nil {
 return nil, err
 }
 bots = append(bots, bot)
 }
 return bots, nil
}
func (m *Manager) SaveBotConfig(config BotConfig) error {
 botsDir := "userdata/bots"
 if err := os.MkdirAll(botsDir, 0755); err != nil {
 return err
 }
 safeName := strings.ReplaceAll(strings.ToLower(config.Name), " ", "_")
 filename := filepath.Join(botsDir, safeName+".json")
 absBasePath, err := filepath.Abs(".")
 if err != nil {
 return err
 }
 if filepath.IsAbs(config.SystemPrompt.Path) {
 relPath, err := filepath.Rel(absBasePath, config.SystemPrompt.Path)
 if err != nil {
 return err
 }
 config.SystemPrompt.Path = relPath
 }
 for k, v := range config.SystemPrompt.Variables {
 if k == "CODEBASE" {
 config.SystemPrompt.Variables[k] = filepath.Join("userdata/repos", v)
 } else if filepath.IsAbs(v) {
 relPath, err := filepath.Rel(absBasePath, v)
 if err != nil {
 return err
 }
 config.SystemPrompt.Variables[k] = relPath
 }
 }
 jsonData, err := json.MarshalIndent(config, "", " ")
 if err != nil {
 return err
 }
 return os.WriteFile(filename, jsonData, 0644)
}
func (m *Manager) loadProviders() ([]AIProvider, error) {
 var providers []AIProvider
 providersPath := m.paths.GetProviderPath()
 err := filepath.WalkDir(providersPath, func(path string, info fs.DirEntry, err error) error {
 if err != nil {
 return err
 }
 if !info.IsDir() && filepath.Ext(info.Name()) == ".json" {
 var provider AIProvider
 file, err := os.Open(path)
 if err != nil {
 return err
 }
 defer file.Close()
 if err := json.NewDecoder(file).Decode(&provider); err != nil {
 return err
 }
 providers = append(providers, provider)
 }
 return nil
 })
 if err != nil {
 return nil, err
 }
 if len(providers) == 0 {
 return nil, fmt.Errorf("no provider configurations found in %s directory", providersPath)
 }
 return providers, nil
}
func (m *Manager) loadPrompts() ([]Prompt, error) {
 var prompts []Prompt
 promptsPath := m.paths.GetPromptPath()
 variableRegex := regexp.MustCompile(`{{\s*([A-Za-z0-9_]+)\s*}}`)
 err := filepath.WalkDir(promptsPath, func(path string, info fs.DirEntry, err error) error {
 if err != nil {
 return err
 }
 if !info.IsDir() {
 content, err := os.ReadFile(path)
 if err != nil {
 return err
 }
 variables := make(map[string]string)
 matches := variableRegex.FindAllStringSubmatch(string(content), -1)
 for _, match := range matches {
 variable := match[1]
 if _, exists := variables[variable]; !exists {
 variables[variable] = ""
 }
 }
 prompts = append(prompts, Prompt{
 Name: info.Name(),
 Variables: variables,
 })
 }
 return nil
 })
 if err != nil {
 return nil, err
 }
 if len(prompts) == 0 {
 return nil, fmt.Errorf("no prompt files found in %s", promptsPath)
 }
 return prompts, nil
}
func (m *Manager) loadRepositories() ([]string, error) {
 var repositories []string
 reposPath := m.paths.GetRepoPath()
 err := filepath.WalkDir(reposPath, func(path string, info fs.DirEntry, err error) error {
 if err != nil {
 return err
 }
 if info.IsDir() && path != reposPath {
 relPath, err := filepath.Rel(reposPath, path)
 if err != nil {
 return err
 }
 repositories = append(repositories, relPath)
 }
 return nil
 })
 if err != nil {
 return nil, err
 }
 if len(repositories) == 0 {
 return nil, fmt.Errorf("no repositories found in %s", reposPath)
 }
 return repositories, nil
}]]></f><f p="config.go"><![CDATA[package config
import (
 "fmt"
 "os"
 "path/filepath"
 "strings"
)
type Manager struct {
 paths *PathConfig
 envFile string
}
func NewManager() *Manager {
 workingDir, _ := os.Getwd()
 envFile := filepath.Join(workingDir, ".env")
 return &Manager{
 paths: NewPathConfig(),
 envFile: envFile,
 }
}
func (m *Manager) Init() error {
 if _, err := os.Stat(m.envFile); os.IsNotExist(err) {
 if err := m.createDefaultEnvFile(m.envFile); err != nil {
 return fmt.Errorf("error creating default .env file: %w", err)
 }
 }
 dirs := []string{
 filepath.Dir(m.envFile),
 filepath.Join(filepath.Dir(m.envFile), "providers"),
 filepath.Join(filepath.Dir(m.envFile), "userdata"),
 filepath.Join(filepath.Dir(m.envFile), "userdata", "bots"),
 filepath.Join(filepath.Dir(m.envFile), "userdata", "prompts"),
 filepath.Join(filepath.Dir(m.envFile), "userdata", "repos"),
 }
 for _, dir := range dirs {
 if err := os.MkdirAll(dir, 0755); err != nil {
 return fmt.Errorf("failed to create directory %s: %w", dir, err)
 }
 }
 workingDir, err := os.Getwd()
 if err != nil {
 return fmt.Errorf("error getting working directory: %w", err)
 }
 files := map[string]string{
 filepath.Join(workingDir, "providers", "anthropic.json"): defaultAnthropicConfig,
 filepath.Join(workingDir, "providers", "openai.json"): defaultOpenAIConfig,
 filepath.Join(workingDir, "userdata", "bots", "default.json"): defaultBotConfig,
 filepath.Join(workingDir, "userdata", "prompts", "default"): defaultPrompt,
 }
 for path, content := range files {
 if _, err := os.Stat(path); os.IsNotExist(err) {
 if err := os.WriteFile(path, []byte(content), 0644); err != nil {
 return fmt.Errorf("failed to create file %s: %w", path, err)
 }
 }
 }
 return nil
}
func (m *Manager) LoadSettings() (*Settings, error) {
 content, err := os.ReadFile(m.envFile)
 if err != nil {
 return nil, fmt.Errorf("error reading .env file: %w", err)
 }
 envMap := make(map[string]string)
 for _, line := range strings.Split(string(content), "\n") {
 line = strings.TrimSpace(line)
 if line == "" || strings.HasPrefix(line, "#") {
 continue
 }
 parts := strings.SplitN(line, "=", 2)
 if len(parts) == 2 {
 key := strings.TrimSpace(parts[0])
 value := strings.TrimSpace(parts[1])
 envMap[key] = value
 }
 }
 settings := &Settings{
 OpenAIKey: envMap["OPENAI_API_KEY"],
 AnthropicKey: envMap["ANTHROPIC_API_KEY"],
 GitHubKey: envMap["GITHUB_API_KEY"],
 DBHost: envMap["POSTGRES_HOST"],
 DBPort: envMap["POSTGRES_PORT"],
 DBName: envMap["POSTGRES_DB"],
 DBUser: envMap["POSTGRES_USER"],
 DBPassword: envMap["POSTGRES_PASSWORD"],
 }
 return settings, nil
}
func (m *Manager) SaveSettings(settings Settings) error {
 content := fmt.Sprintf(`OPENAI_API_KEY=%s
ANTHROPIC_API_KEY=%s
GITHUB_API_KEY=%s
POSTGRES_HOST=%s
POSTGRES_PORT=%s
POSTGRES_DB=%s
POSTGRES_USER=%s
POSTGRES_PASSWORD=%s`,
 settings.OpenAIKey,
 settings.AnthropicKey,
 settings.GitHubKey,
 settings.DBHost,
 settings.DBPort,
 settings.DBName,
 settings.DBUser,
 settings.DBPassword)
 if err := os.WriteFile(m.envFile, []byte(content), 0644); err != nil {
 return fmt.Errorf("error saving settings to .env file: %w", err)
 }
 return nil
}
func (m *Manager) createDefaultEnvFile(path string) error {
 defaultConfig := `OPENAI_API_KEY=
ANTHROPIC_API_KEY=
GITHUB_API_KEY=
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_DB=
POSTGRES_USER=postgres
POSTGRES_PASSWORD=`
 return os.WriteFile(path, []byte(defaultConfig), 0644)
}]]></f><f p="default.go"><![CDATA[package config
const defaultAnthropicConfig = `{
 "name": "anthropic",
 "models": [
 {
 "id": "claude-3-5-sonnet-latest",
 "description": "Our most intelligent model. Highest level of intelligence and capability",
 "context_window": 200000,
 "max_output_tokens": 8192,
 "default_output_tokens": 8192
 },
 {
 "id": "claude-3-5-haiku-latest",
 "description": "Our fastest model. Intelligence at blazing speeds",
 "context_window": 128000,
 "max_output_tokens": 16384,
 "default_output_tokens": 16384,
 "default": true
 }
 ],
 "parameters": {
 "temperature": {
 "min": 0.0,
 "max": 1.0,
 "default": 0,
 "description": "Controls randomness in the output. Higher values mean more random completions."
 },
 "top_p": {
 "min": 0.0,
 "max": 1.0,
 "default": 1.0,
 "description": "Controls diversity via nucleus sampling."
 }
 }
}`
const defaultOpenAIConfig = `{
 "name": "openai",
 "models": [
 {
 "id": "gpt-4o",
 "description": "Our high-intelligence flagship model for complex, multi-step tasks. GPT-4o is cheaper and faster than GPT-4 Turbo.",
 "context_window": 128000,
 "max_output_tokens": 16384,
 "default_output_tokens": 16384
 },
 {
 "id": "gpt-4o-mini",
 "description": "Our affordable and intelligent small model for fast, lightweight tasks. GPT-4o mini is cheaper and more capable than GPT-3.5 Turbo.",
 "context_window": 128000,
 "max_output_tokens": 16384,
 "default_output_tokens": 16384,
 "default": true
 },
 {
 "id": "o1-preview",
 "description": "Reasoning model designed to solve hard problems across domains.",
 "context_window": 128000,
 "max_output_tokens": 32768,
 "default_output_tokens": 32768
 },
 {
 "id": "o1-mini",
 "description": "Faster and cheaper reasoning model particularly good at coding, math, and science.",
 "context_window": 128000,
 "max_output_tokens": 65536,
 "default_output_tokens": 65536
 }
 ],
 "parameters": {
 "temperature": {
 "min": 0.0,
 "max": 2.0,
 "default": 0,
 "description": "Controls randomness in the output. Higher values mean more random completions."
 },
 "top_p": {
 "min": 0.0,
 "max": 1.0,
 "default": 1.0,
 "description": "Controls diversity via nucleus sampling."
 }
 }
}}`
const defaultBotConfig = `{
 "name": "default",
 "description": "default",
 "provider": "anthropic",
 "model": "claude-3-5-sonnet-latest",
 "system_prompt": {
 "path": "prompts/default",
 "variables": {
 "CODEBASE": "repos/default"
 }
 },
 "temperature": 0,
 "max_tokens": 8192,
 "top_p": 1,
 "stop": null
}`
const defaultPrompt = `You are Cline, a highly skilled software engineer with extensive knowledge in many programming languages, frameworks,
design patterns, and best practices.
OBJECTIVE
You accomplish a given task iteratively, breaking it down into clear steps and working through them methodically.
RULES
- Analyze the user's task and set clear, achievable goals to accomplish it. Prioritize these goals in a logical order.
- When making changes to code, always consider the context in which the code is being used. Ensure that your changes are
compatible with the existing codebase and that they follow the project's coding standards and best practices.
- Analyze the user's task and set clear, achievable goals to accomplish it. Prioritize these goals in a logical order.
- The user may provide feedback, which you can use to make improvements and try again. But DO NOT continue in pointless
back and forth conversations, i.e. don't end your responses with questions or offers for further assistance.
- You are STRICTLY FORBIDDEN from starting your messages with "Great", "Certainly", "Okay", "Sure". You should NOT be
conversational in your responses, but rather direct and to the point. For example you should NOT say "Great, I've
updated the CSS" but instead something like "I've updated the CSS". It is important you be clear and technical in your
messages.
CONTEXT
{{CODEBASE}}`]]></f><f p="ignore.go"><![CDATA[package config
import (
 "bufio"
 "os"
 "path/filepath"
 "strings"
)
type IgnoreList struct {
 patterns []string
}
func NewIgnoreList(ignorePath string) (*IgnoreList, error) {
 il := &IgnoreList{
 patterns: make([]string, 0),
 }
 if _, err := os.Stat(ignorePath); err == nil {
 file, err := os.Open(ignorePath)
 if err != nil {
 return nil, err
 }
 defer file.Close()
 scanner := bufio.NewScanner(file)
 for scanner.Scan() {
 pattern := strings.TrimSpace(scanner.Text())
 if pattern != "" && !strings.HasPrefix(pattern, "#") {
 il.patterns = append(il.patterns, pattern)
 }
 }
 }
 return il, nil
}
func (il *IgnoreList) ShouldIgnore(path string) bool {
 path = filepath.ToSlash(path)
 for _, pattern := range il.patterns {
 if pattern == "" {
 continue
 }
 if strings.HasSuffix(pattern, "/") {
 if strings.Contains(path, pattern) {
 return true
 }
 continue
 }
 if strings.HasPrefix(pattern, "*") {
 suffix := pattern[1:]
 if strings.HasSuffix(path, suffix) {
 return true
 }
 continue
 }
 if pattern == filepath.Base(path) {
 return true
 }
 if pattern == ".*" && strings.HasPrefix(filepath.Base(path), ".") {
 return true
 }
 }
 return false
}]]></f><f p="path.go"><![CDATA[package config
import "path/filepath"
type PathConfig struct {
 BaseDir string
 PromptsDir string
 ReposDir string
 ProvidersDir string
 BotsDir string
}
func NewPathConfig() *PathConfig {
 return &PathConfig{
 BaseDir: "userdata",
 PromptsDir: "prompts",
 ReposDir: "repos",
 ProvidersDir: "providers",
 BotsDir: "bots",
 }
}
func (p *PathConfig) GetPromptPath() string {
 return filepath.Join(p.BaseDir, p.PromptsDir)
}
func (p *PathConfig) GetRepoPath() string {
 return filepath.Join(p.BaseDir, p.ReposDir)
}
func (p *PathConfig) GetProviderPath() string {
 return p.ProvidersDir
}
func (p *PathConfig) GetBotPath() string {
 return filepath.Join(p.BaseDir, p.BotsDir)
}]]></f><f p="types.go"><![CDATA[package config
type Settings struct {
 OpenAIKey string `json:"openai_api_key"`
 AnthropicKey string `json:"anthropic_api_key"`
 GitHubKey string `json:"github_api_key"`
 DBHost string `json:"db_host"`
 DBPort string `json:"db_port"`
 DBName string `json:"db_name"`
 DBUser string `json:"db_user"`
 DBPassword string `json:"db_password"`
}
type BotConfig struct {
 Name string `json:"name"`
 Description string `json:"description"`
 Provider string `json:"provider"`
 Model string `json:"model"`
 SystemPrompt struct {
 Path string `json:"path"`
 Variables map[string]string `json:"variables"`
 } `json:"system_prompt"`
 Temperature float64 `json:"temperature"`
 MaxTokens int `json:"max_tokens"`
 TopP float64 `json:"top_p"`
 Stop []string `json:"stop"`
}
type NewBotResponse struct {
 Success bool `json:"success"`
 Message string `json:"message"`
 Error *string `json:"error,omitempty"`
 Data *NewBotData `json:"data,omitempty"`
}
type AIParameterSettings struct {
 Min float64 `json:"min"`
 Max float64 `json:"max"`
 Default float64 `json:"default"`
 Description string `json:"description"`
}
type AIModel struct {
 ID string `json:"id"`
 Description string `json:"description"`
 ContextWindow int `json:"context_window"`
 MaxOutputTokens int `json:"max_output_tokens"`
 DefaultOutputTokens int `json:"default_output_tokens"`
 Default *bool `json:"default,omitempty"`
}
type AIParameters struct {
 Temperature AIParameterSettings `json:"temperature"`
 TopP AIParameterSettings `json:"top_p"`
}
type AIProvider struct {
 Name string `json:"name"`
 Models []AIModel `json:"models"`
 Parameters AIParameters `json:"parameters"`
}
type NewBotData struct {
 SystemPrompts []Prompt `json:"system_prompts"`
 Repositories []string `json:"repositories"`
 Documentation []string `json:"documentation"`
 Providers []AIProvider `json:"providers"`
}
type Prompt struct {
 Name string `json:"name"`
 Variables map[string]string `json:"variables"`
}]]></f><f p="response.go"><![CDATA[package common
type ResponseStatus string
const (
 StatusSuccess ResponseStatus = "success"
 StatusError ResponseStatus = "error"
)
type Response struct {
 Status ResponseStatus `json:"status"`
 Message string `json:"message"`
 Error string `json:"error,omitempty"`
 Data interface{} `json:"data,omitempty"`
}
type Message struct {
 Role string `json:"role"`
 Content string `json:"content"`
}
func NewSuccessResponse(message string, data interface{}) *Response {
 return &Response{
 Status: StatusSuccess,
 Message: message,
 Data: data,
 }
}
func NewErrorResponse(message string, err error) *Response {
 errStr := ""
 if err != nil {
 errStr = err.Error()
 }
 return &Response{
 Status: StatusError,
 Message: message,
 Error: errStr,
 }
}]]></f><f p="errors.go"><![CDATA[package errors
import "fmt"
type AppError struct {
 Code string
 Message string
 Err error
}
func (e *AppError) Error() string {
 if e.Err != nil {
 return fmt.Sprintf("%s: %s (%v)", e.Code, e.Message, e.Err)
 }
 return fmt.Sprintf("%s: %s", e.Code, e.Message)
}
func NewError(code string, message string, err error) *AppError {
 return &AppError{
 Code: code,
 Message: message,
 Err: err,
 }
}]]></f><f p="anthropic.go"><![CDATA[package llm
import (
 "WAILS_SVELTE_FINAL/internal/common"
 "WAILS_SVELTE_FINAL/internal/config"
 "bytes"
 "encoding/json"
 "fmt"
 "io"
 "net/http"
)
func AnthropicChat(token string, botConfig *config.BotConfig, messages []common.Message) (string, error) {
 url := "https:
 req, err := http.NewRequest("POST", url, nil)
 if err != nil {
 return "", fmt.Errorf("failed to create request: %w", err)
 }
 req.Header.Set("Content-Type", "application/json")
 req.Header.Set("x-api-key", token)
 req.Header.Set("anthropic-version", "2023-06-01")
 req.Header.Set("anthropic-beta", "prompt-caching-2024-07-31")
 systemPrompt := map[string]interface{}{
 "type": "text",
 "text": messages[0].Content,
 "cache_control": map[string]string{
 "type": "ephemeral",
 },
 }
 var messageList []map[string]string
 for _, msg := range messages[1:] {
 messageList = append(messageList, map[string]string{
 "role": msg.Role,
 "content": msg.Content,
 })
 }
 payload := map[string]interface{}{
 "model": botConfig.Model,
 "max_tokens": botConfig.MaxTokens,
 "temperature": botConfig.Temperature,
 "top_p": botConfig.TopP,
 "system": []map[string]interface{}{systemPrompt},
 "messages": messageList,
 }
 payloadBytes, err := json.Marshal(payload)
 if err != nil {
 return "", fmt.Errorf("failed to marshal JSON payload: %w", err)
 }
 req.Body = io.NopCloser(bytes.NewBuffer(payloadBytes))
 client := &http.Client{}
 resp, err := client.Do(req)
 if err != nil {
 return "", fmt.Errorf("failed to make API request: %w", err)
 }
 defer resp.Body.Close()
 body, err := io.ReadAll(resp.Body)
 if err != nil {
 return "", fmt.Errorf("failed to read response body: %w", err)
 }
 var result struct {
 Content []struct {
 Type string `json:"type"`
 Text string `json:"text"`
 } `json:"content"`
 }
 if err := json.Unmarshal(body, &result); err != nil {
 return "", fmt.Errorf("failed to parse response JSON: %w", err)
 }
 fmt.Println(string(body))
 if len(result.Content) > 0 {
 return result.Content[0].Text, nil
 }
 return "", fmt.Errorf("no content text found in response")
}]]></f><f p="bot_service.go"><![CDATA[package service
import (
 "WAILS_SVELTE_FINAL/internal/common"
 "WAILS_SVELTE_FINAL/internal/config"
)
type BotService struct {
 config *config.Manager
}
func NewBotService(cfg *config.Manager) *BotService {
 return &BotService{
 config: cfg,
 }
}
func (s *BotService) LoadBots() *common.Response {
 data, err := s.config.LoadBots()
 if err != nil {
 return common.NewErrorResponse("Failed to load bots", err)
 }
 return common.NewSuccessResponse("Bots loaded successfully", data)
}
func (s *BotService) LoadNewBotPageData() *common.Response {
 data, err := s.config.LoadNewBotPageData()
 if err != nil {
 return common.NewErrorResponse("Failed to load bot config data", err)
 }
 return common.NewSuccessResponse("Bot config data loaded successfully", data)
}
func (s *BotService) SaveBotConfig(config config.BotConfig) *common.Response {
 err := s.config.SaveBotConfig(config)
 if err != nil {
 return common.NewErrorResponse("Failed to save bot configuration", err)
 }
 return common.NewSuccessResponse("Bot configuration saved successfully", nil)
}]]></f><f p="chat_service.go"><![CDATA[package service
import (
 "WAILS_SVELTE_FINAL/internal/common"
 "WAILS_SVELTE_FINAL/internal/config"
 "WAILS_SVELTE_FINAL/internal/llm"
 "errors"
 "fmt"
 "os"
 "path/filepath"
 "strings"
)
type ChatService struct {
 config *config.Manager
}
func NewChatService(cfg *config.Manager) *ChatService {
 return &ChatService{
 config: cfg,
 }
}
func (s *ChatService) ChatWithLLM(messages []common.Message, botcfg *config.BotConfig) (*common.Response, error) {
 cfg, _ := s.config.LoadSettings()
 fmt.Println(messages)
 fmt.Println(cfg)
 switch botcfg.Provider {
 case "openai":
 case "anthropic":
 res, err := llm.AnthropicChat(cfg.AnthropicKey, botcfg, messages)
 if err != nil {
 common.NewErrorResponse("Chat error", err)
 }
 return common.NewSuccessResponse("Chat successful", res), nil
 default:
 return nil, errors.New("unsupported provider")
 }
 return nil, nil
}
func (s *ChatService) BuildSystemPrompt(promptTemplatePath string, repoPath string) (string, error) {
 promptTemplate, err := os.ReadFile(promptTemplatePath)
 if err != nil {
 return "", err
 }
 xmlPath := filepath.Join(repoPath, "repository.xml") 
 xmlContent, err := os.ReadFile(xmlPath)
 if err != nil {
 return "", errors.New("could not find or read repository.xml in repository: " + err.Error())
 }
 prompt := strings.Replace(string(promptTemplate), "{{CODEBASE}}", string(xmlContent), -1)
 return prompt, nil
}]]></f><f p="dialog_service.go"><![CDATA[package service
import (
 "WAILS_SVELTE_FINAL/internal/common"
 "context"
 "os"
 "github.com/wailsapp/wails/v2/pkg/runtime"
)
type DialogService struct {
 ctx context.Context
}
func NewDialogService(ctx context.Context) *DialogService {
 return &DialogService{
 ctx: ctx,
 }
}
func (s *DialogService) OpenFolderDialog() *common.Response {
 if s.ctx == nil {
 return common.NewErrorResponse("Context not initialized", nil)
 }
 workingDir, err := os.Getwd()
 if err != nil {
 return common.NewErrorResponse("Failed to get working directory", err)
 }
 dir, err := runtime.OpenDirectoryDialog(s.ctx, runtime.OpenDialogOptions{
 Title: "Select Directory",
 DefaultDirectory: workingDir,
 })
 if err != nil {
 return common.NewErrorResponse("Failed to open folder dialog", err)
 }
 if dir == "" {
 return common.NewSuccessResponse("No directory selected", map[string]interface{}{
 "selected": false,
 })
 }
 return common.NewSuccessResponse("Directory selected", map[string]interface{}{
 "selected": true,
 "path": dir,
 })
}]]></f><f p="processor_service.go"><![CDATA[package service
import (
 "WAILS_SVELTE_FINAL/internal/common"
 "WAILS_SVELTE_FINAL/internal/config"
 "fmt"
 "os"
 "path/filepath"
 "regexp"
 "strings"
 "github.com/pkoukk/tiktoken-go"
)
type ProcessorService struct{}
func NewProcessorService() *ProcessorService {
 return &ProcessorService{}
}
func (s *ProcessorService) ProcessFiles(files []string, name string) *common.Response {
 if len(files) == 0 {
 return common.NewErrorResponse("No files selected", nil)
 }
 baseDir := filepath.Join("userdata", "repos", name)
 if err := os.MkdirAll(baseDir, 0755); err != nil {
 return common.NewErrorResponse("Failed to create output directory", err)
 }
 outputFile := filepath.Join(baseDir, "repository.xml")
 xmlFile, err := os.Create(outputFile)
 if err != nil {
 return common.NewErrorResponse("Failed to create XML file", err)
 }
 defer xmlFile.Close()
 var builder strings.Builder
 builder.WriteString("<repo>")
 for _, filePath := range files {
 content, err := os.ReadFile(filePath)
 if err != nil {
 return common.NewErrorResponse(fmt.Sprintf("Failed to read file %s", filePath), err)
 }
 relativePath := filepath.Base(filePath)
 processedContent := trimContent(string(content))
 builder.WriteString(fmt.Sprintf(`<f p="%s"><![CDATA[%s]]></f>`, relativePath, processedContent))
 }
 builder.WriteString("</repo>")
 xmlContent := builder.String()
 encoding := "gpt-4o"
 tkm, err := tiktoken.EncodingForModel(encoding)
 if err != nil {
 return common.NewSuccessResponse("Files processed successfully, but token count could not be determined", map[string]interface{}{
 "outputPath": outputFile,
 })
 }
 tokens := tkm.Encode(xmlContent, nil, nil)
 tokenCount := len(tokens)
 if _, err := xmlFile.WriteString(xmlContent); err != nil {
 return common.NewErrorResponse("Failed to write XML content to file", err)
 }
 return common.NewSuccessResponse("Files processed successfully", map[string]interface{}{
 "outputPath": outputFile,
 "tokenCount": tokenCount,
 })
}
func (s *ProcessorService) GetDirectoryStructure(rootPath string) *common.Response {
 if rootPath == "" {
 return common.NewErrorResponse("No path provided", nil)
 }
 ignorePath := filepath.Join(rootPath, ".ignore")
 ignoreList, err := config.NewIgnoreList(ignorePath)
 if err != nil {
 return common.NewErrorResponse("Failed to initialize ignore list", err)
 }
 var buildTree func(root string) ([]map[string]interface{}, error)
 buildTree = func(root string) ([]map[string]interface{}, error) {
 var nodes []map[string]interface{}
 entries, err := os.ReadDir(root)
 if err != nil {
 return nil, err
 }
 for _, entry := range entries {
 fullPath := filepath.Join(root, entry.Name())
 if ignoreList.ShouldIgnore(fullPath) {
 continue
 }
 node := map[string]interface{}{
 "name": entry.Name(),
 "path": fullPath,
 "isDir": entry.IsDir(),
 "children": nil,
 }
 if entry.IsDir() {
 children, err := buildTree(fullPath)
 if err != nil {
 return nil, err
 }
 if len(children) > 0 {
 node["children"] = children
 nodes = append(nodes, node)
 }
 } else {
 nodes = append(nodes, node)
 }
 }
 return nodes, nil
 }
 tree, err := buildTree(rootPath)
 if err != nil {
 return common.NewErrorResponse("Failed to read directory structure", err)
 }
 return common.NewSuccessResponse("Directory structure retrieved", tree)
}
func trimContent(content string) string {
 content = regexp.MustCompile(``).ReplaceAllString(content, "")
 content = regexp.MustCompile(`(?s)/\*.*?\*/`).ReplaceAllString(content, "")
 content = regexp.MustCompile(`
 content = regexp.MustCompile(`\n\s*\n`).ReplaceAllString(content, "\n")
 content = regexp.MustCompile(`[ \t]+$`).ReplaceAllString(content, "")
 content = regexp.MustCompile(`[ \t]+`).ReplaceAllString(content, " ")
 return strings.TrimSpace(content)
}]]></f><f p="settings_service.go"><![CDATA[package service
import (
 "WAILS_SVELTE_FINAL/internal/common"
 "WAILS_SVELTE_FINAL/internal/config"
)
type SettingsService struct {
 config *config.Manager
}
func NewSettingsService(cfg *config.Manager) *SettingsService {
 return &SettingsService{
 config: cfg,
 }
}
func (s *SettingsService) LoadSettings() *common.Response {
 if s.config == nil {
 return common.NewErrorResponse("Configuration manager is not initialized", nil)
 }
 data, err := s.config.LoadSettings()
 if err != nil {
 return common.NewErrorResponse("Unable to load settings from configuration file", err)
 }
 if data == nil {
 return common.NewErrorResponse("Settings data is nil", nil)
 }
 return common.NewSuccessResponse("Settings loaded successfully", data)
}
func (s *SettingsService) SaveSettings(settings *config.Settings) *common.Response {
 err := s.config.SaveSettings(*settings)
 if err != nil {
 return common.NewErrorResponse("Unable to save settings to configuration file", err)
 }
 return common.NewSuccessResponse("Settings saved successfully", nil)
}]]></f><f p="main.go"><![CDATA[package main
import (
 "embed"
 "github.com/wailsapp/wails/v2"
 "github.com/wailsapp/wails/v2/pkg/options"
 "github.com/wailsapp/wails/v2/pkg/options/assetserver"
)
var assets embed.FS
func main() {
 app := NewApp()
 err := wails.Run(&options.App{
 Title: "Coding Assistant",
 Width: 1024,
 Height: 768,
 MinWidth: 1024,
 MinHeight: 768,
 AssetServer: &assetserver.Options{
 Assets: assets,
 },
 BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
 OnStartup: app.startup,
 Bind: []interface{}{
 app,
 },
 })
 if err != nil {
 println("Error:", err.Error())
 }
}]]></f></repo>

Analyze this repository. Provide suggestions for improvements. Start with the implementation.