davsclaus commented on code in PR #25172:
URL: https://github.com/apache/camel/pull/25172#discussion_r3663022710


##########
dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/DoctorPopup.java:
##########
@@ -288,6 +288,8 @@ private void checkAiProvider(List<Line> result) {
             provider = "Anthropic";
         } else if (envSet("CLOUD_ML_REGION") && 
envSet("ANTHROPIC_VERTEX_PROJECT_ID")) {
             provider = "Vertex AI";
+        } else if (envSet("GEMINI_API_KEY") || envSet("GOOGLE_API_KEY")) {

Review Comment:
   This check uses `||` (`GEMINI_API_KEY` OR `GOOGLE_API_KEY`), but 
auto-detection in `LlmClient.tryGemini(false)` only checks `GEMINI_API_KEY` via 
`resolveGeminiApiKeyFromEnvForAutoDetect()`. A user with only `GOOGLE_API_KEY` 
set (common for other Google Cloud services) would see "Gemini" here in the 
Doctor but then hit "No LLM service reachable" from actual detection.
   
   The Doctor should match auto-detection behavior:
   
   ```suggestion
           } else if (envSet("GEMINI_API_KEY")) {
   ```



##########
dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/LlmClient.java:
##########
@@ -451,6 +516,312 @@ private String generateOpenAi(String systemPrompt, String 
userPrompt) {
         return extractOpenAiContent(response);
     }
 
+    // ---- Gemini generate ----
+
+    private String generateGemini(String systemPrompt, String userPrompt) {
+        JsonObject request = buildGeminiGenerateRequest(systemPrompt, 
userPrompt, null);
+        String apiUrl = geminiGenerateContentUrl(resolveGeminiApiKey());
+        JsonObject response = sendGeminiRequest(apiUrl, request);
+        return extractGeminiTextFromResponse(response);
+    }
+
+    private ChatResponse chatGeminiFormat(String systemPrompt, List<Message> 
messages, List<ToolDef> tools) {
+        JsonObject request = buildGeminiGenerateRequest(systemPrompt, null, 
tools);
+        request.put("contents", buildGeminiContents(messages));
+        String apiUrl = geminiGenerateContentUrl(resolveGeminiApiKey());
+        JsonObject response = sendGeminiRequest(apiUrl, request);
+        return parseGeminiChatResponse(response);
+    }
+
+    private JsonObject buildGeminiGenerateRequest(String systemPrompt, String 
userPrompt, List<ToolDef> tools) {
+        JsonObject request = new JsonObject();
+        if (systemPrompt != null && !systemPrompt.isBlank()) {
+            JsonObject systemInstruction = new JsonObject();
+            JsonArray parts = new JsonArray();
+            JsonObject text = new JsonObject();
+            text.put("text", systemPrompt);
+            parts.add(text);
+            systemInstruction.put("parts", parts);
+            request.put("systemInstruction", systemInstruction);
+        }
+        if (userPrompt != null) {
+            JsonArray contents = new JsonArray();
+            JsonObject user = new JsonObject();
+            user.put("role", "user");
+            JsonArray parts = new JsonArray();
+            JsonObject text = new JsonObject();
+            text.put("text", userPrompt);
+            parts.add(text);
+            user.put("parts", parts);
+            contents.add(user);
+            request.put("contents", contents);
+        }
+        JsonObject generationConfig = new JsonObject();
+        generationConfig.put("temperature", temperature);
+        if (maxTokens > 0) {
+            generationConfig.put("maxOutputTokens", maxTokens);
+        }
+        request.put("generationConfig", generationConfig);
+        JsonArray declarations = buildGeminiFunctionDeclarations(tools);
+        if (declarations != null) {
+            JsonObject toolsObj = new JsonObject();
+            toolsObj.put("functionDeclarations", declarations);
+            JsonArray toolsArray = new JsonArray();
+            toolsArray.add(toolsObj);
+            request.put("tools", toolsArray);
+        }
+        return request;
+    }
+
+    JsonObject buildGeminiGenerateRequestForTest(String systemPrompt, 
List<Message> messages, List<ToolDef> tools) {
+        JsonObject request = buildGeminiGenerateRequest(systemPrompt, null, 
tools);
+        request.put("contents", buildGeminiContents(messages));
+        return request;
+    }
+
+    private JsonArray buildGeminiContents(List<Message> messages) {
+        JsonArray contents = new JsonArray();
+        for (Message msg : messages) {
+            if (msg.toolCalls() != null && !msg.toolCalls().isEmpty()) {
+                JsonObject modelMsg = new JsonObject();
+                modelMsg.put("role", "model");
+                JsonArray parts = new JsonArray();
+                if (msg.content() != null && !msg.content().isBlank()) {
+                    JsonObject text = new JsonObject();
+                    text.put("text", msg.content());
+                    parts.add(text);
+                }
+                for (ToolCall tc : msg.toolCalls()) {
+                    JsonObject functionCall = new JsonObject();
+                    functionCall.put("name", tc.name());
+                    functionCall.put("args", tc.arguments());
+                    if (tc.id() != null && !tc.id().isBlank() && 
!tc.id().equals(tc.name())) {
+                        functionCall.put("id", tc.id());
+                    }
+                    if (tc.thoughtSignature() != null && 
!tc.thoughtSignature().isBlank()) {
+                        functionCall.put("thoughtSignature", 
tc.thoughtSignature());
+                    }
+                    JsonObject part = new JsonObject();
+                    part.put("functionCall", functionCall);
+                    parts.add(part);
+                }
+                modelMsg.put("parts", parts);
+                contents.add(modelMsg);
+            } else if (msg.toolResults() != null && 
!msg.toolResults().isEmpty()) {
+                JsonObject userMsg = new JsonObject();
+                userMsg.put("role", "user");
+                JsonArray parts = new JsonArray();
+                for (ToolResult tr : msg.toolResults()) {
+                    JsonObject responseBody = new JsonObject();
+                    responseBody.put("content", tr.content());
+                    JsonObject functionResponse = new JsonObject();
+                    functionResponse.put("name", 
toolResultFunctionName(tr.toolCallId()));
+                    functionResponse.put("response", responseBody);
+                    JsonObject part = new JsonObject();
+                    part.put("functionResponse", functionResponse);
+                    parts.add(part);
+                }
+                userMsg.put("parts", parts);
+                contents.add(userMsg);
+            } else {
+                JsonObject turn = new JsonObject();
+                turn.put("role", "user".equals(msg.role()) ? "user" : "model");
+                JsonArray parts = new JsonArray();
+                JsonObject text = new JsonObject();
+                text.put("text", msg.content());
+                parts.add(text);
+                turn.put("parts", parts);
+                contents.add(turn);
+            }
+        }
+        return contents;
+    }
+
+    private static String toolResultFunctionName(String toolCallId) {
+        if (toolCallId == null || toolCallId.isBlank()) {
+            return "tool";
+        }
+        return toolCallId;
+    }
+
+    private JsonArray buildGeminiFunctionDeclarations(List<ToolDef> tools) {
+        if (tools == null || tools.isEmpty()) {
+            return null;
+        }
+        JsonArray declarations = new JsonArray();
+        for (ToolDef tool : tools) {
+            JsonObject decl = new JsonObject();
+            decl.put("name", tool.name());
+            decl.put("description", tool.description());
+            decl.put("parameters", tool.parameters());
+            declarations.add(decl);
+        }
+        return declarations;
+    }
+
+    ChatResponse parseGeminiChatResponse(JsonObject response) {
+        if (response == null) {
+            return new ChatResponse(null, List.of(), "error", false, 
TokenUsage.EMPTY);
+        }
+        TokenUsage usage = extractGeminiUsage(response);
+        JsonArray candidates = (JsonArray) response.get("candidates");
+        if (candidates == null || candidates.isEmpty()) {
+            return new ChatResponse(null, List.of(), "error", false, usage);
+        }
+        JsonObject candidate = (JsonObject) candidates.get(0);
+        String finishReason = candidate.getString("finishReason");
+        JsonObject content = (JsonObject) candidate.get("content");
+        if (content == null) {
+            return new ChatResponse(null, List.of(), finishReason, false, 
usage);
+        }
+        JsonArray parts = (JsonArray) content.get("parts");
+        if (parts == null) {
+            return new ChatResponse(null, List.of(), finishReason, false, 
usage);
+        }
+        StringBuilder text = new StringBuilder();
+        List<ToolCall> toolCalls = new ArrayList<>();
+        for (Object obj : parts) {
+            if (!(obj instanceof JsonObject part)) {
+                continue;
+            }
+            if (part.get("text") != null) {
+                text.append(part.getString("text"));
+            }
+            JsonObject functionCall = (JsonObject) part.get("functionCall");
+            if (functionCall != null) {
+                String name = functionCall.getString("name");
+                String callId = functionCall.getString("id");
+                if (callId == null || callId.isBlank()) {
+                    callId = name;
+                }
+                JsonObject args = functionCall.get("args") instanceof 
JsonObject jo ? jo : new JsonObject();
+                String thoughtSignature = 
functionCall.getString("thoughtSignature");
+                toolCalls.add(new ToolCall(callId, name, args, 
thoughtSignature));
+            }
+        }
+        String stopReason = !toolCalls.isEmpty() ? "tool_calls" : finishReason;
+        String contentText = text.length() > 0 ? text.toString() : null;
+        return new ChatResponse(contentText, toolCalls, stopReason, false, 
usage);
+    }
+
+    String extractGeminiTextFromResponse(JsonObject response) {
+        if (response == null) {
+            return null;
+        }
+        JsonArray candidates = (JsonArray) response.get("candidates");
+        if (candidates == null || candidates.isEmpty()) {
+            return null;
+        }
+        JsonObject candidate = (JsonObject) candidates.get(0);
+        JsonObject content = (JsonObject) candidate.get("content");
+        if (content == null) {
+            return null;
+        }
+        JsonArray parts = (JsonArray) content.get("parts");
+        if (parts == null) {
+            return null;
+        }
+        StringBuilder sb = new StringBuilder();
+        for (Object obj : parts) {
+            if (obj instanceof JsonObject part && part.get("text") != null) {
+                sb.append(part.getString("text"));
+            }
+        }
+        return sb.length() > 0 ? sb.toString() : null;
+    }
+
+    private TokenUsage extractGeminiUsage(JsonObject response) {
+        JsonObject usageMetadata = (JsonObject) response.get("usageMetadata");
+        if (usageMetadata == null) {
+            return TokenUsage.EMPTY;
+        }
+        int input = getIntValue(usageMetadata, "promptTokenCount");
+        int output = getIntValue(usageMetadata, "candidatesTokenCount");
+        int total = getIntValue(usageMetadata, "totalTokenCount");
+        if (total == 0) {
+            total = input + output;
+        }
+        return new TokenUsage(input, output, total);
+    }
+
+    private JsonObject sendGeminiRequest(String requestUrl, JsonObject body) {
+        return sendRequestWithHeaders(requestUrl, body, 
buildGeminiHeaders(resolveGeminiApiKey()));
+    }
+
+    String geminiGenerateContentUrl(String key) {
+        String base = normalizeGeminiBaseUrl(url);
+        String modelId = normalizeGeminiModelId(model);
+        return base + "/models/" + modelId + ":generateContent";
+    }
+
+    static String normalizeGeminiModelId(String modelId) {
+        if (modelId == null) {
+            return DEFAULT_GEMINI_MODEL;
+        }
+        if (modelId.startsWith("models/")) {
+            return modelId.substring("models/".length());
+        }
+        return modelId;
+    }
+
+    static String normalizeGeminiBaseUrl(String endpoint) {
+        if (endpoint == null || endpoint.isBlank()) {
+            return DEFAULT_GEMINI_URL;
+        }
+        String u = endpoint.endsWith("/") ? endpoint.substring(0, 
endpoint.length() - 1) : endpoint;
+        if (u.endsWith(":generateContent") || 
u.endsWith("%3AgenerateContent")) {
+            int modelsIdx = u.indexOf("/models/");
+            if (modelsIdx > 0) {
+                return u.substring(0, modelsIdx);
+            }
+        }
+        return u;
+    }
+
+    static Map<String, String> buildGeminiHeaders(String key) {
+        Map<String, String> headers = new HashMap<>();
+        headers.put("Content-Type", "application/json");
+        if (key != null && !key.isBlank()) {
+            headers.put("x-goog-api-key", key);
+        }
+        return headers;
+    }
+
+    static String appendGeminiApiKey(String requestUrl, String key) {

Review Comment:
   This method is defined but never called — in the PR or the existing 
codebase. It looks like a leftover from when Gemini auth was via query 
parameter (now handled via `x-goog-api-key` header in `buildGeminiHeaders`). 
Please remove the dead code.



##########
dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/DoctorPopup.java:
##########
@@ -305,7 +307,8 @@ private void checkAiProvider(List<Line> result) {
                     Span.styled(String.format("%-14s", "AI"), Theme.muted()),
                     Span.raw(String.format("%-30s", "No API key configured")),
                     Span.raw(" " + TuiIcons.WARN)));
-            result.add(Line.from(Span.styled("                    Set 
ANTHROPIC_API_KEY or OPENAI_API_KEY",
+            result.add(Line.from(Span.styled(
+                    "                    Set ANTHROPIC_API_KEY, 
GEMINI_API_KEY, GOOGLE_API_KEY, or OPENAI_API_KEY",

Review Comment:
   Same issue — `GOOGLE_API_KEY` only works with explicit `--api-type=gemini`, 
not auto-detection. Drop it from the hint to match auto-detection behavior:
   
   ```suggestion
                       "                    Set ANTHROPIC_API_KEY, 
GEMINI_API_KEY, or OPENAI_API_KEY",
   ```



##########
dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/AiPanel.java:
##########
@@ -290,7 +290,8 @@ private void initClient() {
             }
             client = created;
             if (!client.detectEndpoint()) {
-                initError = "No LLM service reachable. Set ANTHROPIC_API_KEY, 
OPENAI_API_KEY, or start Ollama.";
+                initError
+                        = "No LLM service reachable. Set ANTHROPIC_API_KEY, 
GEMINI_API_KEY, GOOGLE_API_KEY, OPENAI_API_KEY, or start Ollama.";

Review Comment:
   This error message lists `GOOGLE_API_KEY` as an option, but it only works 
with explicit `--api-type=gemini`, not auto-detection. Suggesting it here 
without that qualifier will confuse users who set it and still get this error.
   
   ```suggestion
                           = "No LLM service reachable. Set ANTHROPIC_API_KEY, 
GEMINI_API_KEY, OPENAI_API_KEY, or start Ollama.";
   ```



##########
dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/LlmClient.java:
##########
@@ -451,6 +516,312 @@ private String generateOpenAi(String systemPrompt, String 
userPrompt) {
         return extractOpenAiContent(response);
     }
 
+    // ---- Gemini generate ----
+
+    private String generateGemini(String systemPrompt, String userPrompt) {
+        JsonObject request = buildGeminiGenerateRequest(systemPrompt, 
userPrompt, null);
+        String apiUrl = geminiGenerateContentUrl(resolveGeminiApiKey());
+        JsonObject response = sendGeminiRequest(apiUrl, request);
+        return extractGeminiTextFromResponse(response);
+    }
+
+    private ChatResponse chatGeminiFormat(String systemPrompt, List<Message> 
messages, List<ToolDef> tools) {
+        JsonObject request = buildGeminiGenerateRequest(systemPrompt, null, 
tools);
+        request.put("contents", buildGeminiContents(messages));
+        String apiUrl = geminiGenerateContentUrl(resolveGeminiApiKey());
+        JsonObject response = sendGeminiRequest(apiUrl, request);
+        return parseGeminiChatResponse(response);
+    }
+
+    private JsonObject buildGeminiGenerateRequest(String systemPrompt, String 
userPrompt, List<ToolDef> tools) {
+        JsonObject request = new JsonObject();
+        if (systemPrompt != null && !systemPrompt.isBlank()) {
+            JsonObject systemInstruction = new JsonObject();
+            JsonArray parts = new JsonArray();
+            JsonObject text = new JsonObject();
+            text.put("text", systemPrompt);
+            parts.add(text);
+            systemInstruction.put("parts", parts);
+            request.put("systemInstruction", systemInstruction);
+        }
+        if (userPrompt != null) {
+            JsonArray contents = new JsonArray();
+            JsonObject user = new JsonObject();
+            user.put("role", "user");
+            JsonArray parts = new JsonArray();
+            JsonObject text = new JsonObject();
+            text.put("text", userPrompt);
+            parts.add(text);
+            user.put("parts", parts);
+            contents.add(user);
+            request.put("contents", contents);
+        }
+        JsonObject generationConfig = new JsonObject();
+        generationConfig.put("temperature", temperature);
+        if (maxTokens > 0) {
+            generationConfig.put("maxOutputTokens", maxTokens);
+        }
+        request.put("generationConfig", generationConfig);
+        JsonArray declarations = buildGeminiFunctionDeclarations(tools);
+        if (declarations != null) {
+            JsonObject toolsObj = new JsonObject();
+            toolsObj.put("functionDeclarations", declarations);
+            JsonArray toolsArray = new JsonArray();
+            toolsArray.add(toolsObj);
+            request.put("tools", toolsArray);
+        }
+        return request;
+    }
+
+    JsonObject buildGeminiGenerateRequestForTest(String systemPrompt, 
List<Message> messages, List<ToolDef> tools) {
+        JsonObject request = buildGeminiGenerateRequest(systemPrompt, null, 
tools);
+        request.put("contents", buildGeminiContents(messages));
+        return request;
+    }
+
+    private JsonArray buildGeminiContents(List<Message> messages) {
+        JsonArray contents = new JsonArray();
+        for (Message msg : messages) {
+            if (msg.toolCalls() != null && !msg.toolCalls().isEmpty()) {
+                JsonObject modelMsg = new JsonObject();
+                modelMsg.put("role", "model");
+                JsonArray parts = new JsonArray();
+                if (msg.content() != null && !msg.content().isBlank()) {
+                    JsonObject text = new JsonObject();
+                    text.put("text", msg.content());
+                    parts.add(text);
+                }
+                for (ToolCall tc : msg.toolCalls()) {
+                    JsonObject functionCall = new JsonObject();
+                    functionCall.put("name", tc.name());
+                    functionCall.put("args", tc.arguments());
+                    if (tc.id() != null && !tc.id().isBlank() && 
!tc.id().equals(tc.name())) {
+                        functionCall.put("id", tc.id());
+                    }
+                    if (tc.thoughtSignature() != null && 
!tc.thoughtSignature().isBlank()) {
+                        functionCall.put("thoughtSignature", 
tc.thoughtSignature());
+                    }
+                    JsonObject part = new JsonObject();
+                    part.put("functionCall", functionCall);
+                    parts.add(part);
+                }
+                modelMsg.put("parts", parts);
+                contents.add(modelMsg);
+            } else if (msg.toolResults() != null && 
!msg.toolResults().isEmpty()) {
+                JsonObject userMsg = new JsonObject();
+                userMsg.put("role", "user");
+                JsonArray parts = new JsonArray();
+                for (ToolResult tr : msg.toolResults()) {
+                    JsonObject responseBody = new JsonObject();
+                    responseBody.put("content", tr.content());
+                    JsonObject functionResponse = new JsonObject();
+                    functionResponse.put("name", 
toolResultFunctionName(tr.toolCallId()));
+                    functionResponse.put("response", responseBody);
+                    JsonObject part = new JsonObject();
+                    part.put("functionResponse", functionResponse);
+                    parts.add(part);
+                }
+                userMsg.put("parts", parts);
+                contents.add(userMsg);
+            } else {
+                JsonObject turn = new JsonObject();
+                turn.put("role", "user".equals(msg.role()) ? "user" : "model");
+                JsonArray parts = new JsonArray();
+                JsonObject text = new JsonObject();
+                text.put("text", msg.content());
+                parts.add(text);
+                turn.put("parts", parts);
+                contents.add(turn);
+            }
+        }
+        return contents;
+    }
+
+    private static String toolResultFunctionName(String toolCallId) {
+        if (toolCallId == null || toolCallId.isBlank()) {
+            return "tool";
+        }
+        return toolCallId;
+    }
+
+    private JsonArray buildGeminiFunctionDeclarations(List<ToolDef> tools) {
+        if (tools == null || tools.isEmpty()) {
+            return null;
+        }
+        JsonArray declarations = new JsonArray();
+        for (ToolDef tool : tools) {
+            JsonObject decl = new JsonObject();
+            decl.put("name", tool.name());
+            decl.put("description", tool.description());
+            decl.put("parameters", tool.parameters());
+            declarations.add(decl);
+        }
+        return declarations;
+    }
+
+    ChatResponse parseGeminiChatResponse(JsonObject response) {
+        if (response == null) {
+            return new ChatResponse(null, List.of(), "error", false, 
TokenUsage.EMPTY);
+        }
+        TokenUsage usage = extractGeminiUsage(response);
+        JsonArray candidates = (JsonArray) response.get("candidates");
+        if (candidates == null || candidates.isEmpty()) {
+            return new ChatResponse(null, List.of(), "error", false, usage);
+        }
+        JsonObject candidate = (JsonObject) candidates.get(0);
+        String finishReason = candidate.getString("finishReason");
+        JsonObject content = (JsonObject) candidate.get("content");
+        if (content == null) {
+            return new ChatResponse(null, List.of(), finishReason, false, 
usage);
+        }
+        JsonArray parts = (JsonArray) content.get("parts");
+        if (parts == null) {
+            return new ChatResponse(null, List.of(), finishReason, false, 
usage);
+        }
+        StringBuilder text = new StringBuilder();
+        List<ToolCall> toolCalls = new ArrayList<>();
+        for (Object obj : parts) {
+            if (!(obj instanceof JsonObject part)) {
+                continue;
+            }
+            if (part.get("text") != null) {
+                text.append(part.getString("text"));
+            }
+            JsonObject functionCall = (JsonObject) part.get("functionCall");
+            if (functionCall != null) {
+                String name = functionCall.getString("name");
+                String callId = functionCall.getString("id");
+                if (callId == null || callId.isBlank()) {
+                    callId = name;
+                }
+                JsonObject args = functionCall.get("args") instanceof 
JsonObject jo ? jo : new JsonObject();
+                String thoughtSignature = 
functionCall.getString("thoughtSignature");
+                toolCalls.add(new ToolCall(callId, name, args, 
thoughtSignature));
+            }
+        }
+        String stopReason = !toolCalls.isEmpty() ? "tool_calls" : finishReason;
+        String contentText = text.length() > 0 ? text.toString() : null;
+        return new ChatResponse(contentText, toolCalls, stopReason, false, 
usage);
+    }
+
+    String extractGeminiTextFromResponse(JsonObject response) {
+        if (response == null) {
+            return null;
+        }
+        JsonArray candidates = (JsonArray) response.get("candidates");
+        if (candidates == null || candidates.isEmpty()) {
+            return null;
+        }
+        JsonObject candidate = (JsonObject) candidates.get(0);
+        JsonObject content = (JsonObject) candidate.get("content");
+        if (content == null) {
+            return null;
+        }
+        JsonArray parts = (JsonArray) content.get("parts");
+        if (parts == null) {
+            return null;
+        }
+        StringBuilder sb = new StringBuilder();
+        for (Object obj : parts) {
+            if (obj instanceof JsonObject part && part.get("text") != null) {
+                sb.append(part.getString("text"));
+            }
+        }
+        return sb.length() > 0 ? sb.toString() : null;
+    }
+
+    private TokenUsage extractGeminiUsage(JsonObject response) {
+        JsonObject usageMetadata = (JsonObject) response.get("usageMetadata");
+        if (usageMetadata == null) {
+            return TokenUsage.EMPTY;
+        }
+        int input = getIntValue(usageMetadata, "promptTokenCount");
+        int output = getIntValue(usageMetadata, "candidatesTokenCount");
+        int total = getIntValue(usageMetadata, "totalTokenCount");
+        if (total == 0) {
+            total = input + output;
+        }
+        return new TokenUsage(input, output, total);
+    }
+
+    private JsonObject sendGeminiRequest(String requestUrl, JsonObject body) {
+        return sendRequestWithHeaders(requestUrl, body, 
buildGeminiHeaders(resolveGeminiApiKey()));
+    }
+
+    String geminiGenerateContentUrl(String key) {

Review Comment:
   The `key` parameter is never used in the method body — the URL is built 
purely from `url` and `model`. This appears to be a remnant of the 
query-parameter auth approach. Consider removing the unused parameter:
   
   ```suggestion
       String geminiGenerateContentUrl() {
   ```
   
   And update the two callers (`generateGemini` and `chatGeminiFormat`) to call 
`geminiGenerateContentUrl()` without an argument.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to