Files
hack/tools/scripts/llm-key-hunter/results/_cache/content/bennyscash1_aicompautobe.json
T

1 line
75 KiB
JSON
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"repo": "bennyscash1/aicompautobe", "files": {"AiApiCompAuto/Infra/OpenAi/OpenAiService.cs": {"a9d7dccce4e85cac34be49e61537a7a1de37d145": {"t": 1785746193.4100628, "n": 18197, "h": "f6071e1d3cce9a6a", "c": "using Newtonsoft.Json;\nusing Newtonsoft.Json.Linq;\nusing OpenAI.Chat;\nusing System.Text;\nusing System.Text.Json;\n\nnamespace SafeCash.Test.ApiTest.Integration.OpenAi\n{\n public class OpenAiService\n {\n public static string openAiModel = \"gpt-4o-mini\";\n public static string grokAiMode = \"grok-3-mini-fast-latest\";\n #region SystemPrompt\n public enum SystemPromptTypeEnum\n {\n ApiRequest,\n MobileTextInpueRequest,\n MobileSystemPromptMissionTask,\n MobileXyCordinateRequest,\n ImagesCompare,\n AppPackageDetails,\n }\n string mobilePrePrompt = \"You are an automation expert.\\n\" +\n \"Given a mobile XML element dump, return only the XPath of the button or element best matching the target.\\n\\n\" +\n \"Rules:\\n\" +\n \"- Match by content-desc, text, or resource-id.\\n\" +\n \"- If provided, also consider color or visual clues (e.g., \\\"Blue icon\\\") when content-desc, text, or resource-id are insufficient.\\n\" +\n \"- One match → return XPath only. Multiple → return count. No match → return 0.\\n\" +\n \"- Allow partial matches (substring, typo, etc.).\\n\" +\n \"- Recognize semantic and visual terms (e.g., '3 dots', 'plus icon', 'person icon', color descriptions):\\n\" +\n \" • 'plus icon' → content-desc with 'Add'/'Create' or resource-id with 'fab'\\n\" +\n \" • 'search field' → EditText or 'Search'\\n\" +\n \" • 'person icon' → profile/avatar/user\\n\" +\n \" • 'menu button' or '3 dots' → 'More options' or 'Customize and control'\\n\" +\n \" • Color terms (e.g., \\\"Blue icon\\\") → prioritize clickable buttons (ImageButton, Button, ImageView) without text\\n\" +\n \" especially when stated clearly like FAB buttons or visually distinct elements\\n\" +\n \" • Also infer visual roles or icon types from user terms (e.g., 'record icon', 'dialpad icon', '10 dots') even if no exact match in content-desc/text\\n\" +\n \"- Layouts (FrameLayout, LinearLayout) are valid if clickable and labeled.\\n\\n\" +\n \"Examples:\\n\" +\n \"<android.widget.ImageButton content-desc=\\\"5\\\" />\\n\" +\n \"Target: 5\\n\" +\n \"Expected: //android.widget.ImageButton[@content-desc=\\\"5\\\"]\\n\\n\" +\n \"<android.widget.ImageView resource-id=\\\"com.app:id/profile_icon\\\" />\\n\" +\n \"Target: person icon\\n\" +\n \"Expected: //android.widget.ImageView[@resource-id=\\\"com.app:id/profile_icon\\\"]\\n\\n\" +\n \"<android.widget.Button content-desc=\\\"Add city\\\" resource-id=\\\"com.google.android.deskclock:id/fab\\\" />\\n\" +\n \"Target: plus icon\\n\" +\n \"Expected: //android.widget.Button[@content-desc=\\\"Add city\\\"]\\n\\n\" +\n \"<android.widget.ImageButton content-desc=\\\"key pad\\\" resource-id=\\\"com.google.android.dialer:id/dialpad_fab\\\" clickable=\\\"true\\\" />\\n\" +\n \"Target: Blue icon with 10 dots\\n\" +\n \"Expected: //android.widget.ImageButton[@resource-id=\\\"com.google.android.dialer:id/dialpad_fab\\\"]\\n\\n\" +\n \"Important: Return ONLY the raw XPath string (no markdown, no quotes, no formatting).\\n\" +\n \"Now analyze the following:\";\n\n string mobilePrePromptCordinateXy = \"You are an automation expert.\\n\" +\n \"Your task is:\\n\" +\n \"Given:\\n\" +\n \"- A full XML dump of a mobile screen hierarchy.\\n\" +\n \"- The screen width and height.\\n\" +\n \"- A pair of coordinates (X and Y).\\n\\n\" +\n \"Rules:\\n\" +\n \"1. Identify the single UI element in the XML whose bounds ([left,top][right,bottom]) fully contain the given X and Y coordinates.\\n\" +\n \"2. If multiple elements overlap, select the deepest (most nested) element.\\n\" +\n \"3. Return only the XPath expression to locate that specific element.\\n\" +\n \"4. XPath must be precise and use resource-id or content-desc if available.\\n\" +\n \" - Prefer resource-id when present.\\n\" +\n \" - If resource-id is missing, use content-desc.\\n\" +\n \" - If both are missing, use full tag and index path.\\n\" +\n \"5. If no matching element is found, return exactly the number 0 (zero) and nothing else.\\n\" +\n \"6. Never explain, apologize, or add any extra text.\\n\\n\" +\n \"Examples of valid responses:\\n\" +\n \"- //android.widget.ImageButton[@resource-id=\\\"com.example:id/button\\\"]\\n\" +\n \"- //android.widget.TextView[@content-desc=\\\"Submit\\\"]\\n\" +\n \"- 0\\n\\n\" +\n \"Important:\\n\" +\n \"- Screen coordinates are based on the screen size.\\n\" +\n \"- Bounds are given as [left,top][right,bottom] relative to the screen.\\n\" +\n \"- Coordinates on the exact border (equal to left or top but less than right or bottom) are considered inside the bounds.\\n\" +\n \"- Always return only one XPath or 0.\\n\" +\n \"7. Coordinates must be strictly inside the bounds:\\n \" +\n \"- X must be >= left and < right.\\n \" +\n \" - Y must be >= top and < bottom.\\n \" +\n \"- No partial matches are allowed.\\n \" +\n \"- Ignore elements where X and Y are not fully contained inside bounds.\\n\";\n\n string aiSystemPromptMissionTask =\n \"You are a smart navigation agent inside a mobile app.\\n\\n\" +\n \"Your task is to analyze the given Android XML UI hierarchy and guide the user step-by-step to complete their goal.\\n\\n\" +\n \"Input:\\n\" +\n \"1. xmlHierarchy – the current screen's XML.\\n\" +\n \"2. userGoal – a free-text description of what the user wants to do (e.g. 'Search for Hello World').\\n\\n\" +\n \"Process:\\n\" +\n \"- Parse the XML and check if the goal is already complete.\\n\" +\n \"- If the user goal is fully completed (all required inputs/actions are done), return:\\n\" +\n \" { \\\"type\\\": 3 }\\n\" +\n \"- If not, find the next visible UI element that moves the user closer to the goal.\\n\" +\n \"- Prefer buttons like 'Next', 'OK', or 'Continue' unless the goal says otherwise.\\n\" +\n \"- Only suggest actions that match real elements in the XML (no guesses).\\n\" +\n \"- Use exact XPaths based on class, text, content-desc, or resource-id.\\n\" +\n \"- Return only one step at a time – button click or input.\\n\" +\n \"- If stuck, return: { \\\"type\\\": 0 }\\n\\n\" +\n\n \"Output format:\\n\" +\n \"- Click: { \\\"type\\\": 1, \\\"xpath\\\": \\\"...\\\" }\\n\" +\n \"- Input: { \\\"type\\\": 2, \\\"xpath\\\": \\\"...\\\", \\\"value\\\": \\\"...\\\" }\\n\" +\n \"- Done: { \\\"type\\\": 3 }\\n\" +\n \"- No action: { \\\"type\\\": 0 }\\n\\n\" +\n\n \"Important:\\n\" +\n \"- If all required steps are marked as already clicked (via provided locators), return { \\\"type\\\": 3 } and do not continue.\\n\" +\n \"- Never return commentary or code blocks – only a valid JSON object.\\n\" +\n \"- Do not return suggestions for extra UI elements if not part of the userGoal.\\n\";\n\n\n string getAppPackageDetailsSystemPrompt =\n @\"You are an Android expert.\n Your task is to extract the appPackage and appActivity for a specific app name (e.g., 'camera' or 'contacts').\n\n You will receive:\n - A list of installed app packages\n - A target app name\n\n ---\n\n Your job is to:\n 1. Find the app package that best matches the target app name (case-insensitive, partial match is allowed).\n 2. Return a valid JSON in this exact format:\n {\n \"\"appPackage\"\": \"\"<appPackage>\"\",\n \"\"appActivity\"\": \"\"<appActivity>\"\"\n }\n\n ---\n\n Rules:\n - Respond with JSON only. No explanation, no extra text.\n - If multiple packages might match, return the best/most likely one.\n - If no match found, still return the JSON with empty values:\n {\n \"\"appPackage\"\": \"\"\"\",\n \"\"appActivity\"\": \"\"\"\"\n }\n \";\n\n public string GetSystemPrompt(SystemPromptTypeEnum aiRequest)\n {\n string prePrompt;\n switch (aiRequest)\n {\n case SystemPromptTypeEnum.MobileTextInpueRequest:\n prePrompt = mobilePrePrompt;\n break;\n case SystemPromptTypeEnum.MobileSystemPromptMissionTask:\n prePrompt = aiSystemPromptMissionTask;\n break;\n case SystemPromptTypeEnum.MobileXyCordinateRequest:\n prePrompt = mobilePrePromptCordinateXy;\n break;\n case SystemPromptTypeEnum.AppPackageDetails:\n prePrompt = getAppPackageDetailsSystemPrompt;\n break;\n\n default:\n prePrompt = \"You are an AI assistant.\"; // Default fallback\n break;\n }\n return prePrompt;\n }\n #endregion\n\n #region OpenAiServiceRequest\n\n public async Task<string> OpenAiServiceRequest(string userPrompts, SystemPromptTypeEnum systemPrompt)\n {\n string model = openAiModel;\n string prePrompt = GetSystemPrompt(systemPrompt);\n\n string apiKey = Environment.GetEnvironmentVariable(\"OPENAI_API_KEY\") ?? throw new InvalidOperationException(\"API key is missing from environment variables.\");\n string apiResponce = \"An error occurred or no response was returned.\";\n //string combinedPrompt = $\"{prePrompt}\\n\\n{userPrompts}\";\n try\n {\n ChatClient client = new ChatClient(model, apiKey);\n\n var openAiRequest = new\n {\n model = model,\n messages = new[]\n {\n new { role = \"system\", content = prePrompt },\n new { role = \"user\", content = userPrompts }\n }\n };\n string jsonBody = JsonConvert.SerializeObject(openAiRequest, Formatting.Indented);\n\n UserChatMessage message = new UserChatMessage(jsonBody);\n ChatCompletion completion = await client.CompleteChatAsync(message);\n\n if (completion?.Content != null && completion.Content.Count > 0)\n {\n apiResponce = completion.Content[0].Text;\n\n }\n else\n {\n apiResponce = \"No valid content found in the response.\";\n }\n Console.WriteLine(\"after ai\");\n\n }\n catch (Exception ex)\n {\n Console.WriteLine(ex.Message);\n }\n\n return apiResponce;\n }\n #endregion\n\n #region Grok ai request\n public async Task<string> GrokRequestService(string userMessage, SystemPromptTypeEnum aiRequest)\n {\n string grokUrl = \"https://api.x.ai/v1/chat/completions\";\n string apiGrokKey = Environment.GetEnvironmentVariable(\"GROK_API_KEY\") ?? throw new InvalidOperationException(\"API key is missing from environment variables.\");\n\n using (HttpClient client = new HttpClient())\n {\n string aiPrePromptType = GetSystemPrompt(aiRequest);\n\n client.DefaultRequestHeaders.Add(\"Authorization\", $\"Bearer {apiGrokKey}\");\n\n var requestBody = new\n {\n messages = new[]\n {\n new { role = \"system\", content = aiPrePromptType },\n new { role = \"user\", content = userMessage }\n },\n model = grokAiMode,\n stream = false,\n temperature = 0\n };\n\n var jsonContent = new StringContent(JsonConvert.SerializeObject(requestBody), Encoding.UTF8, \"application/json\");\n HttpResponseMessage response = await client.PostAsync(grokUrl, jsonContent);\n\n if (response.IsSuccessStatusCode)\n {\n string jsonResponse = await response.Content.ReadAsStringAsync();\n\n // ✅ Extract only the \"content\" field from the response\n using JsonDocument doc = JsonDocument.Parse(jsonResponse);\n\n if (doc.RootElement.TryGetProperty(\"choices\", out JsonElement choicesArray) &&\n choicesArray.GetArrayLength() > 0 &&\n choicesArray[0].TryGetProperty(\"message\", out JsonElement message) &&\n message.TryGetProperty(\"content\", out JsonElement contentElement))\n {\n return contentElement.GetString() ?? \"No content available.\";\n }\n\n return \"Invalid response format.\";\n }\n else\n {\n return $\"Error: {response.StatusCode} - {response.ReasonPhrase}\";\n }\n }\n }\n #endregion\n\n #region Deep seek ai request\n private readonly HttpClient _httpClient = new HttpClient();\n\n public async Task<string> DeepSeekResponceAi(string userPrompts, SystemPromptTypeEnum aiRequest)\n {\n string apiUrl = \"https://api.deepseek.com/chat/completions\"; // Replace with actual API URL\n string bearerToken = \"sk-5706d7050b8c4bddb967ba236538d89d\"; // Replace with actual token\n string prePrompt = GetSystemPrompt(aiRequest);\n var requestBody = new\n {\n model = \"deepseek-chat\",\n messages = new[]\n {\n new { role = \"system\", content = prePrompt },\n new { role = \"user\", content = userPrompts }\n\n },\n stream = false\n };\n\n string jsonRequest = System.Text.Json.JsonSerializer.Serialize(requestBody);\n var content = new StringContent(jsonRequest, Encoding.UTF8, \"application/json\"); // ✅ \"Content-Type\" set correctly here\n\n var request = new HttpRequestMessage(HttpMethod.Post, apiUrl)\n {\n Content = content\n };\n\n request.Headers.Add(\"Authorization\", $\"Bearer {bearerToken}\"); // ✅ Correct place for Authorization\n // No need to add \"Content-Type\" again here\n\n HttpResponseMessage response = await _httpClient.SendAsync(request);\n string jsonResponse = await response.Content.ReadAsStringAsync();\n\n using JsonDocument doc = JsonDocument.Parse(jsonResponse);\n\n string? contentResponce = doc.RootElement\n .GetProperty(\"choices\")[0]\n .GetProperty(\"message\")\n .GetProperty(\"content\")\n .GetString();\n\n return contentResponce;\n }\n #endregion\n\n #region Claude ais request\n\n public async Task<string> GetClaudeResponse(string userPrompts, SystemPromptTypeEnum aiRequest,\n string apiKey = \"\")\n {\n string prePrompt = GetSystemPrompt(aiRequest);\n if (string.IsNullOrEmpty(apiKey))\n {\n //apiKey = Environment.GetEnvironmentVariable(\"CLAUDE_API_KEY\") ?? throw new InvalidOperationException(\"API key is missing from environment variables.\");\n Console.WriteLine(\"Anthropic Api key is: \" +apiKey);\n throw new InvalidOperationException(\"API key is missing. Please provide a valid API key for Claude AI.\");\n }\n string url = \"https://api.anthropic.com/v1/messages\";\n string claudeModel = \"claude-3-5-sonnet-20240620\";\n var requestBody = new\n {\n model = \"claude-3-5-haiku-20241022\",\n max_tokens = 1024,\n system = prePrompt,\n messages = new[]\n {\n new { role = \"user\", content = userPrompts }\n }\n };\n\n var json = JsonConvert.SerializeObject(requestBody);\n\n // Use the retry method with fresh request creation\n var response = await SendWithRetries(json, url, apiKey);\n\n string responseContent = await response.Content.ReadAsStringAsync();\n\n if (!response.IsSuccessStatusCode)\n {\n throw new InvalidOperationException($\"API key '{apiKey}' is incorrect (Anthropic return http status {response.StatusCode}, {responseContent}). \" +\n $\"Please provide a valid API key for Claude AI.\");\n //return $\"Error: {response.StatusCode}\\n{responseContent}\";\n }\n\n JObject parsed = JObject.Parse(responseContent);\n var text = parsed[\"content\"]?[0]?[\"text\"]?.ToString();\n\n return text ?? \"No text content found.\";\n }\n\n private async Task<HttpResponseMessage> SendWithRetries(string json, string url, string apiKey, int maxRetries = 3)\n {\n for (int attempt = 0; attempt < maxRetries; attempt++)\n {\n var request = new HttpRequestMessage(HttpMethod.Post, url);\n request.Headers.Add(\"x-api-key\", apiKey);\n request.Headers.Add(\"anthropic-version\", \"2023-06-01\");\n request.Content = new StringContent(json, Encoding.UTF8, \"application/json\");\n\n var response = await _httpClient.SendAsync(request);\n\n if ((int)response.StatusCode != 529)\n return response;\n\n int waitTime = (int)Math.Pow(2, attempt + 1) * 1000; // 2s, 4s, 8s\n await Task.Delay(waitTime);\n }\n\n throw new Exception(\"Claude API is overloaded (529) after multiple retries.\");\n }\n\n #endregion\n }\n public enum AiServicesList\n {\n OpenAi,\n Grok,\n Claude,\n DeepSeek\n }\n}\n"}, "c74e9e020b8e59e37020665bd4774493551757e7": {"t": 1785760510.576776, "n": 18197, "h": "f6071e1d3cce9a6a", "c": "using Newtonsoft.Json;\nusing Newtonsoft.Json.Linq;\nusing OpenAI.Chat;\nusing System.Text;\nusing System.Text.Json;\n\nnamespace SafeCash.Test.ApiTest.Integration.OpenAi\n{\n public class OpenAiService\n {\n public static string openAiModel = \"gpt-4o-mini\";\n public static string grokAiMode = \"grok-3-mini-fast-latest\";\n #region SystemPrompt\n public enum SystemPromptTypeEnum\n {\n ApiRequest,\n MobileTextInpueRequest,\n MobileSystemPromptMissionTask,\n MobileXyCordinateRequest,\n ImagesCompare,\n AppPackageDetails,\n }\n string mobilePrePrompt = \"You are an automation expert.\\n\" +\n \"Given a mobile XML element dump, return only the XPath of the button or element best matching the target.\\n\\n\" +\n \"Rules:\\n\" +\n \"- Match by content-desc, text, or resource-id.\\n\" +\n \"- If provided, also consider color or visual clues (e.g., \\\"Blue icon\\\") when content-desc, text, or resource-id are insufficient.\\n\" +\n \"- One match → return XPath only. Multiple → return count. No match → return 0.\\n\" +\n \"- Allow partial matches (substring, typo, etc.).\\n\" +\n \"- Recognize semantic and visual terms (e.g., '3 dots', 'plus icon', 'person icon', color descriptions):\\n\" +\n \" • 'plus icon' → content-desc with 'Add'/'Create' or resource-id with 'fab'\\n\" +\n \" • 'search field' → EditText or 'Search'\\n\" +\n \" • 'person icon' → profile/avatar/user\\n\" +\n \" • 'menu button' or '3 dots' → 'More options' or 'Customize and control'\\n\" +\n \" • Color terms (e.g., \\\"Blue icon\\\") → prioritize clickable buttons (ImageButton, Button, ImageView) without text\\n\" +\n \" especially when stated clearly like FAB buttons or visually distinct elements\\n\" +\n \" • Also infer visual roles or icon types from user terms (e.g., 'record icon', 'dialpad icon', '10 dots') even if no exact match in content-desc/text\\n\" +\n \"- Layouts (FrameLayout, LinearLayout) are valid if clickable and labeled.\\n\\n\" +\n \"Examples:\\n\" +\n \"<android.widget.ImageButton content-desc=\\\"5\\\" />\\n\" +\n \"Target: 5\\n\" +\n \"Expected: //android.widget.ImageButton[@content-desc=\\\"5\\\"]\\n\\n\" +\n \"<android.widget.ImageView resource-id=\\\"com.app:id/profile_icon\\\" />\\n\" +\n \"Target: person icon\\n\" +\n \"Expected: //android.widget.ImageView[@resource-id=\\\"com.app:id/profile_icon\\\"]\\n\\n\" +\n \"<android.widget.Button content-desc=\\\"Add city\\\" resource-id=\\\"com.google.android.deskclock:id/fab\\\" />\\n\" +\n \"Target: plus icon\\n\" +\n \"Expected: //android.widget.Button[@content-desc=\\\"Add city\\\"]\\n\\n\" +\n \"<android.widget.ImageButton content-desc=\\\"key pad\\\" resource-id=\\\"com.google.android.dialer:id/dialpad_fab\\\" clickable=\\\"true\\\" />\\n\" +\n \"Target: Blue icon with 10 dots\\n\" +\n \"Expected: //android.widget.ImageButton[@resource-id=\\\"com.google.android.dialer:id/dialpad_fab\\\"]\\n\\n\" +\n \"Important: Return ONLY the raw XPath string (no markdown, no quotes, no formatting).\\n\" +\n \"Now analyze the following:\";\n\n string mobilePrePromptCordinateXy = \"You are an automation expert.\\n\" +\n \"Your task is:\\n\" +\n \"Given:\\n\" +\n \"- A full XML dump of a mobile screen hierarchy.\\n\" +\n \"- The screen width and height.\\n\" +\n \"- A pair of coordinates (X and Y).\\n\\n\" +\n \"Rules:\\n\" +\n \"1. Identify the single UI element in the XML whose bounds ([left,top][right,bottom]) fully contain the given X and Y coordinates.\\n\" +\n \"2. If multiple elements overlap, select the deepest (most nested) element.\\n\" +\n \"3. Return only the XPath expression to locate that specific element.\\n\" +\n \"4. XPath must be precise and use resource-id or content-desc if available.\\n\" +\n \" - Prefer resource-id when present.\\n\" +\n \" - If resource-id is missing, use content-desc.\\n\" +\n \" - If both are missing, use full tag and index path.\\n\" +\n \"5. If no matching element is found, return exactly the number 0 (zero) and nothing else.\\n\" +\n \"6. Never explain, apologize, or add any extra text.\\n\\n\" +\n \"Examples of valid responses:\\n\" +\n \"- //android.widget.ImageButton[@resource-id=\\\"com.example:id/button\\\"]\\n\" +\n \"- //android.widget.TextView[@content-desc=\\\"Submit\\\"]\\n\" +\n \"- 0\\n\\n\" +\n \"Important:\\n\" +\n \"- Screen coordinates are based on the screen size.\\n\" +\n \"- Bounds are given as [left,top][right,bottom] relative to the screen.\\n\" +\n \"- Coordinates on the exact border (equal to left or top but less than right or bottom) are considered inside the bounds.\\n\" +\n \"- Always return only one XPath or 0.\\n\" +\n \"7. Coordinates must be strictly inside the bounds:\\n \" +\n \"- X must be >= left and < right.\\n \" +\n \" - Y must be >= top and < bottom.\\n \" +\n \"- No partial matches are allowed.\\n \" +\n \"- Ignore elements where X and Y are not fully contained inside bounds.\\n\";\n\n string aiSystemPromptMissionTask =\n \"You are a smart navigation agent inside a mobile app.\\n\\n\" +\n \"Your task is to analyze the given Android XML UI hierarchy and guide the user step-by-step to complete their goal.\\n\\n\" +\n \"Input:\\n\" +\n \"1. xmlHierarchy – the current screen's XML.\\n\" +\n \"2. userGoal – a free-text description of what the user wants to do (e.g. 'Search for Hello World').\\n\\n\" +\n \"Process:\\n\" +\n \"- Parse the XML and check if the goal is already complete.\\n\" +\n \"- If the user goal is fully completed (all required inputs/actions are done), return:\\n\" +\n \" { \\\"type\\\": 3 }\\n\" +\n \"- If not, find the next visible UI element that moves the user closer to the goal.\\n\" +\n \"- Prefer buttons like 'Next', 'OK', or 'Continue' unless the goal says otherwise.\\n\" +\n \"- Only suggest actions that match real elements in the XML (no guesses).\\n\" +\n \"- Use exact XPaths based on class, text, content-desc, or resource-id.\\n\" +\n \"- Return only one step at a time – button click or input.\\n\" +\n \"- If stuck, return: { \\\"type\\\": 0 }\\n\\n\" +\n\n \"Output format:\\n\" +\n \"- Click: { \\\"type\\\": 1, \\\"xpath\\\": \\\"...\\\" }\\n\" +\n \"- Input: { \\\"type\\\": 2, \\\"xpath\\\": \\\"...\\\", \\\"value\\\": \\\"...\\\" }\\n\" +\n \"- Done: { \\\"type\\\": 3 }\\n\" +\n \"- No action: { \\\"type\\\": 0 }\\n\\n\" +\n\n \"Important:\\n\" +\n \"- If all required steps are marked as already clicked (via provided locators), return { \\\"type\\\": 3 } and do not continue.\\n\" +\n \"- Never return commentary or code blocks – only a valid JSON object.\\n\" +\n \"- Do not return suggestions for extra UI elements if not part of the userGoal.\\n\";\n\n\n string getAppPackageDetailsSystemPrompt =\n @\"You are an Android expert.\n Your task is to extract the appPackage and appActivity for a specific app name (e.g., 'camera' or 'contacts').\n\n You will receive:\n - A list of installed app packages\n - A target app name\n\n ---\n\n Your job is to:\n 1. Find the app package that best matches the target app name (case-insensitive, partial match is allowed).\n 2. Return a valid JSON in this exact format:\n {\n \"\"appPackage\"\": \"\"<appPackage>\"\",\n \"\"appActivity\"\": \"\"<appActivity>\"\"\n }\n\n ---\n\n Rules:\n - Respond with JSON only. No explanation, no extra text.\n - If multiple packages might match, return the best/most likely one.\n - If no match found, still return the JSON with empty values:\n {\n \"\"appPackage\"\": \"\"\"\",\n \"\"appActivity\"\": \"\"\"\"\n }\n \";\n\n public string GetSystemPrompt(SystemPromptTypeEnum aiRequest)\n {\n string prePrompt;\n switch (aiRequest)\n {\n case SystemPromptTypeEnum.MobileTextInpueRequest:\n prePrompt = mobilePrePrompt;\n break;\n case SystemPromptTypeEnum.MobileSystemPromptMissionTask:\n prePrompt = aiSystemPromptMissionTask;\n break;\n case SystemPromptTypeEnum.MobileXyCordinateRequest:\n prePrompt = mobilePrePromptCordinateXy;\n break;\n case SystemPromptTypeEnum.AppPackageDetails:\n prePrompt = getAppPackageDetailsSystemPrompt;\n break;\n\n default:\n prePrompt = \"You are an AI assistant.\"; // Default fallback\n break;\n }\n return prePrompt;\n }\n #endregion\n\n #region OpenAiServiceRequest\n\n public async Task<string> OpenAiServiceRequest(string userPrompts, SystemPromptTypeEnum systemPrompt)\n {\n string model = openAiModel;\n string prePrompt = GetSystemPrompt(systemPrompt);\n\n string apiKey = Environment.GetEnvironmentVariable(\"OPENAI_API_KEY\") ?? throw new InvalidOperationException(\"API key is missing from environment variables.\");\n string apiResponce = \"An error occurred or no response was returned.\";\n //string combinedPrompt = $\"{prePrompt}\\n\\n{userPrompts}\";\n try\n {\n ChatClient client = new ChatClient(model, apiKey);\n\n var openAiRequest = new\n {\n model = model,\n messages = new[]\n {\n new { role = \"system\", content = prePrompt },\n new { role = \"user\", content = userPrompts }\n }\n };\n string jsonBody = JsonConvert.SerializeObject(openAiRequest, Formatting.Indented);\n\n UserChatMessage message = new UserChatMessage(jsonBody);\n ChatCompletion completion = await client.CompleteChatAsync(message);\n\n if (completion?.Content != null && completion.Content.Count > 0)\n {\n apiResponce = completion.Content[0].Text;\n\n }\n else\n {\n apiResponce = \"No valid content found in the response.\";\n }\n Console.WriteLine(\"after ai\");\n\n }\n catch (Exception ex)\n {\n Console.WriteLine(ex.Message);\n }\n\n return apiResponce;\n }\n #endregion\n\n #region Grok ai request\n public async Task<string> GrokRequestService(string userMessage, SystemPromptTypeEnum aiRequest)\n {\n string grokUrl = \"https://api.x.ai/v1/chat/completions\";\n string apiGrokKey = Environment.GetEnvironmentVariable(\"GROK_API_KEY\") ?? throw new InvalidOperationException(\"API key is missing from environment variables.\");\n\n using (HttpClient client = new HttpClient())\n {\n string aiPrePromptType = GetSystemPrompt(aiRequest);\n\n client.DefaultRequestHeaders.Add(\"Authorization\", $\"Bearer {apiGrokKey}\");\n\n var requestBody = new\n {\n messages = new[]\n {\n new { role = \"system\", content = aiPrePromptType },\n new { role = \"user\", content = userMessage }\n },\n model = grokAiMode,\n stream = false,\n temperature = 0\n };\n\n var jsonContent = new StringContent(JsonConvert.SerializeObject(requestBody), Encoding.UTF8, \"application/json\");\n HttpResponseMessage response = await client.PostAsync(grokUrl, jsonContent);\n\n if (response.IsSuccessStatusCode)\n {\n string jsonResponse = await response.Content.ReadAsStringAsync();\n\n // ✅ Extract only the \"content\" field from the response\n using JsonDocument doc = JsonDocument.Parse(jsonResponse);\n\n if (doc.RootElement.TryGetProperty(\"choices\", out JsonElement choicesArray) &&\n choicesArray.GetArrayLength() > 0 &&\n choicesArray[0].TryGetProperty(\"message\", out JsonElement message) &&\n message.TryGetProperty(\"content\", out JsonElement contentElement))\n {\n return contentElement.GetString() ?? \"No content available.\";\n }\n\n return \"Invalid response format.\";\n }\n else\n {\n return $\"Error: {response.StatusCode} - {response.ReasonPhrase}\";\n }\n }\n }\n #endregion\n\n #region Deep seek ai request\n private readonly HttpClient _httpClient = new HttpClient();\n\n public async Task<string> DeepSeekResponceAi(string userPrompts, SystemPromptTypeEnum aiRequest)\n {\n string apiUrl = \"https://api.deepseek.com/chat/completions\"; // Replace with actual API URL\n string bearerToken = \"sk-5706d7050b8c4bddb967ba236538d89d\"; // Replace with actual token\n string prePrompt = GetSystemPrompt(aiRequest);\n var requestBody = new\n {\n model = \"deepseek-chat\",\n messages = new[]\n {\n new { role = \"system\", content = prePrompt },\n new { role = \"user\", content = userPrompts }\n\n },\n stream = false\n };\n\n string jsonRequest = System.Text.Json.JsonSerializer.Serialize(requestBody);\n var content = new StringContent(jsonRequest, Encoding.UTF8, \"application/json\"); // ✅ \"Content-Type\" set correctly here\n\n var request = new HttpRequestMessage(HttpMethod.Post, apiUrl)\n {\n Content = content\n };\n\n request.Headers.Add(\"Authorization\", $\"Bearer {bearerToken}\"); // ✅ Correct place for Authorization\n // No need to add \"Content-Type\" again here\n\n HttpResponseMessage response = await _httpClient.SendAsync(request);\n string jsonResponse = await response.Content.ReadAsStringAsync();\n\n using JsonDocument doc = JsonDocument.Parse(jsonResponse);\n\n string? contentResponce = doc.RootElement\n .GetProperty(\"choices\")[0]\n .GetProperty(\"message\")\n .GetProperty(\"content\")\n .GetString();\n\n return contentResponce;\n }\n #endregion\n\n #region Claude ais request\n\n public async Task<string> GetClaudeResponse(string userPrompts, SystemPromptTypeEnum aiRequest,\n string apiKey = \"\")\n {\n string prePrompt = GetSystemPrompt(aiRequest);\n if (string.IsNullOrEmpty(apiKey))\n {\n //apiKey = Environment.GetEnvironmentVariable(\"CLAUDE_API_KEY\") ?? throw new InvalidOperationException(\"API key is missing from environment variables.\");\n Console.WriteLine(\"Anthropic Api key is: \" +apiKey);\n throw new InvalidOperationException(\"API key is missing. Please provide a valid API key for Claude AI.\");\n }\n string url = \"https://api.anthropic.com/v1/messages\";\n string claudeModel = \"claude-3-5-sonnet-20240620\";\n var requestBody = new\n {\n model = \"claude-3-5-haiku-20241022\",\n max_tokens = 1024,\n system = prePrompt,\n messages = new[]\n {\n new { role = \"user\", content = userPrompts }\n }\n };\n\n var json = JsonConvert.SerializeObject(requestBody);\n\n // Use the retry method with fresh request creation\n var response = await SendWithRetries(json, url, apiKey);\n\n string responseContent = await response.Content.ReadAsStringAsync();\n\n if (!response.IsSuccessStatusCode)\n {\n throw new InvalidOperationException($\"API key '{apiKey}' is incorrect (Anthropic return http status {response.StatusCode}, {responseContent}). \" +\n $\"Please provide a valid API key for Claude AI.\");\n //return $\"Error: {response.StatusCode}\\n{responseContent}\";\n }\n\n JObject parsed = JObject.Parse(responseContent);\n var text = parsed[\"content\"]?[0]?[\"text\"]?.ToString();\n\n return text ?? \"No text content found.\";\n }\n\n private async Task<HttpResponseMessage> SendWithRetries(string json, string url, string apiKey, int maxRetries = 3)\n {\n for (int attempt = 0; attempt < maxRetries; attempt++)\n {\n var request = new HttpRequestMessage(HttpMethod.Post, url);\n request.Headers.Add(\"x-api-key\", apiKey);\n request.Headers.Add(\"anthropic-version\", \"2023-06-01\");\n request.Content = new StringContent(json, Encoding.UTF8, \"application/json\");\n\n var response = await _httpClient.SendAsync(request);\n\n if ((int)response.StatusCode != 529)\n return response;\n\n int waitTime = (int)Math.Pow(2, attempt + 1) * 1000; // 2s, 4s, 8s\n await Task.Delay(waitTime);\n }\n\n throw new Exception(\"Claude API is overloaded (529) after multiple retries.\");\n }\n\n #endregion\n }\n public enum AiServicesList\n {\n OpenAi,\n Grok,\n Claude,\n DeepSeek\n }\n}\n"}, "a78b976326cb913f156714e6a75568ade0ba8d86": {"t": 1785760511.9459245, "n": 18186, "h": "65f389cbdb729a52", "c": "using Newtonsoft.Json;\nusing Newtonsoft.Json.Linq;\nusing OpenAI.Chat;\nusing System.Text;\nusing System.Text.Json;\n\nnamespace SafeCash.Test.ApiTest.Integration.OpenAi\n{\n public class OpenAiService\n {\n public static string openAiModel = \"gpt-4o-mini\";\n public static string grokAiMode = \"grok-3-mini-fast-latest\";\n #region SystemPrompt\n public enum SystemPromptTypeEnum\n {\n ApiRequest,\n MobileTextInpueRequest,\n MobileSystemPromptMissionTask,\n MobileXyCordinateRequest,\n ImagesCompare,\n AppPackageDetails,\n }\n string mobilePrePrompt = \"You are an automation expert.\\n\" +\n \"Given a mobile XML element dump, return only the XPath of the button or element best matching the target.\\n\\n\" +\n \"Rules:\\n\" +\n \"- Match by content-desc, text, or resource-id.\\n\" +\n \"- If provided, also consider color or visual clues (e.g., \\\"Blue icon\\\") when content-desc, text, or resource-id are insufficient.\\n\" +\n \"- One match → return XPath only. Multiple → return count. No match → return 0.\\n\" +\n \"- Allow partial matches (substring, typo, etc.).\\n\" +\n \"- Recognize semantic and visual terms (e.g., '3 dots', 'plus icon', 'person icon', color descriptions):\\n\" +\n \" • 'plus icon' → content-desc with 'Add'/'Create' or resource-id with 'fab'\\n\" +\n \" • 'search field' → EditText or 'Search'\\n\" +\n \" • 'person icon' → profile/avatar/user\\n\" +\n \" • 'menu button' or '3 dots' → 'More options' or 'Customize and control'\\n\" +\n \" • Color terms (e.g., \\\"Blue icon\\\") → prioritize clickable buttons (ImageButton, Button, ImageView) without text\\n\" +\n \" especially when stated clearly like FAB buttons or visually distinct elements\\n\" +\n \" • Also infer visual roles or icon types from user terms (e.g., 'record icon', 'dialpad icon', '10 dots') even if no exact match in content-desc/text\\n\" +\n \"- Layouts (FrameLayout, LinearLayout) are valid if clickable and labeled.\\n\\n\" +\n \"Examples:\\n\" +\n \"<android.widget.ImageButton content-desc=\\\"5\\\" />\\n\" +\n \"Target: 5\\n\" +\n \"Expected: //android.widget.ImageButton[@content-desc=\\\"5\\\"]\\n\\n\" +\n \"<android.widget.ImageView resource-id=\\\"com.app:id/profile_icon\\\" />\\n\" +\n \"Target: person icon\\n\" +\n \"Expected: //android.widget.ImageView[@resource-id=\\\"com.app:id/profile_icon\\\"]\\n\\n\" +\n \"<android.widget.Button content-desc=\\\"Add city\\\" resource-id=\\\"com.google.android.deskclock:id/fab\\\" />\\n\" +\n \"Target: plus icon\\n\" +\n \"Expected: //android.widget.Button[@content-desc=\\\"Add city\\\"]\\n\\n\" +\n \"<android.widget.ImageButton content-desc=\\\"key pad\\\" resource-id=\\\"com.google.android.dialer:id/dialpad_fab\\\" clickable=\\\"true\\\" />\\n\" +\n \"Target: Blue icon with 10 dots\\n\" +\n \"Expected: //android.widget.ImageButton[@resource-id=\\\"com.google.android.dialer:id/dialpad_fab\\\"]\\n\\n\" +\n \"Important: Return ONLY the raw XPath string (no markdown, no quotes, no formatting).\\n\" +\n \"Now analyze the following:\";\n\n string mobilePrePromptCordinateXy = \"You are an automation expert.\\n\" +\n \"Your task is:\\n\" +\n \"Given:\\n\" +\n \"- A full XML dump of a mobile screen hierarchy.\\n\" +\n \"- The screen width and height.\\n\" +\n \"- A pair of coordinates (X and Y).\\n\\n\" +\n \"Rules:\\n\" +\n \"1. Identify the single UI element in the XML whose bounds ([left,top][right,bottom]) fully contain the given X and Y coordinates.\\n\" +\n \"2. If multiple elements overlap, select the deepest (most nested) element.\\n\" +\n \"3. Return only the XPath expression to locate that specific element.\\n\" +\n \"4. XPath must be precise and use resource-id or content-desc if available.\\n\" +\n \" - Prefer resource-id when present.\\n\" +\n \" - If resource-id is missing, use content-desc.\\n\" +\n \" - If both are missing, use full tag and index path.\\n\" +\n \"5. If no matching element is found, return exactly the number 0 (zero) and nothing else.\\n\" +\n \"6. Never explain, apologize, or add any extra text.\\n\\n\" +\n \"Examples of valid responses:\\n\" +\n \"- //android.widget.ImageButton[@resource-id=\\\"com.example:id/button\\\"]\\n\" +\n \"- //android.widget.TextView[@content-desc=\\\"Submit\\\"]\\n\" +\n \"- 0\\n\\n\" +\n \"Important:\\n\" +\n \"- Screen coordinates are based on the screen size.\\n\" +\n \"- Bounds are given as [left,top][right,bottom] relative to the screen.\\n\" +\n \"- Coordinates on the exact border (equal to left or top but less than right or bottom) are considered inside the bounds.\\n\" +\n \"- Always return only one XPath or 0.\\n\" +\n \"7. Coordinates must be strictly inside the bounds:\\n \" +\n \"- X must be >= left and < right.\\n \" +\n \" - Y must be >= top and < bottom.\\n \" +\n \"- No partial matches are allowed.\\n \" +\n \"- Ignore elements where X and Y are not fully contained inside bounds.\\n\";\n\n string aiSystemPromptMissionTask =\n \"You are a smart navigation agent inside a mobile app.\\n\\n\" +\n \"Your task is to analyze the given Android XML UI hierarchy and guide the user step-by-step to complete their goal.\\n\\n\" +\n \"Input:\\n\" +\n \"1. xmlHierarchy – the current screen's XML.\\n\" +\n \"2. userGoal – a free-text description of what the user wants to do (e.g. 'Search for Hello World').\\n\\n\" +\n \"Process:\\n\" +\n \"- Parse the XML and check if the goal is already complete.\\n\" +\n \"- If the user goal is fully completed (all required inputs/actions are done), return:\\n\" +\n \" { \\\"type\\\": 3 }\\n\" +\n \"- If not, find the next visible UI element that moves the user closer to the goal.\\n\" +\n \"- Prefer buttons like 'Next', 'OK', or 'Continue' unless the goal says otherwise.\\n\" +\n \"- Only suggest actions that match real elements in the XML (no guesses).\\n\" +\n \"- Use exact XPaths based on class, text, content-desc, or resource-id.\\n\" +\n \"- Return only one step at a time – button click or input.\\n\" +\n \"- If stuck, return: { \\\"type\\\": 0 }\\n\\n\" +\n\n \"Output format:\\n\" +\n \"- Click: { \\\"type\\\": 1, \\\"xpath\\\": \\\"...\\\" }\\n\" +\n \"- Input: { \\\"type\\\": 2, \\\"xpath\\\": \\\"...\\\", \\\"value\\\": \\\"...\\\" }\\n\" +\n \"- Done: { \\\"type\\\": 3 }\\n\" +\n \"- No action: { \\\"type\\\": 0 }\\n\\n\" +\n\n \"Important:\\n\" +\n \"- If all required steps are marked as already clicked (via provided locators), return { \\\"type\\\": 3 } and do not continue.\\n\" +\n \"- Never return commentary or code blocks – only a valid JSON object.\\n\" +\n \"- Do not return suggestions for extra UI elements if not part of the userGoal.\\n\";\n\n\n string getAppPackageDetailsSystemPrompt =\n @\"You are an Android expert.\n Your task is to extract the appPackage and appActivity for a specific app name (e.g., 'camera' or 'contacts').\n\n You will receive:\n - A list of installed app packages\n - A target app name\n\n ---\n\n Your job is to:\n 1. Find the app package that best matches the target app name (case-insensitive, partial match is allowed).\n 2. Return a valid JSON in this exact format:\n {\n \"\"appPackage\"\": \"\"<appPackage>\"\",\n \"\"appActivity\"\": \"\"<appActivity>\"\"\n }\n\n ---\n\n Rules:\n - Respond with JSON only. No explanation, no extra text.\n - If multiple packages might match, return the best/most likely one.\n - If no match found, still return the JSON with empty values:\n {\n \"\"appPackage\"\": \"\"\"\",\n \"\"appActivity\"\": \"\"\"\"\n }\n \";\n\n public string GetSystemPrompt(SystemPromptTypeEnum aiRequest)\n {\n string prePrompt;\n switch (aiRequest)\n {\n case SystemPromptTypeEnum.MobileTextInpueRequest:\n prePrompt = mobilePrePrompt;\n break;\n case SystemPromptTypeEnum.MobileSystemPromptMissionTask:\n prePrompt = aiSystemPromptMissionTask;\n break;\n case SystemPromptTypeEnum.MobileXyCordinateRequest:\n prePrompt = mobilePrePromptCordinateXy;\n break;\n case SystemPromptTypeEnum.AppPackageDetails:\n prePrompt = getAppPackageDetailsSystemPrompt;\n break;\n\n default:\n prePrompt = \"You are an AI assistant.\"; // Default fallback\n break;\n }\n return prePrompt;\n }\n #endregion\n\n #region OpenAiServiceRequest\n\n public async Task<string> OpenAiServiceRequest(string userPrompts, SystemPromptTypeEnum systemPrompt)\n {\n string model = openAiModel;\n string prePrompt = GetSystemPrompt(systemPrompt);\n\n string apiKey = Environment.GetEnvironmentVariable(\"OPENAI_API_KEY\") ?? throw new InvalidOperationException(\"API key is missing from environment variables.\");\n string apiResponce = \"An error occurred or no response was returned.\";\n //string combinedPrompt = $\"{prePrompt}\\n\\n{userPrompts}\";\n try\n {\n ChatClient client = new ChatClient(model, apiKey);\n\n var openAiRequest = new\n {\n model = model,\n messages = new[]\n {\n new { role = \"system\", content = prePrompt },\n new { role = \"user\", content = userPrompts }\n }\n };\n string jsonBody = JsonConvert.SerializeObject(openAiRequest, Formatting.Indented);\n\n UserChatMessage message = new UserChatMessage(jsonBody);\n ChatCompletion completion = await client.CompleteChatAsync(message);\n\n if (completion?.Content != null && completion.Content.Count > 0)\n {\n apiResponce = completion.Content[0].Text;\n\n }\n else\n {\n apiResponce = \"No valid content found in the response.\";\n }\n Console.WriteLine(\"after ai\");\n\n }\n catch (Exception ex)\n {\n Console.WriteLine(ex.Message);\n }\n\n return apiResponce;\n }\n #endregion\n\n #region Grok ai request\n public async Task<string> GrokRequestService(string userMessage, SystemPromptTypeEnum aiRequest)\n {\n string grokUrl = \"https://api.x.ai/v1/chat/completions\";\n string apiGrokKey = Environment.GetEnvironmentVariable(\"GROK_API_KEY\") ?? throw new InvalidOperationException(\"API key is missing from environment variables.\");\n\n using (HttpClient client = new HttpClient())\n {\n string aiPrePromptType = GetSystemPrompt(aiRequest);\n\n client.DefaultRequestHeaders.Add(\"Authorization\", $\"Bearer {apiGrokKey}\");\n\n var requestBody = new\n {\n messages = new[]\n {\n new { role = \"system\", content = aiPrePromptType },\n new { role = \"user\", content = userMessage }\n },\n model = grokAiMode,\n stream = false,\n temperature = 0\n };\n\n var jsonContent = new StringContent(JsonConvert.SerializeObject(requestBody), Encoding.UTF8, \"application/json\");\n HttpResponseMessage response = await client.PostAsync(grokUrl, jsonContent);\n\n if (response.IsSuccessStatusCode)\n {\n string jsonResponse = await response.Content.ReadAsStringAsync();\n\n // ✅ Extract only the \"content\" field from the response\n using JsonDocument doc = JsonDocument.Parse(jsonResponse);\n\n if (doc.RootElement.TryGetProperty(\"choices\", out JsonElement choicesArray) &&\n choicesArray.GetArrayLength() > 0 &&\n choicesArray[0].TryGetProperty(\"message\", out JsonElement message) &&\n message.TryGetProperty(\"content\", out JsonElement contentElement))\n {\n return contentElement.GetString() ?? \"No content available.\";\n }\n\n return \"Invalid response format.\";\n }\n else\n {\n return $\"Error: {response.StatusCode} - {response.ReasonPhrase}\";\n }\n }\n }\n #endregion\n\n #region Deep seek ai request\n private readonly HttpClient _httpClient = new HttpClient();\n\n public async Task<string> DeepSeekResponceAi(string userPrompts, SystemPromptTypeEnum aiRequest)\n {\n string apiUrl = \"https://api.deepseek.com/chat/completions\"; // Replace with actual API URL\n string bearerToken = \"sk-5706d7050b8c4bddb967ba236538d89d\"; // Replace with actual token\n string prePrompt = GetSystemPrompt(aiRequest);\n var requestBody = new\n {\n model = \"deepseek-chat\",\n messages = new[]\n {\n new { role = \"system\", content = prePrompt },\n new { role = \"user\", content = userPrompts }\n\n },\n stream = false\n };\n\n string jsonRequest = System.Text.Json.JsonSerializer.Serialize(requestBody);\n var content = new StringContent(jsonRequest, Encoding.UTF8, \"application/json\"); // ✅ \"Content-Type\" set correctly here\n\n var request = new HttpRequestMessage(HttpMethod.Post, apiUrl)\n {\n Content = content\n };\n\n request.Headers.Add(\"Authorization\", $\"Bearer {bearerToken}\"); // ✅ Correct place for Authorization\n // No need to add \"Content-Type\" again here\n\n HttpResponseMessage response = await _httpClient.SendAsync(request);\n string jsonResponse = await response.Content.ReadAsStringAsync();\n\n using JsonDocument doc = JsonDocument.Parse(jsonResponse);\n\n string? contentResponce = doc.RootElement\n .GetProperty(\"choices\")[0]\n .GetProperty(\"message\")\n .GetProperty(\"content\")\n .GetString();\n\n return contentResponce;\n }\n #endregion\n\n #region Claude ais request\n\n public async Task<string> GetClaudeResponse(string userPrompts, SystemPromptTypeEnum aiRequest,\n string apiKey = \"\")\n {\n string prePrompt = GetSystemPrompt(aiRequest);\n if (string.IsNullOrEmpty(apiKey))\n {\n //apiKey = Environment.GetEnvironmentVariable(\"CLAUDE_API_KEY\") ?? throw new InvalidOperationException(\"API key is missing from environment variables.\");\n Console.WriteLine(\"Anthropic Api key is: \" +apiKey);\n throw new InvalidOperationException(\"API key is missing. Please provide a valid API key for Claude AI.\");\n }\n string url = \"https://api.anthropic.com/v1/messages\";\n string claudeModel = \"claude-3-5-sonnet-20240620\";\n var requestBody = new\n {\n model = \"claude-3-5-haiku-20241022\",\n max_tokens = 1024,\n system = prePrompt,\n messages = new[]\n {\n new { role = \"user\", content = userPrompts }\n }\n };\n\n var json = JsonConvert.SerializeObject(requestBody);\n\n // Use the retry method with fresh request creation\n var response = await SendWithRetries(json, url, apiKey);\n\n string responseContent = await response.Content.ReadAsStringAsync();\n\n if (!response.IsSuccessStatusCode)\n {\n throw new InvalidOperationException($\"API key is incorrect (Anthropic return http status {response.StatusCode}, {responseContent}). \" +\n $\"Please provide a valid API key for Claude AI.\");\n //return $\"Error: {response.StatusCode}\\n{responseContent}\";\n }\n\n JObject parsed = JObject.Parse(responseContent);\n var text = parsed[\"content\"]?[0]?[\"text\"]?.ToString();\n\n return text ?? \"No text content found.\";\n }\n\n private async Task<HttpResponseMessage> SendWithRetries(string json, string url, string apiKey, int maxRetries = 3)\n {\n for (int attempt = 0; attempt < maxRetries; attempt++)\n {\n var request = new HttpRequestMessage(HttpMethod.Post, url);\n request.Headers.Add(\"x-api-key\", apiKey);\n request.Headers.Add(\"anthropic-version\", \"2023-06-01\");\n request.Content = new StringContent(json, Encoding.UTF8, \"application/json\");\n\n var response = await _httpClient.SendAsync(request);\n\n if ((int)response.StatusCode != 529)\n return response;\n\n int waitTime = (int)Math.Pow(2, attempt + 1) * 1000; // 2s, 4s, 8s\n await Task.Delay(waitTime);\n }\n\n throw new Exception(\"Claude API is overloaded (529) after multiple retries.\");\n }\n\n #endregion\n }\n public enum AiServicesList\n {\n OpenAi,\n Grok,\n Claude,\n DeepSeek\n }\n}\n"}, "b226e6dd07ab73064c592b8bd906402b6b6b7f42": {"t": 1785760513.8067992, "n": 18117, "h": "5e15b8375b5fb917", "c": "using Newtonsoft.Json;\nusing Newtonsoft.Json.Linq;\nusing OpenAI.Chat;\nusing System.Text;\nusing System.Text.Json;\n\nnamespace SafeCash.Test.ApiTest.Integration.OpenAi\n{\n public class OpenAiService\n {\n public static string openAiModel = \"gpt-4o-mini\";\n public static string grokAiMode = \"grok-3-mini-fast-latest\";\n #region SystemPrompt\n public enum SystemPromptTypeEnum\n {\n ApiRequest,\n MobileTextInpueRequest,\n MobileSystemPromptMissionTask,\n MobileXyCordinateRequest,\n ImagesCompare,\n AppPackageDetails,\n }\n string mobilePrePrompt = \"You are an automation expert.\\n\" +\n \"Given a mobile XML element dump, return only the XPath of the button or element best matching the target.\\n\\n\" +\n \"Rules:\\n\" +\n \"- Match by content-desc, text, or resource-id.\\n\" +\n \"- If provided, also consider color or visual clues (e.g., \\\"Blue icon\\\") when content-desc, text, or resource-id are insufficient.\\n\" +\n \"- One match → return XPath only. Multiple → return count. No match → return 0.\\n\" +\n \"- Allow partial matches (substring, typo, etc.).\\n\" +\n \"- Recognize semantic and visual terms (e.g., '3 dots', 'plus icon', 'person icon', color descriptions):\\n\" +\n \" • 'plus icon' → content-desc with 'Add'/'Create' or resource-id with 'fab'\\n\" +\n \" • 'search field' → EditText or 'Search'\\n\" +\n \" • 'person icon' → profile/avatar/user\\n\" +\n \" • 'menu button' or '3 dots' → 'More options' or 'Customize and control'\\n\" +\n \" • Color terms (e.g., \\\"Blue icon\\\") → prioritize clickable buttons (ImageButton, Button, ImageView) without text\\n\" +\n \" especially when stated clearly like FAB buttons or visually distinct elements\\n\" +\n \" • Also infer visual roles or icon types from user terms (e.g., 'record icon', 'dialpad icon', '10 dots') even if no exact match in content-desc/text\\n\" +\n \"- Layouts (FrameLayout, LinearLayout) are valid if clickable and labeled.\\n\\n\" +\n \"Examples:\\n\" +\n \"<android.widget.ImageButton content-desc=\\\"5\\\" />\\n\" +\n \"Target: 5\\n\" +\n \"Expected: //android.widget.ImageButton[@content-desc=\\\"5\\\"]\\n\\n\" +\n \"<android.widget.ImageView resource-id=\\\"com.app:id/profile_icon\\\" />\\n\" +\n \"Target: person icon\\n\" +\n \"Expected: //android.widget.ImageView[@resource-id=\\\"com.app:id/profile_icon\\\"]\\n\\n\" +\n \"<android.widget.Button content-desc=\\\"Add city\\\" resource-id=\\\"com.google.android.deskclock:id/fab\\\" />\\n\" +\n \"Target: plus icon\\n\" +\n \"Expected: //android.widget.Button[@content-desc=\\\"Add city\\\"]\\n\\n\" +\n \"<android.widget.ImageButton content-desc=\\\"key pad\\\" resource-id=\\\"com.google.android.dialer:id/dialpad_fab\\\" clickable=\\\"true\\\" />\\n\" +\n \"Target: Blue icon with 10 dots\\n\" +\n \"Expected: //android.widget.ImageButton[@resource-id=\\\"com.google.android.dialer:id/dialpad_fab\\\"]\\n\\n\" +\n \"Important: Return ONLY the raw XPath string (no markdown, no quotes, no formatting).\\n\" +\n \"Now analyze the following:\";\n\n string mobilePrePromptCordinateXy = \"You are an automation expert.\\n\" +\n \"Your task is:\\n\" +\n \"Given:\\n\" +\n \"- A full XML dump of a mobile screen hierarchy.\\n\" +\n \"- The screen width and height.\\n\" +\n \"- A pair of coordinates (X and Y).\\n\\n\" +\n \"Rules:\\n\" +\n \"1. Identify the single UI element in the XML whose bounds ([left,top][right,bottom]) fully contain the given X and Y coordinates.\\n\" +\n \"2. If multiple elements overlap, select the deepest (most nested) element.\\n\" +\n \"3. Return only the XPath expression to locate that specific element.\\n\" +\n \"4. XPath must be precise and use resource-id or content-desc if available.\\n\" +\n \" - Prefer resource-id when present.\\n\" +\n \" - If resource-id is missing, use content-desc.\\n\" +\n \" - If both are missing, use full tag and index path.\\n\" +\n \"5. If no matching element is found, return exactly the number 0 (zero) and nothing else.\\n\" +\n \"6. Never explain, apologize, or add any extra text.\\n\\n\" +\n \"Examples of valid responses:\\n\" +\n \"- //android.widget.ImageButton[@resource-id=\\\"com.example:id/button\\\"]\\n\" +\n \"- //android.widget.TextView[@content-desc=\\\"Submit\\\"]\\n\" +\n \"- 0\\n\\n\" +\n \"Important:\\n\" +\n \"- Screen coordinates are based on the screen size.\\n\" +\n \"- Bounds are given as [left,top][right,bottom] relative to the screen.\\n\" +\n \"- Coordinates on the exact border (equal to left or top but less than right or bottom) are considered inside the bounds.\\n\" +\n \"- Always return only one XPath or 0.\\n\" +\n \"7. Coordinates must be strictly inside the bounds:\\n \" +\n \"- X must be >= left and < right.\\n \" +\n \" - Y must be >= top and < bottom.\\n \" +\n \"- No partial matches are allowed.\\n \" +\n \"- Ignore elements where X and Y are not fully contained inside bounds.\\n\";\n\n string aiSystemPromptMissionTask =\n \"You are a smart navigation agent inside a mobile app.\\n\\n\" +\n \"Your task is to analyze the given Android XML UI hierarchy and guide the user step-by-step to complete their goal.\\n\\n\" +\n \"Input:\\n\" +\n \"1. xmlHierarchy – the current screen's XML.\\n\" +\n \"2. userGoal – a free-text description of what the user wants to do (e.g. 'Search for Hello World').\\n\\n\" +\n \"Process:\\n\" +\n \"- Parse the XML and check if the goal is already complete.\\n\" +\n \"- If the user goal is fully completed (all required inputs/actions are done), return:\\n\" +\n \" { \\\"type\\\": 3 }\\n\" +\n \"- If not, find the next visible UI element that moves the user closer to the goal.\\n\" +\n \"- Prefer buttons like 'Next', 'OK', or 'Continue' unless the goal says otherwise.\\n\" +\n \"- Only suggest actions that match real elements in the XML (no guesses).\\n\" +\n \"- Use exact XPaths based on class, text, content-desc, or resource-id.\\n\" +\n \"- Return only one step at a time – button click or input.\\n\" +\n \"- If stuck, return: { \\\"type\\\": 0 }\\n\\n\" +\n\n \"Output format:\\n\" +\n \"- Click: { \\\"type\\\": 1, \\\"xpath\\\": \\\"...\\\" }\\n\" +\n \"- Input: { \\\"type\\\": 2, \\\"xpath\\\": \\\"...\\\", \\\"value\\\": \\\"...\\\" }\\n\" +\n \"- Done: { \\\"type\\\": 3 }\\n\" +\n \"- No action: { \\\"type\\\": 0 }\\n\\n\" +\n\n \"Important:\\n\" +\n \"- If all required steps are marked as already clicked (via provided locators), return { \\\"type\\\": 3 } and do not continue.\\n\" +\n \"- Never return commentary or code blocks – only a valid JSON object.\\n\" +\n \"- Do not return suggestions for extra UI elements if not part of the userGoal.\\n\";\n\n\n string getAppPackageDetailsSystemPrompt =\n @\"You are an Android expert.\n Your task is to extract the appPackage and appActivity for a specific app name (e.g., 'camera' or 'contacts').\n\n You will receive:\n - A list of installed app packages\n - A target app name\n\n ---\n\n Your job is to:\n 1. Find the app package that best matches the target app name (case-insensitive, partial match is allowed).\n 2. Return a valid JSON in this exact format:\n {\n \"\"appPackage\"\": \"\"<appPackage>\"\",\n \"\"appActivity\"\": \"\"<appActivity>\"\"\n }\n\n ---\n\n Rules:\n - Respond with JSON only. No explanation, no extra text.\n - If multiple packages might match, return the best/most likely one.\n - If no match found, still return the JSON with empty values:\n {\n \"\"appPackage\"\": \"\"\"\",\n \"\"appActivity\"\": \"\"\"\"\n }\n \";\n\n public string GetSystemPrompt(SystemPromptTypeEnum aiRequest)\n {\n string prePrompt;\n switch (aiRequest)\n {\n case SystemPromptTypeEnum.MobileTextInpueRequest:\n prePrompt = mobilePrePrompt;\n break;\n case SystemPromptTypeEnum.MobileSystemPromptMissionTask:\n prePrompt = aiSystemPromptMissionTask;\n break;\n case SystemPromptTypeEnum.MobileXyCordinateRequest:\n prePrompt = mobilePrePromptCordinateXy;\n break;\n case SystemPromptTypeEnum.AppPackageDetails:\n prePrompt = getAppPackageDetailsSystemPrompt;\n break;\n\n default:\n prePrompt = \"You are an AI assistant.\"; // Default fallback\n break;\n }\n return prePrompt;\n }\n #endregion\n\n #region OpenAiServiceRequest\n\n public async Task<string> OpenAiServiceRequest(string userPrompts, SystemPromptTypeEnum systemPrompt)\n {\n string model = openAiModel;\n string prePrompt = GetSystemPrompt(systemPrompt);\n\n string apiKey = Environment.GetEnvironmentVariable(\"OPENAI_API_KEY\") ?? throw new InvalidOperationException(\"API key is missing from environment variables.\");\n string apiResponce = \"An error occurred or no response was returned.\";\n //string combinedPrompt = $\"{prePrompt}\\n\\n{userPrompts}\";\n try\n {\n ChatClient client = new ChatClient(model, apiKey);\n\n var openAiRequest = new\n {\n model = model,\n messages = new[]\n {\n new { role = \"system\", content = prePrompt },\n new { role = \"user\", content = userPrompts }\n }\n };\n string jsonBody = JsonConvert.SerializeObject(openAiRequest, Formatting.Indented);\n\n UserChatMessage message = new UserChatMessage(jsonBody);\n ChatCompletion completion = await client.CompleteChatAsync(message);\n\n if (completion?.Content != null && completion.Content.Count > 0)\n {\n apiResponce = completion.Content[0].Text;\n\n }\n else\n {\n apiResponce = \"No valid content found in the response.\";\n }\n Console.WriteLine(\"after ai\");\n\n }\n catch (Exception ex)\n {\n Console.WriteLine(ex.Message);\n }\n\n return apiResponce;\n }\n #endregion\n\n #region Grok ai request\n public async Task<string> GrokRequestService(string userMessage, SystemPromptTypeEnum aiRequest)\n {\n string grokUrl = \"https://api.x.ai/v1/chat/completions\";\n string apiGrokKey = Environment.GetEnvironmentVariable(\"GROK_API_KEY\") ?? throw new InvalidOperationException(\"API key is missing from environment variables.\");\n\n using (HttpClient client = new HttpClient())\n {\n string aiPrePromptType = GetSystemPrompt(aiRequest);\n\n client.DefaultRequestHeaders.Add(\"Authorization\", $\"Bearer {apiGrokKey}\");\n\n var requestBody = new\n {\n messages = new[]\n {\n new { role = \"system\", content = aiPrePromptType },\n new { role = \"user\", content = userMessage }\n },\n model = grokAiMode,\n stream = false,\n temperature = 0\n };\n\n var jsonContent = new StringContent(JsonConvert.SerializeObject(requestBody), Encoding.UTF8, \"application/json\");\n HttpResponseMessage response = await client.PostAsync(grokUrl, jsonContent);\n\n if (response.IsSuccessStatusCode)\n {\n string jsonResponse = await response.Content.ReadAsStringAsync();\n\n // ✅ Extract only the \"content\" field from the response\n using JsonDocument doc = JsonDocument.Parse(jsonResponse);\n\n if (doc.RootElement.TryGetProperty(\"choices\", out JsonElement choicesArray) &&\n choicesArray.GetArrayLength() > 0 &&\n choicesArray[0].TryGetProperty(\"message\", out JsonElement message) &&\n message.TryGetProperty(\"content\", out JsonElement contentElement))\n {\n return contentElement.GetString() ?? \"No content available.\";\n }\n\n return \"Invalid response format.\";\n }\n else\n {\n return $\"Error: {response.StatusCode} - {response.ReasonPhrase}\";\n }\n }\n }\n #endregion\n\n #region Deep seek ai request\n private readonly HttpClient _httpClient = new HttpClient();\n\n public async Task<string> DeepSeekResponceAi(string userPrompts, SystemPromptTypeEnum aiRequest)\n {\n string apiUrl = \"https://api.deepseek.com/chat/completions\"; // Replace with actual API URL\n string bearerToken = \"sk-5706d7050b8c4bddb967ba236538d89d\"; // Replace with actual token\n string prePrompt = GetSystemPrompt(aiRequest);\n var requestBody = new\n {\n model = \"deepseek-chat\",\n messages = new[]\n {\n new { role = \"system\", content = prePrompt },\n new { role = \"user\", content = userPrompts }\n\n },\n stream = false\n };\n\n string jsonRequest = System.Text.Json.JsonSerializer.Serialize(requestBody);\n var content = new StringContent(jsonRequest, Encoding.UTF8, \"application/json\"); // ✅ \"Content-Type\" set correctly here\n\n var request = new HttpRequestMessage(HttpMethod.Post, apiUrl)\n {\n Content = content\n };\n\n request.Headers.Add(\"Authorization\", $\"Bearer {bearerToken}\"); // ✅ Correct place for Authorization\n // No need to add \"Content-Type\" again here\n\n HttpResponseMessage response = await _httpClient.SendAsync(request);\n string jsonResponse = await response.Content.ReadAsStringAsync();\n\n using JsonDocument doc = JsonDocument.Parse(jsonResponse);\n\n string? contentResponce = doc.RootElement\n .GetProperty(\"choices\")[0]\n .GetProperty(\"message\")\n .GetProperty(\"content\")\n .GetString();\n\n return contentResponce;\n }\n #endregion\n\n #region Claude ais request\n\n public async Task<string> GetClaudeResponse(string userPrompts, SystemPromptTypeEnum aiRequest,\n string apiKey = \"\")\n {\n string prePrompt = GetSystemPrompt(aiRequest);\n if (string.IsNullOrEmpty(apiKey))\n {\n apiKey = Environment.GetEnvironmentVariable(\"CLAUDE_API_KEY\") ?? throw new InvalidOperationException(\"API key is missing from environment variables.\");\n // throw new InvalidOperationException(\"API key is missing. Please provide a valid API key for Claude AI.\");\n }\n string url = \"https://api.anthropic.com/v1/messages\";\n string claudeModel = \"claude-3-5-sonnet-20240620\";\n var requestBody = new\n {\n model = \"claude-3-5-haiku-20241022\",\n max_tokens = 1024,\n system = prePrompt,\n messages = new[]\n {\n new { role = \"user\", content = userPrompts }\n }\n };\n\n var json = JsonConvert.SerializeObject(requestBody);\n\n // Use the retry method with fresh request creation\n var response = await SendWithRetries(json, url, apiKey);\n\n string responseContent = await response.Content.ReadAsStringAsync();\n\n if (!response.IsSuccessStatusCode)\n {\n throw new InvalidOperationException($\"API key is incorrect (Anthropic return http status {response.StatusCode}, {responseContent}). \" +\n $\"Please provide a valid API key for Claude AI.\");\n //return $\"Error: {response.StatusCode}\\n{responseContent}\";\n }\n\n JObject parsed = JObject.Parse(responseContent);\n var text = parsed[\"content\"]?[0]?[\"text\"]?.ToString();\n\n return text ?? \"No text content found.\";\n }\n\n private async Task<HttpResponseMessage> SendWithRetries(string json, string url, string apiKey, int maxRetries = 3)\n {\n for (int attempt = 0; attempt < maxRetries; attempt++)\n {\n var request = new HttpRequestMessage(HttpMethod.Post, url);\n request.Headers.Add(\"x-api-key\", apiKey);\n request.Headers.Add(\"anthropic-version\", \"2023-06-01\");\n request.Content = new StringContent(json, Encoding.UTF8, \"application/json\");\n\n var response = await _httpClient.SendAsync(request);\n\n if ((int)response.StatusCode != 529)\n return response;\n\n int waitTime = (int)Math.Pow(2, attempt + 1) * 1000; // 2s, 4s, 8s\n await Task.Delay(waitTime);\n }\n\n throw new Exception(\"Claude API is overloaded (529) after multiple retries.\");\n }\n\n #endregion\n }\n public enum AiServicesList\n {\n OpenAi,\n Grok,\n Claude,\n DeepSeek\n }\n}\n"}}}}