{"repo": "aldotobing/neurogo", "files": {"cmd/server/main.go": {"36e66763d10a480523ee5edaefe64879c37a5cfc": {"t": 1785745626.6245806, "n": 31716, "h": "e179539cedc4fefb", "c": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n\t\"strings\"\n\n\t\"github.com/gorilla/mux\"\n\t\"github.com/joho/godotenv\"\n\t\"github.com/rs/cors\"\n\n\t\"github.com/aldotobing/neurogo/config\"\n\t\"github.com/aldotobing/neurogo/providers\"\n\t\"github.com/aldotobing/neurogo/router\"\n\t\"github.com/aldotobing/neurogo/server\"\n)\n\n// Global provider registry and current provider\nvar providerRegistry = make(map[string]providers.Provider)\nvar currentProvider = \"\"\n\nfunc main() {\n\t// Debug: Print current working directory and file existence\n\tif cwd, err := os.Getwd(); err == nil {\n\t\tlog.Printf(\"šŸ” Current working directory: %s\", cwd)\n\t}\n\n\t// Check if web files exist\n\twebFiles := []string{\"../../web/docs.html\", \"../../web/index.html\", \"../../web/static/app.js\", \"../../web/static/style.css\"}\n\tfor _, file := range webFiles {\n\t\tif _, err := os.Stat(file); err == nil {\n\t\t\tlog.Printf(\"āœ… Found: %s\", file)\n\t\t} else {\n\t\t\tlog.Printf(\"āŒ Missing: %s\", file)\n\t\t}\n\t}\n\n\t// Load environment variables with better error handling\n\tloadEnvironment()\n\n\t// Initialize the NeuroGO router\n\tneuroRouter := router.New()\n\n\t// Configure providers\n\tsetupProviders(neuroRouter)\n\n\t// Setup universal routes (works with any provider)\n\tsetupUniversalRoutes(neuroRouter)\n\n\t// Setup provider switching routes\n\tsetupProviderSwitchingRoutes(neuroRouter)\n\n\t// Setup example routes\n\tsetupExampleRoutes(neuroRouter)\n\n\t// Create HTTP server\n\thttpRouter := mux.NewRouter()\n\n\t// Setup API routes\n\tapi := httpRouter.PathPrefix(\"/api\").Subrouter()\n\tserver.SetupAPIRoutes(api, neuroRouter)\n\n\t// Setup WebSocket for real-time communication\n\tserver.SetupWebSocket(httpRouter, neuroRouter)\n\n\t// Serve static files for the playground\n\tsetupStaticFiles(httpRouter)\n\n\t// Setup CORS\n\tc := cors.New(cors.Options{\n\t\tAllowedOrigins: []string{\"*\"},\n\t\tAllowedMethods: []string{\"GET\", \"POST\", \"PUT\", \"DELETE\", \"OPTIONS\"},\n\t\tAllowedHeaders: []string{\"*\"},\n\t})\n\n\thandler := c.Handler(httpRouter)\n\n\tport := os.Getenv(\"PORT\")\n\tif port == \"\" {\n\t\tport = \"8080\"\n\t}\n\n\tfmt.Printf(\"šŸš€ NeuroGO server starting on port %s\\n\", port)\n\tfmt.Printf(\"šŸ“± Playground UI: http://localhost:%s\\n\", port)\n\tfmt.Printf(\"šŸ“š API Documentation: http://localhost:%s/docs\\n\", port)\n\tfmt.Printf(\"šŸ”— API Endpoint: http://localhost:%s/api\\n\", port)\n\n\tlog.Fatal(http.ListenAndServe(\":\"+port, handler))\n}\n\n// loadEnvironment loads environment variables with better error handling\nfunc loadEnvironment() {\n\t// Try to load .env file from current directory\n\tif err := godotenv.Load(); err != nil {\n\t\t// Try to load from parent directory (in case we're in cmd/server)\n\t\tif err := godotenv.Load(\"../../.env\"); err != nil {\n\t\t\tlog.Println(\"No .env file found, using system environment variables\")\n\t\t} else {\n\t\t\tlog.Println(\"āœ… Loaded .env file from parent directory\")\n\t\t}\n\t} else {\n\t\tlog.Println(\"āœ… Loaded .env file successfully\")\n\t}\n\n\t// Debug: Print which environment variables are set\n\tdebugEnvironmentVariables()\n}\n\n// debugEnvironmentVariables prints which environment variables are detected\nfunc debugEnvironmentVariables() {\n\tenvVars := []string{\n\t\t\"OPENAI_API_KEY\",\n\t\t\"DEEPSEEK_API_KEY\",\n\t\t\"GEMINI_API_KEY\",\n\t\t\"HUGGINGFACE_API_KEY\",\n\t\t\"OLLAMA_HOST\",\n\t}\n\n\tlog.Println(\"šŸ” Environment Variables Status:\")\n\tfor _, envVar := range envVars {\n\t\tvalue := os.Getenv(envVar)\n\t\tif value != \"\" {\n\t\t\t// Don't print the full API key for security\n\t\t\tif len(value) > 10 {\n\t\t\t\tlog.Printf(\" āœ… %s: %s...%s\", envVar, value[:4], value[len(value)-4:])\n\t\t\t} else {\n\t\t\t\tlog.Printf(\" āœ… %s: %s\", envVar, value)\n\t\t\t}\n\t\t} else {\n\t\t\tlog.Printf(\" āŒ %s: not set\", envVar)\n\t\t}\n\t}\n}\n\n// getCurrentProvider returns the currently selected provider or the best available one\nfunc getCurrentProvider(taskType string) providers.Provider {\n\t// If a specific provider is selected, use it\n\tif currentProvider != \"\" {\n\t\tif provider, exists := providerRegistry[currentProvider]; exists {\n\t\t\treturn provider\n\t\t}\n\t}\n\n\t// Otherwise, use the best provider for the task type\n\treturn getBestProvider(taskType)\n}\n\n// getBestProvider returns the best available provider for a given task type\nfunc getBestProvider(taskType string) providers.Provider {\n\t// Provider preferences for different task types\n\tpreferences := map[string][]string{\n\t\t\"translation\": {\"Gemini\", \"OpenAI\", \"DeepSeek\", \"Ollama\"},\n\t\t\"reasoning\": {\"DeepSeek\", \"OpenAI\", \"Gemini\", \"Ollama\"},\n\t\t\"coding\": {\"Ollama\", \"OpenAI\", \"DeepSeek\", \"Gemini\"},\n\t\t\"summary\": {\"OpenAI\", \"DeepSeek\", \"Gemini\", \"Ollama\"},\n\t\t\"general\": {\"OpenAI\", \"DeepSeek\", \"Gemini\", \"Ollama\"},\n\t}\n\n\tproviderList, exists := preferences[taskType]\n\tif !exists {\n\t\tproviderList = preferences[\"general\"]\n\t}\n\n\t// Return the first available provider from the preference list\n\tfor _, providerName := range providerList {\n\t\tif provider, exists := providerRegistry[providerName]; exists {\n\t\t\treturn provider\n\t\t}\n\t}\n\n\t// Fallback: return any available provider\n\tfor _, provider := range providerRegistry {\n\t\treturn provider\n\t}\n\n\treturn nil\n}\n\n// getProviderList returns a list of available provider names\nfunc getProviderList() []string {\n\tvar providers []string\n\tfor name := range providerRegistry {\n\t\tproviders = append(providers, name)\n\t}\n\treturn providers\n}\n\nfunc setupProviders(r *router.Router) {\n\tavailableProviders := []string{}\n\n\t// OpenAI Provider\n\tif apiKey := os.Getenv(\"OPENAI_API_KEY\"); apiKey != \"\" {\n\t\topenAIProvider := providers.NewOpenAI(apiKey)\n\t\tif openAIProvider.IsAvailable() {\n\t\t\tproviderRegistry[\"OpenAI\"] = openAIProvider\n\t\t\tavailableProviders = append(availableProviders, \"OpenAI\")\n\t\t\tlog.Println(\"āœ… OpenAI provider configured\")\n\t\t} else {\n\t\t\tlog.Println(\"āŒ OpenAI provider configuration failed\")\n\t\t}\n\t} else {\n\t\tlog.Println(\"āš ļø OpenAI API key not provided\")\n\t}\n\n\t// DeepSeek Provider\n\tif apiKey := os.Getenv(\"DEEPSEEK_API_KEY\"); apiKey != \"\" {\n\t\tdeepSeekProvider := providers.NewDeepSeek(apiKey)\n\t\tif deepSeekProvider.IsAvailable() {\n\t\t\tproviderRegistry[\"DeepSeek\"] = deepSeekProvider\n\t\t\tavailableProviders = append(availableProviders, \"DeepSeek\")\n\t\t\tlog.Println(\"āœ… DeepSeek provider configured\")\n\t\t} else {\n\t\t\tlog.Println(\"āŒ DeepSeek provider configuration failed\")\n\t\t}\n\t} else {\n\t\tlog.Println(\"āš ļø DeepSeek API key not provided\")\n\t}\n\n\t// Gemini Provider\n\tif apiKey := os.Getenv(\"GEMINI_API_KEY\"); apiKey != \"\" {\n\t\tgeminiProvider := providers.NewGemini(apiKey)\n\t\tif geminiProvider.IsAvailable() {\n\t\t\tproviderRegistry[\"Gemini\"] = geminiProvider\n\t\t\tavailableProviders = append(availableProviders, \"Gemini\")\n\t\t\tlog.Println(\"āœ… Gemini provider configured\")\n\t\t} else {\n\t\t\tlog.Println(\"āŒ Gemini provider configuration failed\")\n\t\t}\n\t} else {\n\t\tlog.Println(\"āš ļø Gemini API key not provided\")\n\t}\n\n\t// Ollama Provider\n\tollamaHost := os.Getenv(\"OLLAMA_HOST\")\n\tif ollamaHost == \"\" {\n\t\tollamaHost = \"http://localhost:11434\"\n\t}\n\n\tlog.Printf(\"šŸ” Checking Ollama at: %s\", ollamaHost)\n\tollamaProvider := providers.NewOllama(ollamaHost)\n\tif ollamaProvider.IsAvailable() {\n\t\tproviderRegistry[\"Ollama\"] = ollamaProvider\n\t\tavailableProviders = append(availableProviders, \"Ollama\")\n\t\tlog.Println(\"āœ… Ollama provider configured\")\n\t} else {\n\t\tlog.Printf(\"āš ļø Ollama not available - make sure Ollama is running on %s\", ollamaHost)\n\t}\n\n\t// HuggingFace Provider\n\tif apiKey := os.Getenv(\"HUGGINGFACE_API_KEY\"); apiKey != \"\" {\n\t\thfProvider := providers.NewHuggingFace(apiKey)\n\t\tif hfProvider.IsAvailable() {\n\t\t\tproviderRegistry[\"HuggingFace\"] = hfProvider\n\t\t\tavailableProviders = append(availableProviders, \"HuggingFace\")\n\t\t\tlog.Println(\"āœ… HuggingFace provider configured\")\n\t\t} else {\n\t\t\tlog.Println(\"āŒ HuggingFace provider configuration failed\")\n\t\t}\n\t} else {\n\t\tlog.Println(\"āš ļø HuggingFace API key not provided\")\n\t}\n\n\t// Set default provider to the first available one\n\tif len(availableProviders) > 0 && currentProvider == \"\" {\n\t\tcurrentProvider = availableProviders[0]\n\t\tlog.Printf(\"šŸŽÆ Default provider set to: %s\", currentProvider)\n\t}\n\n\t// Log summary\n\tif len(availableProviders) == 0 {\n\t\tlog.Println(\"āš ļø No AI providers configured. Only basic commands will work.\")\n\t\tlog.Println(\"šŸ’” To get started with Ollama: run 'ollama serve' and 'ollama pull llama2'\")\n\t\tlog.Println(\"šŸ’” Or add API keys to your .env file for cloud providers\")\n\t} else {\n\t\tlog.Printf(\"šŸŽ‰ Configured providers: %v\", availableProviders)\n\t}\n}\n\n// setupProviderSwitchingRoutes creates routes for switching between providers\nfunc setupProviderSwitchingRoutes(r *router.Router) {\n\t// Switch to a specific provider\n\tr.Handle(\"use *\", func(ctx *router.Context) error {\n\t\tproviderName := normalizeProviderName(ctx.Captures[0])\n\n\t\tif _, exists := providerRegistry[providerName]; exists {\n\t\t\tcurrentProvider = providerName\n\t\t\tctx.Response = fmt.Sprintf(\"āœ… Switched to %s provider. All subsequent commands will use %s.\", providerName, providerName)\n\t\t} else {\n\t\t\tavailableProviders := getProviderList()\n\t\t\tctx.Response = fmt.Sprintf(\"āŒ Provider '%s' not available. Available providers: %s\",\n\t\t\t\tctx.Captures[0], strings.Join(availableProviders, \", \"))\n\t\t}\n\t\treturn nil\n\t})\n\n\t// Switch to auto mode (best provider for each task)\n\tr.Handle(\"use auto\", func(ctx *router.Context) error {\n\t\tcurrentProvider = \"\"\n\t\tctx.Response = \"āœ… Switched to auto mode. The system will automatically choose the best provider for each task.\"\n\t\treturn nil\n\t})\n\n\t// Show current provider\n\tr.Handle(\"current provider\", func(ctx *router.Context) error {\n\t\tif currentProvider == \"\" {\n\t\t\tctx.Response = \"šŸ¤– Currently in auto mode - the system chooses the best provider for each task.\"\n\t\t} else {\n\t\t\tctx.Response = fmt.Sprintf(\"šŸŽÆ Currently using: %s\", currentProvider)\n\t\t}\n\t\treturn nil\n\t})\n\n\t// List all available providers\n\tr.Handle(\"list providers\", func(ctx *router.Context) error {\n\t\tproviders := getProviderList()\n\t\tif len(providers) == 0 {\n\t\t\tctx.Response = \"āŒ No providers configured.\"\n\t\t\treturn nil\n\t\t}\n\n\t\tresponse := \"šŸ“‹ Available providers:\\n\\n\"\n\t\tfor _, name := range providers {\n\t\t\tif name == currentProvider {\n\t\t\t\tresponse += fmt.Sprintf(\"šŸŽÆ %s (currently selected)\\n\", name)\n\t\t\t} else {\n\t\t\t\tresponse += fmt.Sprintf(\" %s\\n\", name)\n\t\t\t}\n\t\t}\n\n\t\tresponse += \"\\nšŸ’” Commands:\\n\"\n\t\tresponse += \"• 'use [provider]' - Switch to specific provider\\n\"\n\t\tresponse += \"• 'use auto' - Auto-select best provider for each task\\n\"\n\t\tresponse += \"• 'current provider' - Show current provider\\n\"\n\t\tresponse += \"• 'list providers' - Show this list\\n\"\n\n\t\tctx.Response = response\n\t\treturn nil\n\t})\n\n\t// Provider-specific commands (force use of specific provider)\n\tr.Handle(\"with * *\", func(ctx *router.Context) error {\n\t\tproviderName := normalizeProviderName(ctx.Captures[0])\n\t\tcommand := ctx.Captures[1]\n\n\t\tprovider, exists := providerRegistry[providerName]\n\t\tif !exists {\n\t\t\tavailableProviders := getProviderList()\n\t\t\tctx.Response = fmt.Sprintf(\"āŒ Provider '%s' not available. Available providers: %s\",\n\t\t\t\tctx.Captures[0], strings.Join(availableProviders, \", \"))\n\t\t\treturn nil\n\t\t}\n\n\t\t// Execute the command with the specified provider\n\t\tresponse, err := provider.Complete(command, config.CompletionOptions{\n\t\t\tModel: getModelForProvider(provider),\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tctx.Response = fmt.Sprintf(\"[Using %s]\\n\\n%s\", providerName, response)\n\t\treturn nil\n\t})\n}\n\n// normalizeProviderName converts provider names to the correct case\nfunc normalizeProviderName(name string) string {\n\tswitch strings.ToLower(name) {\n\tcase \"openai\":\n\t\treturn \"OpenAI\"\n\tcase \"deepseek\":\n\t\treturn \"DeepSeek\"\n\tcase \"gemini\":\n\t\treturn \"Gemini\"\n\tcase \"ollama\":\n\t\treturn \"Ollama\"\n\tcase \"huggingface\":\n\t\treturn \"HuggingFace\"\n\tdefault:\n\t\treturn strings.Title(strings.ToLower(name))\n\t}\n}\n\n// setupUniversalRoutes creates routes that work with any available provider\nfunc setupUniversalRoutes(r *router.Router) {\n\t// Translation route - works with any provider\n\tr.Handle(\"translate * to *\", func(ctx *router.Context) error {\n\t\ttext := ctx.Captures[0]\n\t\tlanguage := ctx.Captures[1]\n\n\t\tprovider := getCurrentProvider(\"translation\")\n\t\tif provider == nil {\n\t\t\treturn fmt.Errorf(\"no AI providers available\")\n\t\t}\n\n\t\tprompt := fmt.Sprintf(\"Translate the following text to %s: %s\", language, text)\n\t\tresponse, err := provider.Complete(prompt, config.CompletionOptions{\n\t\t\tModel: getModelForProvider(provider),\n\t\t\tSystemPrompt: \"You are a professional translator. Provide accurate translations.\",\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tproviderInfo := \"\"\n\t\tif currentProvider == \"\" {\n\t\t\tproviderInfo = fmt.Sprintf(\"[Auto-selected: %s]\\n\\n\", provider.GetName())\n\t\t} else {\n\t\t\tproviderInfo = fmt.Sprintf(\"[Using: %s]\\n\\n\", provider.GetName())\n\t\t}\n\n\t\tctx.Response = providerInfo + response\n\t\treturn nil\n\t})\n\n\t// Summarization route - works with any provider\n\tr.Handle(\"summarize *\", func(ctx *router.Context) error {\n\t\tprovider := getCurrentProvider(\"summary\")\n\t\tif provider == nil {\n\t\t\treturn fmt.Errorf(\"no AI providers available\")\n\t\t}\n\n\t\tresponse, err := provider.Complete(ctx.Captures[0], config.CompletionOptions{\n\t\t\tModel: getModelForProvider(provider),\n\t\t\tSystemPrompt: \"You are a summarization expert. Provide concise, clear summaries.\",\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tproviderInfo := \"\"\n\t\tif currentProvider == \"\" {\n\t\t\tproviderInfo = fmt.Sprintf(\"[Auto-selected: %s]\\n\\n\", provider.GetName())\n\t\t} else {\n\t\t\tproviderInfo = fmt.Sprintf(\"[Using: %s]\\n\\n\", provider.GetName())\n\t\t}\n\n\t\tctx.Response = providerInfo + response\n\t\treturn nil\n\t})\n\n\t// Reasoning route - works with any provider\n\tr.Handle(\"think about *\", func(ctx *router.Context) error {\n\t\tprovider := getCurrentProvider(\"reasoning\")\n\t\tif provider == nil {\n\t\t\treturn fmt.Errorf(\"no AI providers available\")\n\t\t}\n\n\t\tresponse, err := provider.Complete(ctx.Captures[0], config.CompletionOptions{\n\t\t\tModel: getModelForProvider(provider),\n\t\t\tSystemPrompt: \"You are a deep thinking AI. Provide thoughtful, analytical responses.\",\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tproviderInfo := \"\"\n\t\tif currentProvider == \"\" {\n\t\t\tproviderInfo = fmt.Sprintf(\"[Auto-selected: %s]\\n\\n\", provider.GetName())\n\t\t} else {\n\t\t\tproviderInfo = fmt.Sprintf(\"[Using: %s]\\n\\n\", provider.GetName())\n\t\t}\n\n\t\tctx.Response = providerInfo + response\n\t\treturn nil\n\t})\n\n\t// Step-by-step reasoning\n\tr.Handle(\"reason through *\", func(ctx *router.Context) error {\n\t\tprovider := getCurrentProvider(\"reasoning\")\n\t\tif provider == nil {\n\t\t\treturn fmt.Errorf(\"no AI providers available\")\n\t\t}\n\n\t\tprompt := fmt.Sprintf(\"Please reason through this step by step: %s\", ctx.Captures[0])\n\t\tresponse, err := provider.Complete(prompt, config.CompletionOptions{\n\t\t\tModel: getModelForProvider(provider),\n\t\t\tSystemPrompt: \"You are an expert at logical reasoning. Break down problems step by step.\",\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tproviderInfo := \"\"\n\t\tif currentProvider == \"\" {\n\t\t\tproviderInfo = fmt.Sprintf(\"[Auto-selected: %s]\\n\\n\", provider.GetName())\n\t\t} else {\n\t\t\tproviderInfo = fmt.Sprintf(\"[Using: %s]\\n\\n\", provider.GetName())\n\t\t}\n\n\t\tctx.Response = providerInfo + response\n\t\treturn nil\n\t})\n\n\t// Code generation route\n\tr.Handle(\"generate code for *\", func(ctx *router.Context) error {\n\t\tprovider := getCurrentProvider(\"coding\")\n\t\tif provider == nil {\n\t\t\treturn fmt.Errorf(\"no AI providers available\")\n\t\t}\n\n\t\tprompt := fmt.Sprintf(\"Write clean, well-documented code for: %s\", ctx.Captures[0])\n\t\tresponse, err := provider.Complete(prompt, config.CompletionOptions{\n\t\t\tModel: getModelForProvider(provider),\n\t\t\tSystemPrompt: \"You are an expert programmer. Write clean, efficient, and well-documented code.\",\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tproviderInfo := \"\"\n\t\tif currentProvider == \"\" {\n\t\t\tproviderInfo = fmt.Sprintf(\"[Auto-selected: %s]\\n\\n\", provider.GetName())\n\t\t} else {\n\t\t\tproviderInfo = fmt.Sprintf(\"[Using: %s]\\n\\n\", provider.GetName())\n\t\t}\n\n\t\tctx.Response = providerInfo + response\n\t\treturn nil\n\t})\n\n\t// General chat route\n\tr.Handle(\"chat *\", func(ctx *router.Context) error {\n\t\tprovider := getCurrentProvider(\"general\")\n\t\tif provider == nil {\n\t\t\treturn fmt.Errorf(\"no AI providers available\")\n\t\t}\n\n\t\tresponse, err := provider.Complete(ctx.Captures[0], config.CompletionOptions{\n\t\t\tModel: getModelForProvider(provider),\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tproviderInfo := \"\"\n\t\tif currentProvider == \"\" {\n\t\t\tproviderInfo = fmt.Sprintf(\"[Auto-selected: %s]\\n\\n\", provider.GetName())\n\t\t} else {\n\t\t\tproviderInfo = fmt.Sprintf(\"[Using: %s]\\n\\n\", provider.GetName())\n\t\t}\n\n\t\tctx.Response = providerInfo + response\n\t\treturn nil\n\t})\n\n\t// Sentiment analysis\n\tr.Handle(\"analyze sentiment of *\", func(ctx *router.Context) error {\n\t\tprovider := getCurrentProvider(\"general\")\n\t\tif provider == nil {\n\t\t\treturn fmt.Errorf(\"no AI providers available\")\n\t\t}\n\n\t\tprompt := fmt.Sprintf(\"Analyze the sentiment of this text and explain your reasoning: %s\", ctx.Captures[0])\n\t\tresponse, err := provider.Complete(prompt, config.CompletionOptions{\n\t\t\tModel: getModelForProvider(provider),\n\t\t\tSystemPrompt: \"You are a sentiment analysis expert. Analyze text sentiment and provide detailed explanations.\",\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tproviderInfo := \"\"\n\t\tif currentProvider == \"\" {\n\t\t\tproviderInfo = fmt.Sprintf(\"[Auto-selected: %s]\\n\\n\", provider.GetName())\n\t\t} else {\n\t\t\tproviderInfo = fmt.Sprintf(\"[Using: %s]\\n\\n\", provider.GetName())\n\t\t}\n\n\t\tctx.Response = providerInfo + response\n\t\treturn nil\n\t})\n}\n\n// getModelForProvider returns the appropriate model name for each provider\nfunc getModelForProvider(provider providers.Provider) string {\n\tswitch provider.GetName() {\n\tcase \"OpenAI\":\n\t\treturn \"gpt-3.5-turbo\"\n\tcase \"DeepSeek\":\n\t\treturn \"deepseek-chat\"\n\tcase \"Gemini\":\n\t\treturn \"gemini-pro\"\n\tcase \"Ollama\":\n\t\treturn \"llama2\"\n\tcase \"HuggingFace\":\n\t\treturn \"gpt2\"\n\tdefault:\n\t\treturn \"\"\n\t}\n}\n\nfunc setupExampleRoutes(r *router.Router) {\n\t// Enhanced help command\n\tr.Handle(\"help\", func(ctx *router.Context) error {\n\t\thelp := `\n🧠 NeuroGO Framework - Available Commands:\n\nšŸ“‹ General Commands:\n- \"help\" - Show this help message\n- \"status\" - Show system status and configured providers\n\nšŸ”„ Provider Management:\n- \"list providers\" - Show all available providers\n- \"use [provider]\" - Switch to specific provider (e.g., \"use deepseek\")\n- \"use auto\" - Auto-select best provider for each task\n- \"current provider\" - Show currently selected provider\n- \"with [provider] [command]\" - Run one command with specific provider\n\n🌟 Universal Commands (work with any provider):\n- \"translate [text] to [language]\" - Translate text\n- \"summarize [text]\" - Summarize content\n- \"think about [topic]\" - Deep analysis\n- \"reason through [problem]\" - Step-by-step reasoning\n- \"generate code for [task]\" - Generate code\n- \"chat [message]\" - General conversation\n- \"analyze sentiment of [text]\" - Sentiment analysis\n\nšŸ’” Examples:\n- \"use deepseek\" → \"translate hello to Spanish\"\n- \"with openai explain quantum computing\"\n- \"list providers\"\n- \"current provider\"\n\nšŸ”§ Your configured providers: `\n\n\t\tvar configuredProviders []string\n\t\tfor name := range providerRegistry {\n\t\t\tconfiguredProviders = append(configuredProviders, name)\n\t\t}\n\n\t\tif len(configuredProviders) > 0 {\n\t\t\thelp += strings.Join(configuredProviders, \", \")\n\t\t} else {\n\t\t\thelp += \"None\"\n\t\t}\n\n\t\tif currentProvider != \"\" {\n\t\t\thelp += fmt.Sprintf(\"\\nšŸŽÆ Currently using: %s\", currentProvider)\n\t\t} else {\n\t\t\thelp += \"\\nšŸ¤– Currently in auto mode\"\n\t\t}\n\n\t\thelp += `\n\nšŸš€ Switch providers anytime to compare responses!\n\t\t`\n\n\t\tctx.Response = help\n\t\treturn nil\n\t})\n\n\t// Enhanced status command\n\tr.Handle(\"status\", func(ctx *router.Context) error {\n\t\tstatus := map[string]interface{}{\n\t\t\t\"framework\": \"NeuroGO\",\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"status\": \"running\",\n\t\t\t\"providers\": map[string]interface{}{\n\t\t\t\t\"configured\": []string{},\n\t\t\t\t\"available\": []string{},\n\t\t\t\t\"current\": currentProvider,\n\t\t\t\t\"mode\": \"auto\",\n\t\t\t\t\"total\": 0,\n\t\t\t},\n\t\t}\n\n\t\tvar configured []string\n\t\tfor name := range providerRegistry {\n\t\t\tconfigured = append(configured, name)\n\t\t}\n\n\t\tif currentProvider != \"\" {\n\t\t\tstatus[\"providers\"].(map[string]interface{})[\"mode\"] = \"manual\"\n\t\t}\n\n\t\tstatus[\"providers\"].(map[string]interface{})[\"configured\"] = configured\n\t\tstatus[\"providers\"].(map[string]interface{})[\"available\"] = configured\n\t\tstatus[\"providers\"].(map[string]interface{})[\"total\"] = len(configured)\n\n\t\tif len(configured) == 0 {\n\t\t\tstatus[\"message\"] = \"No providers configured. Install Ollama or add API keys to get started.\"\n\t\t} else {\n\t\t\tif currentProvider != \"\" {\n\t\t\t\tstatus[\"message\"] = fmt.Sprintf(\"Ready! Using %s provider. %d total provider(s) available.\", currentProvider, len(configured))\n\t\t\t} else {\n\t\t\t\tstatus[\"message\"] = fmt.Sprintf(\"Ready! Auto mode - %d provider(s) available: %s\", len(configured), strings.Join(configured, \", \"))\n\t\t\t}\n\t\t}\n\n\t\tjsonData, _ := json.MarshalIndent(status, \"\", \" \")\n\t\tctx.Response = string(jsonData)\n\t\treturn nil\n\t})\n}\n\nfunc setupStaticFiles(r *mux.Router) {\n\t// Serve static files\n\tstaticDir := \"../../web/static/\"\n\n\tr.PathPrefix(\"/static/\").Handler(http.StripPrefix(\"/static/\", http.FileServer(http.Dir(staticDir))))\n\n\t// API Documentation endpoint\n\tr.HandleFunc(\"/docs\", func(w http.ResponseWriter, r *http.Request) {\n\t\tw.Header().Set(\"Content-Type\", \"text/html\")\n\n\t\t// Try multiple possible paths for docs.html\n\t\tdocsPaths := []string{\n\t\t\t\"../../web/docs.html\",\n\t\t\t\"../../web/docs.html\",\n\t\t\t\"docs.html\",\n\t\t}\n\n\t\tfor _, docsPath := range docsPaths {\n\t\t\tif _, err := os.Stat(docsPath); err == nil {\n\t\t\t\tlog.Printf(\"āœ… Serving docs from: %s\", docsPath)\n\t\t\t\thttp.ServeFile(w, r, docsPath)\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\t// If no file found, log and serve fallback\n\t\tlog.Println(\"āš ļø docs.html file not found, serving embedded fallback\")\n\t\tfmt.Fprint(w, getEmbeddedDocsHTML())\n\t})\n\n\t// Serve the playground UI\n\tr.HandleFunc(\"/\", func(w http.ResponseWriter, r *http.Request) {\n\t\t// Try multiple possible paths for index.html\n\t\tindexPaths := []string{\n\t\t\t\"../../web/index.html\",\n\t\t\t\"../../web/index.html\",\n\t\t\t\"index.html\",\n\t\t}\n\n\t\tfor _, indexPath := range indexPaths {\n\t\t\tif _, err := os.Stat(indexPath); err == nil {\n\t\t\t\tlog.Printf(\"āœ… Serving index from: %s\", indexPath)\n\t\t\t\thttp.ServeFile(w, r, indexPath)\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\t// If no file found, serve fallback\n\t\tlog.Println(\"āš ļø index.html file not found, serving embedded fallback\")\n\t\tw.Header().Set(\"Content-Type\", \"text/html\")\n\t\tfmt.Fprint(w, getEmbeddedHTML())\n\t})\n}\n\nfunc getEmbeddedHTML() string {\n\treturn `\n\n\n \n \n NeuroGO Playground\n \n\n\n
\n
\n

🧠 NeuroGO Playground

\n

Test your AI command router with natural language prompts

\n
\n \n
\n šŸ“š API Documentation\n šŸ” Health Check\n šŸ›£ļø Routes\n
\n \n
\n
\n

šŸ”— Available Endpoints:

\n

REST API: /api/process, /api/health, /api/routes

\n

WebSocket: /ws

\n

Documentation: /docs (Full API testing interface)

\n
\n \n
\n

šŸ”„ Provider Management

\n

Switch between AI providers or let the system auto-select the best one for each task.

\n
\n \n
\n \n \n
\n \n \n \n
\n
\n

Processing your request...

\n
\n \n
\n

Response:

\n
\n            
\n \n
\n

Example Commands:

\n \n

šŸ”„ Provider Management:

\n
list providers
\n
current provider
\n
use deepseek
\n
use auto
\n \n

🌟 Universal Commands:

\n
translate hello world to Spanish
\n
think about artificial intelligence
\n
summarize the benefits of renewable energy
\n
generate code for a simple calculator
\n \n

šŸŽÆ Provider-Specific Commands:

\n
with deepseek explain quantum computing
\n
with openai write a poem about nature
\n \n

šŸ“‹ System Commands:

\n
help
\n
status
\n
\n
\n
\n\n \n\n`\n}\n\n// getEmbeddedDocsHTML returns a minimal fallback for docs if file doesn't exist\nfunc getEmbeddedDocsHTML() string {\n\treturn `\n\n\n \n \n NeuroGO API Documentation\n \n\n\n
\n

🧠 NeuroGO API Documentation

\n
\n Documentation file not found.
\n The docs.html file is missing. Please ensure web/docs.html exists.\n
\n
\n ← Back to Playground\n Health Check\n API Routes\n
\n

For now, you can use the main playground interface or access the API endpoints directly.

\n
\n\n`\n}\n"}, "e020db6345d007d9b7bf69b1f066c6ec63674315": {"t": 1785755007.0740845, "n": 31716, "h": "e179539cedc4fefb", "c": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n\t\"strings\"\n\n\t\"github.com/gorilla/mux\"\n\t\"github.com/joho/godotenv\"\n\t\"github.com/rs/cors\"\n\n\t\"github.com/aldotobing/neurogo/config\"\n\t\"github.com/aldotobing/neurogo/providers\"\n\t\"github.com/aldotobing/neurogo/router\"\n\t\"github.com/aldotobing/neurogo/server\"\n)\n\n// Global provider registry and current provider\nvar providerRegistry = make(map[string]providers.Provider)\nvar currentProvider = \"\"\n\nfunc main() {\n\t// Debug: Print current working directory and file existence\n\tif cwd, err := os.Getwd(); err == nil {\n\t\tlog.Printf(\"šŸ” Current working directory: %s\", cwd)\n\t}\n\n\t// Check if web files exist\n\twebFiles := []string{\"../../web/docs.html\", \"../../web/index.html\", \"../../web/static/app.js\", \"../../web/static/style.css\"}\n\tfor _, file := range webFiles {\n\t\tif _, err := os.Stat(file); err == nil {\n\t\t\tlog.Printf(\"āœ… Found: %s\", file)\n\t\t} else {\n\t\t\tlog.Printf(\"āŒ Missing: %s\", file)\n\t\t}\n\t}\n\n\t// Load environment variables with better error handling\n\tloadEnvironment()\n\n\t// Initialize the NeuroGO router\n\tneuroRouter := router.New()\n\n\t// Configure providers\n\tsetupProviders(neuroRouter)\n\n\t// Setup universal routes (works with any provider)\n\tsetupUniversalRoutes(neuroRouter)\n\n\t// Setup provider switching routes\n\tsetupProviderSwitchingRoutes(neuroRouter)\n\n\t// Setup example routes\n\tsetupExampleRoutes(neuroRouter)\n\n\t// Create HTTP server\n\thttpRouter := mux.NewRouter()\n\n\t// Setup API routes\n\tapi := httpRouter.PathPrefix(\"/api\").Subrouter()\n\tserver.SetupAPIRoutes(api, neuroRouter)\n\n\t// Setup WebSocket for real-time communication\n\tserver.SetupWebSocket(httpRouter, neuroRouter)\n\n\t// Serve static files for the playground\n\tsetupStaticFiles(httpRouter)\n\n\t// Setup CORS\n\tc := cors.New(cors.Options{\n\t\tAllowedOrigins: []string{\"*\"},\n\t\tAllowedMethods: []string{\"GET\", \"POST\", \"PUT\", \"DELETE\", \"OPTIONS\"},\n\t\tAllowedHeaders: []string{\"*\"},\n\t})\n\n\thandler := c.Handler(httpRouter)\n\n\tport := os.Getenv(\"PORT\")\n\tif port == \"\" {\n\t\tport = \"8080\"\n\t}\n\n\tfmt.Printf(\"šŸš€ NeuroGO server starting on port %s\\n\", port)\n\tfmt.Printf(\"šŸ“± Playground UI: http://localhost:%s\\n\", port)\n\tfmt.Printf(\"šŸ“š API Documentation: http://localhost:%s/docs\\n\", port)\n\tfmt.Printf(\"šŸ”— API Endpoint: http://localhost:%s/api\\n\", port)\n\n\tlog.Fatal(http.ListenAndServe(\":\"+port, handler))\n}\n\n// loadEnvironment loads environment variables with better error handling\nfunc loadEnvironment() {\n\t// Try to load .env file from current directory\n\tif err := godotenv.Load(); err != nil {\n\t\t// Try to load from parent directory (in case we're in cmd/server)\n\t\tif err := godotenv.Load(\"../../.env\"); err != nil {\n\t\t\tlog.Println(\"No .env file found, using system environment variables\")\n\t\t} else {\n\t\t\tlog.Println(\"āœ… Loaded .env file from parent directory\")\n\t\t}\n\t} else {\n\t\tlog.Println(\"āœ… Loaded .env file successfully\")\n\t}\n\n\t// Debug: Print which environment variables are set\n\tdebugEnvironmentVariables()\n}\n\n// debugEnvironmentVariables prints which environment variables are detected\nfunc debugEnvironmentVariables() {\n\tenvVars := []string{\n\t\t\"OPENAI_API_KEY\",\n\t\t\"DEEPSEEK_API_KEY\",\n\t\t\"GEMINI_API_KEY\",\n\t\t\"HUGGINGFACE_API_KEY\",\n\t\t\"OLLAMA_HOST\",\n\t}\n\n\tlog.Println(\"šŸ” Environment Variables Status:\")\n\tfor _, envVar := range envVars {\n\t\tvalue := os.Getenv(envVar)\n\t\tif value != \"\" {\n\t\t\t// Don't print the full API key for security\n\t\t\tif len(value) > 10 {\n\t\t\t\tlog.Printf(\" āœ… %s: %s...%s\", envVar, value[:4], value[len(value)-4:])\n\t\t\t} else {\n\t\t\t\tlog.Printf(\" āœ… %s: %s\", envVar, value)\n\t\t\t}\n\t\t} else {\n\t\t\tlog.Printf(\" āŒ %s: not set\", envVar)\n\t\t}\n\t}\n}\n\n// getCurrentProvider returns the currently selected provider or the best available one\nfunc getCurrentProvider(taskType string) providers.Provider {\n\t// If a specific provider is selected, use it\n\tif currentProvider != \"\" {\n\t\tif provider, exists := providerRegistry[currentProvider]; exists {\n\t\t\treturn provider\n\t\t}\n\t}\n\n\t// Otherwise, use the best provider for the task type\n\treturn getBestProvider(taskType)\n}\n\n// getBestProvider returns the best available provider for a given task type\nfunc getBestProvider(taskType string) providers.Provider {\n\t// Provider preferences for different task types\n\tpreferences := map[string][]string{\n\t\t\"translation\": {\"Gemini\", \"OpenAI\", \"DeepSeek\", \"Ollama\"},\n\t\t\"reasoning\": {\"DeepSeek\", \"OpenAI\", \"Gemini\", \"Ollama\"},\n\t\t\"coding\": {\"Ollama\", \"OpenAI\", \"DeepSeek\", \"Gemini\"},\n\t\t\"summary\": {\"OpenAI\", \"DeepSeek\", \"Gemini\", \"Ollama\"},\n\t\t\"general\": {\"OpenAI\", \"DeepSeek\", \"Gemini\", \"Ollama\"},\n\t}\n\n\tproviderList, exists := preferences[taskType]\n\tif !exists {\n\t\tproviderList = preferences[\"general\"]\n\t}\n\n\t// Return the first available provider from the preference list\n\tfor _, providerName := range providerList {\n\t\tif provider, exists := providerRegistry[providerName]; exists {\n\t\t\treturn provider\n\t\t}\n\t}\n\n\t// Fallback: return any available provider\n\tfor _, provider := range providerRegistry {\n\t\treturn provider\n\t}\n\n\treturn nil\n}\n\n// getProviderList returns a list of available provider names\nfunc getProviderList() []string {\n\tvar providers []string\n\tfor name := range providerRegistry {\n\t\tproviders = append(providers, name)\n\t}\n\treturn providers\n}\n\nfunc setupProviders(r *router.Router) {\n\tavailableProviders := []string{}\n\n\t// OpenAI Provider\n\tif apiKey := os.Getenv(\"OPENAI_API_KEY\"); apiKey != \"\" {\n\t\topenAIProvider := providers.NewOpenAI(apiKey)\n\t\tif openAIProvider.IsAvailable() {\n\t\t\tproviderRegistry[\"OpenAI\"] = openAIProvider\n\t\t\tavailableProviders = append(availableProviders, \"OpenAI\")\n\t\t\tlog.Println(\"āœ… OpenAI provider configured\")\n\t\t} else {\n\t\t\tlog.Println(\"āŒ OpenAI provider configuration failed\")\n\t\t}\n\t} else {\n\t\tlog.Println(\"āš ļø OpenAI API key not provided\")\n\t}\n\n\t// DeepSeek Provider\n\tif apiKey := os.Getenv(\"DEEPSEEK_API_KEY\"); apiKey != \"\" {\n\t\tdeepSeekProvider := providers.NewDeepSeek(apiKey)\n\t\tif deepSeekProvider.IsAvailable() {\n\t\t\tproviderRegistry[\"DeepSeek\"] = deepSeekProvider\n\t\t\tavailableProviders = append(availableProviders, \"DeepSeek\")\n\t\t\tlog.Println(\"āœ… DeepSeek provider configured\")\n\t\t} else {\n\t\t\tlog.Println(\"āŒ DeepSeek provider configuration failed\")\n\t\t}\n\t} else {\n\t\tlog.Println(\"āš ļø DeepSeek API key not provided\")\n\t}\n\n\t// Gemini Provider\n\tif apiKey := os.Getenv(\"GEMINI_API_KEY\"); apiKey != \"\" {\n\t\tgeminiProvider := providers.NewGemini(apiKey)\n\t\tif geminiProvider.IsAvailable() {\n\t\t\tproviderRegistry[\"Gemini\"] = geminiProvider\n\t\t\tavailableProviders = append(availableProviders, \"Gemini\")\n\t\t\tlog.Println(\"āœ… Gemini provider configured\")\n\t\t} else {\n\t\t\tlog.Println(\"āŒ Gemini provider configuration failed\")\n\t\t}\n\t} else {\n\t\tlog.Println(\"āš ļø Gemini API key not provided\")\n\t}\n\n\t// Ollama Provider\n\tollamaHost := os.Getenv(\"OLLAMA_HOST\")\n\tif ollamaHost == \"\" {\n\t\tollamaHost = \"http://localhost:11434\"\n\t}\n\n\tlog.Printf(\"šŸ” Checking Ollama at: %s\", ollamaHost)\n\tollamaProvider := providers.NewOllama(ollamaHost)\n\tif ollamaProvider.IsAvailable() {\n\t\tproviderRegistry[\"Ollama\"] = ollamaProvider\n\t\tavailableProviders = append(availableProviders, \"Ollama\")\n\t\tlog.Println(\"āœ… Ollama provider configured\")\n\t} else {\n\t\tlog.Printf(\"āš ļø Ollama not available - make sure Ollama is running on %s\", ollamaHost)\n\t}\n\n\t// HuggingFace Provider\n\tif apiKey := os.Getenv(\"HUGGINGFACE_API_KEY\"); apiKey != \"\" {\n\t\thfProvider := providers.NewHuggingFace(apiKey)\n\t\tif hfProvider.IsAvailable() {\n\t\t\tproviderRegistry[\"HuggingFace\"] = hfProvider\n\t\t\tavailableProviders = append(availableProviders, \"HuggingFace\")\n\t\t\tlog.Println(\"āœ… HuggingFace provider configured\")\n\t\t} else {\n\t\t\tlog.Println(\"āŒ HuggingFace provider configuration failed\")\n\t\t}\n\t} else {\n\t\tlog.Println(\"āš ļø HuggingFace API key not provided\")\n\t}\n\n\t// Set default provider to the first available one\n\tif len(availableProviders) > 0 && currentProvider == \"\" {\n\t\tcurrentProvider = availableProviders[0]\n\t\tlog.Printf(\"šŸŽÆ Default provider set to: %s\", currentProvider)\n\t}\n\n\t// Log summary\n\tif len(availableProviders) == 0 {\n\t\tlog.Println(\"āš ļø No AI providers configured. Only basic commands will work.\")\n\t\tlog.Println(\"šŸ’” To get started with Ollama: run 'ollama serve' and 'ollama pull llama2'\")\n\t\tlog.Println(\"šŸ’” Or add API keys to your .env file for cloud providers\")\n\t} else {\n\t\tlog.Printf(\"šŸŽ‰ Configured providers: %v\", availableProviders)\n\t}\n}\n\n// setupProviderSwitchingRoutes creates routes for switching between providers\nfunc setupProviderSwitchingRoutes(r *router.Router) {\n\t// Switch to a specific provider\n\tr.Handle(\"use *\", func(ctx *router.Context) error {\n\t\tproviderName := normalizeProviderName(ctx.Captures[0])\n\n\t\tif _, exists := providerRegistry[providerName]; exists {\n\t\t\tcurrentProvider = providerName\n\t\t\tctx.Response = fmt.Sprintf(\"āœ… Switched to %s provider. All subsequent commands will use %s.\", providerName, providerName)\n\t\t} else {\n\t\t\tavailableProviders := getProviderList()\n\t\t\tctx.Response = fmt.Sprintf(\"āŒ Provider '%s' not available. Available providers: %s\",\n\t\t\t\tctx.Captures[0], strings.Join(availableProviders, \", \"))\n\t\t}\n\t\treturn nil\n\t})\n\n\t// Switch to auto mode (best provider for each task)\n\tr.Handle(\"use auto\", func(ctx *router.Context) error {\n\t\tcurrentProvider = \"\"\n\t\tctx.Response = \"āœ… Switched to auto mode. The system will automatically choose the best provider for each task.\"\n\t\treturn nil\n\t})\n\n\t// Show current provider\n\tr.Handle(\"current provider\", func(ctx *router.Context) error {\n\t\tif currentProvider == \"\" {\n\t\t\tctx.Response = \"šŸ¤– Currently in auto mode - the system chooses the best provider for each task.\"\n\t\t} else {\n\t\t\tctx.Response = fmt.Sprintf(\"šŸŽÆ Currently using: %s\", currentProvider)\n\t\t}\n\t\treturn nil\n\t})\n\n\t// List all available providers\n\tr.Handle(\"list providers\", func(ctx *router.Context) error {\n\t\tproviders := getProviderList()\n\t\tif len(providers) == 0 {\n\t\t\tctx.Response = \"āŒ No providers configured.\"\n\t\t\treturn nil\n\t\t}\n\n\t\tresponse := \"šŸ“‹ Available providers:\\n\\n\"\n\t\tfor _, name := range providers {\n\t\t\tif name == currentProvider {\n\t\t\t\tresponse += fmt.Sprintf(\"šŸŽÆ %s (currently selected)\\n\", name)\n\t\t\t} else {\n\t\t\t\tresponse += fmt.Sprintf(\" %s\\n\", name)\n\t\t\t}\n\t\t}\n\n\t\tresponse += \"\\nšŸ’” Commands:\\n\"\n\t\tresponse += \"• 'use [provider]' - Switch to specific provider\\n\"\n\t\tresponse += \"• 'use auto' - Auto-select best provider for each task\\n\"\n\t\tresponse += \"• 'current provider' - Show current provider\\n\"\n\t\tresponse += \"• 'list providers' - Show this list\\n\"\n\n\t\tctx.Response = response\n\t\treturn nil\n\t})\n\n\t// Provider-specific commands (force use of specific provider)\n\tr.Handle(\"with * *\", func(ctx *router.Context) error {\n\t\tproviderName := normalizeProviderName(ctx.Captures[0])\n\t\tcommand := ctx.Captures[1]\n\n\t\tprovider, exists := providerRegistry[providerName]\n\t\tif !exists {\n\t\t\tavailableProviders := getProviderList()\n\t\t\tctx.Response = fmt.Sprintf(\"āŒ Provider '%s' not available. Available providers: %s\",\n\t\t\t\tctx.Captures[0], strings.Join(availableProviders, \", \"))\n\t\t\treturn nil\n\t\t}\n\n\t\t// Execute the command with the specified provider\n\t\tresponse, err := provider.Complete(command, config.CompletionOptions{\n\t\t\tModel: getModelForProvider(provider),\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tctx.Response = fmt.Sprintf(\"[Using %s]\\n\\n%s\", providerName, response)\n\t\treturn nil\n\t})\n}\n\n// normalizeProviderName converts provider names to the correct case\nfunc normalizeProviderName(name string) string {\n\tswitch strings.ToLower(name) {\n\tcase \"openai\":\n\t\treturn \"OpenAI\"\n\tcase \"deepseek\":\n\t\treturn \"DeepSeek\"\n\tcase \"gemini\":\n\t\treturn \"Gemini\"\n\tcase \"ollama\":\n\t\treturn \"Ollama\"\n\tcase \"huggingface\":\n\t\treturn \"HuggingFace\"\n\tdefault:\n\t\treturn strings.Title(strings.ToLower(name))\n\t}\n}\n\n// setupUniversalRoutes creates routes that work with any available provider\nfunc setupUniversalRoutes(r *router.Router) {\n\t// Translation route - works with any provider\n\tr.Handle(\"translate * to *\", func(ctx *router.Context) error {\n\t\ttext := ctx.Captures[0]\n\t\tlanguage := ctx.Captures[1]\n\n\t\tprovider := getCurrentProvider(\"translation\")\n\t\tif provider == nil {\n\t\t\treturn fmt.Errorf(\"no AI providers available\")\n\t\t}\n\n\t\tprompt := fmt.Sprintf(\"Translate the following text to %s: %s\", language, text)\n\t\tresponse, err := provider.Complete(prompt, config.CompletionOptions{\n\t\t\tModel: getModelForProvider(provider),\n\t\t\tSystemPrompt: \"You are a professional translator. Provide accurate translations.\",\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tproviderInfo := \"\"\n\t\tif currentProvider == \"\" {\n\t\t\tproviderInfo = fmt.Sprintf(\"[Auto-selected: %s]\\n\\n\", provider.GetName())\n\t\t} else {\n\t\t\tproviderInfo = fmt.Sprintf(\"[Using: %s]\\n\\n\", provider.GetName())\n\t\t}\n\n\t\tctx.Response = providerInfo + response\n\t\treturn nil\n\t})\n\n\t// Summarization route - works with any provider\n\tr.Handle(\"summarize *\", func(ctx *router.Context) error {\n\t\tprovider := getCurrentProvider(\"summary\")\n\t\tif provider == nil {\n\t\t\treturn fmt.Errorf(\"no AI providers available\")\n\t\t}\n\n\t\tresponse, err := provider.Complete(ctx.Captures[0], config.CompletionOptions{\n\t\t\tModel: getModelForProvider(provider),\n\t\t\tSystemPrompt: \"You are a summarization expert. Provide concise, clear summaries.\",\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tproviderInfo := \"\"\n\t\tif currentProvider == \"\" {\n\t\t\tproviderInfo = fmt.Sprintf(\"[Auto-selected: %s]\\n\\n\", provider.GetName())\n\t\t} else {\n\t\t\tproviderInfo = fmt.Sprintf(\"[Using: %s]\\n\\n\", provider.GetName())\n\t\t}\n\n\t\tctx.Response = providerInfo + response\n\t\treturn nil\n\t})\n\n\t// Reasoning route - works with any provider\n\tr.Handle(\"think about *\", func(ctx *router.Context) error {\n\t\tprovider := getCurrentProvider(\"reasoning\")\n\t\tif provider == nil {\n\t\t\treturn fmt.Errorf(\"no AI providers available\")\n\t\t}\n\n\t\tresponse, err := provider.Complete(ctx.Captures[0], config.CompletionOptions{\n\t\t\tModel: getModelForProvider(provider),\n\t\t\tSystemPrompt: \"You are a deep thinking AI. Provide thoughtful, analytical responses.\",\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tproviderInfo := \"\"\n\t\tif currentProvider == \"\" {\n\t\t\tproviderInfo = fmt.Sprintf(\"[Auto-selected: %s]\\n\\n\", provider.GetName())\n\t\t} else {\n\t\t\tproviderInfo = fmt.Sprintf(\"[Using: %s]\\n\\n\", provider.GetName())\n\t\t}\n\n\t\tctx.Response = providerInfo + response\n\t\treturn nil\n\t})\n\n\t// Step-by-step reasoning\n\tr.Handle(\"reason through *\", func(ctx *router.Context) error {\n\t\tprovider := getCurrentProvider(\"reasoning\")\n\t\tif provider == nil {\n\t\t\treturn fmt.Errorf(\"no AI providers available\")\n\t\t}\n\n\t\tprompt := fmt.Sprintf(\"Please reason through this step by step: %s\", ctx.Captures[0])\n\t\tresponse, err := provider.Complete(prompt, config.CompletionOptions{\n\t\t\tModel: getModelForProvider(provider),\n\t\t\tSystemPrompt: \"You are an expert at logical reasoning. Break down problems step by step.\",\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tproviderInfo := \"\"\n\t\tif currentProvider == \"\" {\n\t\t\tproviderInfo = fmt.Sprintf(\"[Auto-selected: %s]\\n\\n\", provider.GetName())\n\t\t} else {\n\t\t\tproviderInfo = fmt.Sprintf(\"[Using: %s]\\n\\n\", provider.GetName())\n\t\t}\n\n\t\tctx.Response = providerInfo + response\n\t\treturn nil\n\t})\n\n\t// Code generation route\n\tr.Handle(\"generate code for *\", func(ctx *router.Context) error {\n\t\tprovider := getCurrentProvider(\"coding\")\n\t\tif provider == nil {\n\t\t\treturn fmt.Errorf(\"no AI providers available\")\n\t\t}\n\n\t\tprompt := fmt.Sprintf(\"Write clean, well-documented code for: %s\", ctx.Captures[0])\n\t\tresponse, err := provider.Complete(prompt, config.CompletionOptions{\n\t\t\tModel: getModelForProvider(provider),\n\t\t\tSystemPrompt: \"You are an expert programmer. Write clean, efficient, and well-documented code.\",\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tproviderInfo := \"\"\n\t\tif currentProvider == \"\" {\n\t\t\tproviderInfo = fmt.Sprintf(\"[Auto-selected: %s]\\n\\n\", provider.GetName())\n\t\t} else {\n\t\t\tproviderInfo = fmt.Sprintf(\"[Using: %s]\\n\\n\", provider.GetName())\n\t\t}\n\n\t\tctx.Response = providerInfo + response\n\t\treturn nil\n\t})\n\n\t// General chat route\n\tr.Handle(\"chat *\", func(ctx *router.Context) error {\n\t\tprovider := getCurrentProvider(\"general\")\n\t\tif provider == nil {\n\t\t\treturn fmt.Errorf(\"no AI providers available\")\n\t\t}\n\n\t\tresponse, err := provider.Complete(ctx.Captures[0], config.CompletionOptions{\n\t\t\tModel: getModelForProvider(provider),\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tproviderInfo := \"\"\n\t\tif currentProvider == \"\" {\n\t\t\tproviderInfo = fmt.Sprintf(\"[Auto-selected: %s]\\n\\n\", provider.GetName())\n\t\t} else {\n\t\t\tproviderInfo = fmt.Sprintf(\"[Using: %s]\\n\\n\", provider.GetName())\n\t\t}\n\n\t\tctx.Response = providerInfo + response\n\t\treturn nil\n\t})\n\n\t// Sentiment analysis\n\tr.Handle(\"analyze sentiment of *\", func(ctx *router.Context) error {\n\t\tprovider := getCurrentProvider(\"general\")\n\t\tif provider == nil {\n\t\t\treturn fmt.Errorf(\"no AI providers available\")\n\t\t}\n\n\t\tprompt := fmt.Sprintf(\"Analyze the sentiment of this text and explain your reasoning: %s\", ctx.Captures[0])\n\t\tresponse, err := provider.Complete(prompt, config.CompletionOptions{\n\t\t\tModel: getModelForProvider(provider),\n\t\t\tSystemPrompt: \"You are a sentiment analysis expert. Analyze text sentiment and provide detailed explanations.\",\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tproviderInfo := \"\"\n\t\tif currentProvider == \"\" {\n\t\t\tproviderInfo = fmt.Sprintf(\"[Auto-selected: %s]\\n\\n\", provider.GetName())\n\t\t} else {\n\t\t\tproviderInfo = fmt.Sprintf(\"[Using: %s]\\n\\n\", provider.GetName())\n\t\t}\n\n\t\tctx.Response = providerInfo + response\n\t\treturn nil\n\t})\n}\n\n// getModelForProvider returns the appropriate model name for each provider\nfunc getModelForProvider(provider providers.Provider) string {\n\tswitch provider.GetName() {\n\tcase \"OpenAI\":\n\t\treturn \"gpt-3.5-turbo\"\n\tcase \"DeepSeek\":\n\t\treturn \"deepseek-chat\"\n\tcase \"Gemini\":\n\t\treturn \"gemini-pro\"\n\tcase \"Ollama\":\n\t\treturn \"llama2\"\n\tcase \"HuggingFace\":\n\t\treturn \"gpt2\"\n\tdefault:\n\t\treturn \"\"\n\t}\n}\n\nfunc setupExampleRoutes(r *router.Router) {\n\t// Enhanced help command\n\tr.Handle(\"help\", func(ctx *router.Context) error {\n\t\thelp := `\n🧠 NeuroGO Framework - Available Commands:\n\nšŸ“‹ General Commands:\n- \"help\" - Show this help message\n- \"status\" - Show system status and configured providers\n\nšŸ”„ Provider Management:\n- \"list providers\" - Show all available providers\n- \"use [provider]\" - Switch to specific provider (e.g., \"use deepseek\")\n- \"use auto\" - Auto-select best provider for each task\n- \"current provider\" - Show currently selected provider\n- \"with [provider] [command]\" - Run one command with specific provider\n\n🌟 Universal Commands (work with any provider):\n- \"translate [text] to [language]\" - Translate text\n- \"summarize [text]\" - Summarize content\n- \"think about [topic]\" - Deep analysis\n- \"reason through [problem]\" - Step-by-step reasoning\n- \"generate code for [task]\" - Generate code\n- \"chat [message]\" - General conversation\n- \"analyze sentiment of [text]\" - Sentiment analysis\n\nšŸ’” Examples:\n- \"use deepseek\" → \"translate hello to Spanish\"\n- \"with openai explain quantum computing\"\n- \"list providers\"\n- \"current provider\"\n\nšŸ”§ Your configured providers: `\n\n\t\tvar configuredProviders []string\n\t\tfor name := range providerRegistry {\n\t\t\tconfiguredProviders = append(configuredProviders, name)\n\t\t}\n\n\t\tif len(configuredProviders) > 0 {\n\t\t\thelp += strings.Join(configuredProviders, \", \")\n\t\t} else {\n\t\t\thelp += \"None\"\n\t\t}\n\n\t\tif currentProvider != \"\" {\n\t\t\thelp += fmt.Sprintf(\"\\nšŸŽÆ Currently using: %s\", currentProvider)\n\t\t} else {\n\t\t\thelp += \"\\nšŸ¤– Currently in auto mode\"\n\t\t}\n\n\t\thelp += `\n\nšŸš€ Switch providers anytime to compare responses!\n\t\t`\n\n\t\tctx.Response = help\n\t\treturn nil\n\t})\n\n\t// Enhanced status command\n\tr.Handle(\"status\", func(ctx *router.Context) error {\n\t\tstatus := map[string]interface{}{\n\t\t\t\"framework\": \"NeuroGO\",\n\t\t\t\"version\": \"1.0.0\",\n\t\t\t\"status\": \"running\",\n\t\t\t\"providers\": map[string]interface{}{\n\t\t\t\t\"configured\": []string{},\n\t\t\t\t\"available\": []string{},\n\t\t\t\t\"current\": currentProvider,\n\t\t\t\t\"mode\": \"auto\",\n\t\t\t\t\"total\": 0,\n\t\t\t},\n\t\t}\n\n\t\tvar configured []string\n\t\tfor name := range providerRegistry {\n\t\t\tconfigured = append(configured, name)\n\t\t}\n\n\t\tif currentProvider != \"\" {\n\t\t\tstatus[\"providers\"].(map[string]interface{})[\"mode\"] = \"manual\"\n\t\t}\n\n\t\tstatus[\"providers\"].(map[string]interface{})[\"configured\"] = configured\n\t\tstatus[\"providers\"].(map[string]interface{})[\"available\"] = configured\n\t\tstatus[\"providers\"].(map[string]interface{})[\"total\"] = len(configured)\n\n\t\tif len(configured) == 0 {\n\t\t\tstatus[\"message\"] = \"No providers configured. Install Ollama or add API keys to get started.\"\n\t\t} else {\n\t\t\tif currentProvider != \"\" {\n\t\t\t\tstatus[\"message\"] = fmt.Sprintf(\"Ready! Using %s provider. %d total provider(s) available.\", currentProvider, len(configured))\n\t\t\t} else {\n\t\t\t\tstatus[\"message\"] = fmt.Sprintf(\"Ready! Auto mode - %d provider(s) available: %s\", len(configured), strings.Join(configured, \", \"))\n\t\t\t}\n\t\t}\n\n\t\tjsonData, _ := json.MarshalIndent(status, \"\", \" \")\n\t\tctx.Response = string(jsonData)\n\t\treturn nil\n\t})\n}\n\nfunc setupStaticFiles(r *mux.Router) {\n\t// Serve static files\n\tstaticDir := \"../../web/static/\"\n\n\tr.PathPrefix(\"/static/\").Handler(http.StripPrefix(\"/static/\", http.FileServer(http.Dir(staticDir))))\n\n\t// API Documentation endpoint\n\tr.HandleFunc(\"/docs\", func(w http.ResponseWriter, r *http.Request) {\n\t\tw.Header().Set(\"Content-Type\", \"text/html\")\n\n\t\t// Try multiple possible paths for docs.html\n\t\tdocsPaths := []string{\n\t\t\t\"../../web/docs.html\",\n\t\t\t\"../../web/docs.html\",\n\t\t\t\"docs.html\",\n\t\t}\n\n\t\tfor _, docsPath := range docsPaths {\n\t\t\tif _, err := os.Stat(docsPath); err == nil {\n\t\t\t\tlog.Printf(\"āœ… Serving docs from: %s\", docsPath)\n\t\t\t\thttp.ServeFile(w, r, docsPath)\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\t// If no file found, log and serve fallback\n\t\tlog.Println(\"āš ļø docs.html file not found, serving embedded fallback\")\n\t\tfmt.Fprint(w, getEmbeddedDocsHTML())\n\t})\n\n\t// Serve the playground UI\n\tr.HandleFunc(\"/\", func(w http.ResponseWriter, r *http.Request) {\n\t\t// Try multiple possible paths for index.html\n\t\tindexPaths := []string{\n\t\t\t\"../../web/index.html\",\n\t\t\t\"../../web/index.html\",\n\t\t\t\"index.html\",\n\t\t}\n\n\t\tfor _, indexPath := range indexPaths {\n\t\t\tif _, err := os.Stat(indexPath); err == nil {\n\t\t\t\tlog.Printf(\"āœ… Serving index from: %s\", indexPath)\n\t\t\t\thttp.ServeFile(w, r, indexPath)\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\t// If no file found, serve fallback\n\t\tlog.Println(\"āš ļø index.html file not found, serving embedded fallback\")\n\t\tw.Header().Set(\"Content-Type\", \"text/html\")\n\t\tfmt.Fprint(w, getEmbeddedHTML())\n\t})\n}\n\nfunc getEmbeddedHTML() string {\n\treturn `\n\n\n \n \n NeuroGO Playground\n \n\n\n
\n
\n

🧠 NeuroGO Playground

\n

Test your AI command router with natural language prompts

\n
\n \n
\n šŸ“š API Documentation\n šŸ” Health Check\n šŸ›£ļø Routes\n
\n \n
\n
\n

šŸ”— Available Endpoints:

\n

REST API: /api/process, /api/health, /api/routes

\n

WebSocket: /ws

\n

Documentation: /docs (Full API testing interface)

\n
\n \n
\n

šŸ”„ Provider Management

\n

Switch between AI providers or let the system auto-select the best one for each task.

\n
\n \n
\n \n \n
\n \n \n \n
\n
\n

Processing your request...

\n
\n \n
\n

Response:

\n
\n            
\n \n
\n

Example Commands:

\n \n

šŸ”„ Provider Management:

\n
list providers
\n
current provider
\n
use deepseek
\n
use auto
\n \n

🌟 Universal Commands:

\n
translate hello world to Spanish
\n
think about artificial intelligence
\n
summarize the benefits of renewable energy
\n
generate code for a simple calculator
\n \n

šŸŽÆ Provider-Specific Commands:

\n
with deepseek explain quantum computing
\n
with openai write a poem about nature
\n \n

šŸ“‹ System Commands:

\n
help
\n
status
\n
\n
\n
\n\n \n\n`\n}\n\n// getEmbeddedDocsHTML returns a minimal fallback for docs if file doesn't exist\nfunc getEmbeddedDocsHTML() string {\n\treturn `\n\n\n \n \n NeuroGO API Documentation\n \n\n\n
\n

🧠 NeuroGO API Documentation

\n
\n Documentation file not found.
\n The docs.html file is missing. Please ensure web/docs.html exists.\n
\n
\n ← Back to Playground\n Health Check\n API Routes\n
\n

For now, you can use the main playground interface or access the API endpoints directly.

\n
\n\n`\n}\n"}}}}