Skip to content

Reduce unnecessary function callings to Gemini#135

Closed
masap wants to merge 6 commits intoreceptron:mainfrom
masap:fix-123
Closed

Reduce unnecessary function callings to Gemini#135
masap wants to merge 6 commits intoreceptron:mainfrom
masap:fix-123

Conversation

@masap
Copy link
Copy Markdown
Contributor

@masap masap commented Mar 1, 2026

Resolves #123.

According to official documentation [1], we should specify no more than 20 function callings to Gemini .

[1] https://ai.google.dev/gemini-api/docs/function-calling?example=meeting#native-tools

Summary by CodeRabbit

  • Refactor
    • Centralized function-calling configuration to improve tool declaration and selection.
    • Added limits and safer handling when many tools are available (max 20) to reduce unexpected behavior.
    • Optional external-guided tool ordering with robust fallbacks for predictable selection.
    • Streamlined generation flow so AI instantiation and content generation occur in a clearer, more reliable order.

masap added 2 commits March 1, 2026 10:24
Resolves receptron#123.

According to official documentation [1], we should specify no more than 20
function callings to Gemini .

[1] https://ai.google.dev/gemini-api/docs/function-calling?example=meeting#native-tools

Signed-off-by: Masashi Honma <masashi.honma@gmail.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 1, 2026

📝 Walkthrough

Walkthrough

Centralized function-calling selection in server/llm/providers/google.ts via a new getFunctionCallingConfig, restructured generateWithGoogle to instantiate GoogleGenAI earlier, call generateContent with derived config, and updated tool-call id generation and extraction logic.

Changes

Cohort / File(s) Summary
Gemini / Google provider
server/llm/providers/google.ts
Added getFunctionCallingConfig(ai, config, params) to build toolDeclarations and allowedFunctionNames (caps at 20, can ask Gemini to choose indices). Reworked generateWithGoogle to instantiate GoogleGenAI earlier, use getFunctionCallingConfig to set config.tools/config.toolConfig, call generateContent(model, contents, config) directly, changed tool call id extraction from .substr(2, 9) to .substring(2, 11), and adjusted toolCalls/thought signature handling to match the new flow.

Sequence Diagram(s)

sequenceDiagram
  actor Client
  participant Server
  participant GoogleGenAI
  participant Gemini
  participant Tools

  Client->>Server: send generation request
  Server->>Server: getFunctionCallingConfig(ai, config, params)
  Server->>GoogleGenAI: instantiate with model
  Server->>GoogleGenAI: generateContent(model, contents, config)
  GoogleGenAI->>Gemini: request (with tool declarations / optional subset request)
  Gemini-->>GoogleGenAI: response (content, selected tool indices / function calls)
  GoogleGenAI-->>Server: content + toolCalls
  Server->>Tools: extract toolCalls (ids via substring) and invoke tools
  Tools-->>Server: tool results
  Server-->>Client: aggregated response
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Poem

🐇 I nibbled at functions, tidy and bright,
Chose twenty or fewer to keep things light.
I hopped, re-ordered, and trimmed the call line,
Substring fixed — now outputs align.
Carrots for code, a crisp, happy bite.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR implements capping function calls at 20 per official Gemini API guidance, directly addressing the tools-complexity error issue. However, it lacks improvements to error handling and user feedback mentioned in issue #123. Implement surface-level error handling for Gemini API 400/500 errors and add user-facing warnings about plugin/tool limits as specified in issue #123 requirements.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: limiting function calls to Gemini API, which aligns with the core modification of capping function calls at 20.
Out of Scope Changes check ✅ Passed All code changes focus on refactoring tool configuration and function call limiting to address the Gemini API tools-complexity issue; no unrelated modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
server/llm/providers/google.ts (3)

213-222: The if (ret) check is always truthy.

getFunctionCallingConfig always returns an object, never undefined or null. Consider checking for non-empty declarations instead, or remove the conditional.

♻️ Optional: check for non-empty declarations
     const ret = await getFunctionCallingConfig(ai, config, params);
-    if (ret) {
+    if (ret.functionDeclarations.length > 0) {
       config.tools = [{ functionDeclarations: ret.functionDeclarations }];
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/llm/providers/google.ts` around lines 213 - 222,
getFunctionCallingConfig(...) always returns an object so the current if (ret)
is redundant; update the conditional to verify there are actual function
declarations (e.g., check ret.functionDeclarations &&
ret.functionDeclarations.length > 0) before setting config.tools and
config.toolConfig, or remove the if and always assign if you intend to apply an
empty config; reference getFunctionCallingConfig, ret, config.tools,
config.toolConfig and FunctionCallingConfigMode.ANY when making the change.

151-162: Consider the cost and latency of the additional API call.

When tools exceed 20, this makes an extra LLM call to select tools before the actual generation. For high-traffic scenarios, consider:

  • Caching selection results for similar conversation contexts
  • Using a smaller/faster model for tool selection
  • Deterministic filtering based on conversation keywords

This is acceptable for now but worth monitoring.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/llm/providers/google.ts` around lines 151 - 162, The current
tool-selection flow triggers an extra LLM call via ai.models.generateContent
(using normalizeModelId and toGeminiMessages) when tools > 20, which can
increase cost/latency; mitigate by adding a selection cache keyed by
conversation context/signature to avoid repeated generateContent calls for
similar contexts, optionally route selection to a configurable smaller/faster
model (expose a separate selectionModel config used before calling
normalizeModelId) or implement a deterministic pre-filter (keyword-based filter)
to reduce candidates before invoking ai.models.generateContent; update the code
paths around generateContent to consult the cache and selectionModel or run
deterministic filtering first, and ensure cache invalidation/TTL is
configurable.

164-166: Consider using structured logging instead of console.log.

Per coding guidelines, prefer the existing structured logging pattern and minimize use of console.* in committed code.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/llm/providers/google.ts` around lines 164 - 166, Replace the
console.log call in server/llm/providers/google.ts with the project's structured
logger (e.g., processLogger.info or logger.info) and emit the same message as
both a human-readable string and structured fields: include
MAX_FUNCTION_CALLINGS as maxFunctionCallings and the tools used (indices.map(i
=> tools[i].name)) as usedTools (array). Locate the console.log invocation that
references MAX_FUNCTION_CALLINGS, indices, and tools and swap it for a
structured log entry that passes the message and the two structured fields.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@server/llm/providers/google.ts`:
- Around line 141-143: The current construction of toolList builds JSON by
interpolating t.description directly, which can break when descriptions contain
quotes, backslashes or newlines; change the mapping to safely escape
descriptions by using JSON.stringify for the description (or better, build
actual objects { index: i, description: t.description } and call JSON.stringify
on the array) so that toolList is valid JSON; update the code around the
tools.map(...) that creates toolList to use JSON.stringify accordingly.
- Around line 163-166: The LLM response parsing is unsafe: when setting indices
from response.text you must wrap JSON.parse in a try/catch and validate the
parsed value is an array of valid integer indices within 0..tools.length-1 (and
optionally dedupe and limit to MAX_FUNCTION_CALLINGS); on parse error or invalid
items fall back to an empty array and log the error with context (use
console.error or the module logger) so the subsequent console.log/indices.map
won't access undefined tools entries; update the code around
response.text/indices and the console.log that maps indices to tools to use the
validated indices.

---

Nitpick comments:
In `@server/llm/providers/google.ts`:
- Around line 213-222: getFunctionCallingConfig(...) always returns an object so
the current if (ret) is redundant; update the conditional to verify there are
actual function declarations (e.g., check ret.functionDeclarations &&
ret.functionDeclarations.length > 0) before setting config.tools and
config.toolConfig, or remove the if and always assign if you intend to apply an
empty config; reference getFunctionCallingConfig, ret, config.tools,
config.toolConfig and FunctionCallingConfigMode.ANY when making the change.
- Around line 151-162: The current tool-selection flow triggers an extra LLM
call via ai.models.generateContent (using normalizeModelId and toGeminiMessages)
when tools > 20, which can increase cost/latency; mitigate by adding a selection
cache keyed by conversation context/signature to avoid repeated generateContent
calls for similar contexts, optionally route selection to a configurable
smaller/faster model (expose a separate selectionModel config used before
calling normalizeModelId) or implement a deterministic pre-filter (keyword-based
filter) to reduce candidates before invoking ai.models.generateContent; update
the code paths around generateContent to consult the cache and selectionModel or
run deterministic filtering first, and ensure cache invalidation/TTL is
configurable.
- Around line 164-166: Replace the console.log call in
server/llm/providers/google.ts with the project's structured logger (e.g.,
processLogger.info or logger.info) and emit the same message as both a
human-readable string and structured fields: include MAX_FUNCTION_CALLINGS as
maxFunctionCallings and the tools used (indices.map(i => tools[i].name)) as
usedTools (array). Locate the console.log invocation that references
MAX_FUNCTION_CALLINGS, indices, and tools and swap it for a structured log entry
that passes the message and the two structured fields.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a4901bb and 73e2a1e.

📒 Files selected for processing (1)
  • server/llm/providers/google.ts

Comment on lines +163 to +166
indices = response.text === undefined ? [] : JSON.parse(response.text);
console.log(
`Gemini recommends using ${MAX_FUNCTION_CALLINGS} or fewer function callings. We use only ${indices.map((i) => tools[i].name)}.`,
);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add error handling for LLM response parsing and validate returned indices.

The LLM may return invalid JSON or out-of-bounds indices. Missing validation could cause runtime crashes or accessing undefined tool entries.

🛡️ Proposed fix with validation
-    indices = response.text === undefined ? [] : JSON.parse(response.text);
-    console.log(
-      `Gemini recommends using ${MAX_FUNCTION_CALLINGS} or fewer function callings. We use only ${indices.map((i) => tools[i].name)}.`,
-    );
+    try {
+      const parsed = response.text === undefined ? [] : JSON.parse(response.text);
+      // Validate indices: must be numbers within bounds, deduplicated, and limited to max
+      indices = [...new Set(parsed)]
+        .filter((i): i is number => typeof i === "number" && i >= 0 && i < tools.length)
+        .slice(0, MAX_FUNCTION_CALLINGS);
+    } catch {
+      // Fallback to first MAX_FUNCTION_CALLINGS tools if parsing fails
+      indices = tools.slice(0, MAX_FUNCTION_CALLINGS).map((_, i) => i);
+    }
+    console.log(
+      `Gemini recommends using ${MAX_FUNCTION_CALLINGS} or fewer function callings. We use only ${indices.map((i) => tools[i].name)}.`,
+    );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
indices = response.text === undefined ? [] : JSON.parse(response.text);
console.log(
`Gemini recommends using ${MAX_FUNCTION_CALLINGS} or fewer function callings. We use only ${indices.map((i) => tools[i].name)}.`,
);
try {
const parsed = response.text === undefined ? [] : JSON.parse(response.text);
// Validate indices: must be numbers within bounds, deduplicated, and limited to max
indices = [...new Set(parsed)]
.filter((i): i is number => typeof i === "number" && i >= 0 && i < tools.length)
.slice(0, MAX_FUNCTION_CALLINGS);
} catch {
// Fallback to first MAX_FUNCTION_CALLINGS tools if parsing fails
indices = tools.slice(0, MAX_FUNCTION_CALLINGS).map((_, i) => i);
}
console.log(
`Gemini recommends using ${MAX_FUNCTION_CALLINGS} or fewer function callings. We use only ${indices.map((i) => tools[i].name)}.`,
);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/llm/providers/google.ts` around lines 163 - 166, The LLM response
parsing is unsafe: when setting indices from response.text you must wrap
JSON.parse in a try/catch and validate the parsed value is an array of valid
integer indices within 0..tools.length-1 (and optionally dedupe and limit to
MAX_FUNCTION_CALLINGS); on parse error or invalid items fall back to an empty
array and log the error with context (use console.error or the module logger) so
the subsequent console.log/indices.map won't access undefined tools entries;
update the code around response.text/indices and the console.log that maps
indices to tools to use the validated indices.

masap added 2 commits March 1, 2026 10:50
Signed-off-by: Masashi Honma <masashi.honma@gmail.com>
…ices

Signed-off-by: Masashi Honma <masashi.honma@gmail.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
server/llm/providers/google.ts (1)

166-175: ⚠️ Potential issue | 🟠 Major

Require integer index validation before dereferencing tools.

At Line 172-174, decimals (e.g. 1.5) pass the filter. That can produce tools[i] === undefined, then break at Line 181/189/193 when accessing .name/.description/.parameters.

🔒 Proposed hardening
     try {
-      const parsed =
-        response.text === undefined ? [] : JSON.parse(response.text);
+      const parsed =
+        response.text === undefined ? [] : JSON.parse(response.text);
+      if (!Array.isArray(parsed)) {
+        throw new Error("Function-calling selector returned non-array JSON");
+      }
       // Validate indices: must be numbers within bounds, deduplicated, and limited to max
       indices = [...new Set(parsed)]
         .filter(
           (i): i is number =>
-            typeof i === "number" && i >= 0 && i < tools.length,
+            Number.isInteger(i) && i >= 0 && i < tools.length,
         )
         .slice(0, MAX_FUNCTION_CALLINGS);
     } catch {
       // Fallback to first MAX_FUNCTION_CALLINGS tools if parsing fails
       indices = tools.slice(0, MAX_FUNCTION_CALLINGS).map((_, i) => i);
     }
#!/bin/bash
# Verify the current predicate and dereference sites in this file.
rg -nP 'typeof i === "number" && i >= 0 && i < tools\.length|tools\[i\]\.(name|description|parameters)' server/llm/providers/google.ts

Also applies to: 181-193

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/llm/providers/google.ts` around lines 166 - 175, Parsed indices can
include non-integer numbers (e.g. 1.5) which pass the current typeof check and
later cause tools[i] to be undefined; update the filter predicate used when
creating indices (the expression that deduplicates and filters parsed into
indices for tools) to require integer indices (use Number.isInteger(i) or
equivalent) in addition to the existing bounds check and keep the slice(0,
MAX_FUNCTION_CALLINGS) behavior so only valid integer indices within [0,
tools.length) are included before any dereference of tools[i].
🧹 Nitpick comments (1)
server/llm/providers/google.ts (1)

180-182: Replace console.log with the project's structured logger.

Import logger from ../utils/logger and use logger.info() to align with the established structured logging pattern used throughout the server codebase, per the coding guideline: "Prefer the existing structured logging pattern and minimize use of console.* in committed code".

logger.info(
  `Gemini recommends using ${MAX_FUNCTION_CALLINGS} or fewer function callings. We use only ${indices.map((i) => tools[i].name)}.`,
);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/llm/providers/google.ts` around lines 180 - 182, Replace the
console.log call in the Gemini recommendation block with the project's
structured logger: import logger from ../utils/logger and change the call to
logger.info(...) using the same message string that references
MAX_FUNCTION_CALLINGS and the indices.map((i) => tools[i].name) expression;
update the file-level imports and ensure the replacement occurs where the
current console.log invocation exists in server/llm/providers/google.ts so the
code uses logger.info instead of console.log.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@server/llm/providers/google.ts`:
- Around line 154-165: The pre-filter selector call using
ai.models.generateContent (called with model: normalizeModelId(model) and
contents: toGeminiMessages(message)) must not abort the whole generation on
failure; wrap that generateContent call in a try/catch and on any error
(network/4xx/5xx) log the error and fallback to selecting the first 20 tools
instead of throwing; apply the same pattern to the other selector invocation
around the code referenced at the later block (the second generateContent call
at the 176-179 area), ensuring both use the same try/catch fallback to first 20
tools.
- Around line 141-146: The tool-list JSON entries are malformed due to an extra
closing brace in the string construction inside the tools.map used to build
toolList; update the mapping in the toolList construction (the tools.map
callback that references t and i and assigns to toolList) to remove the stray
"}" so each entry is valid JSON (e.g. produce
{"index":<i>,"description":<JSON.stringify(t.description)>} for each tool) and
keep the join logic unchanged.

---

Duplicate comments:
In `@server/llm/providers/google.ts`:
- Around line 166-175: Parsed indices can include non-integer numbers (e.g. 1.5)
which pass the current typeof check and later cause tools[i] to be undefined;
update the filter predicate used when creating indices (the expression that
deduplicates and filters parsed into indices for tools) to require integer
indices (use Number.isInteger(i) or equivalent) in addition to the existing
bounds check and keep the slice(0, MAX_FUNCTION_CALLINGS) behavior so only valid
integer indices within [0, tools.length) are included before any dereference of
tools[i].

---

Nitpick comments:
In `@server/llm/providers/google.ts`:
- Around line 180-182: Replace the console.log call in the Gemini recommendation
block with the project's structured logger: import logger from ../utils/logger
and change the call to logger.info(...) using the same message string that
references MAX_FUNCTION_CALLINGS and the indices.map((i) => tools[i].name)
expression; update the file-level imports and ensure the replacement occurs
where the current console.log invocation exists in
server/llm/providers/google.ts so the code uses logger.info instead of
console.log.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 73e2a1e and 22bfc31.

📒 Files selected for processing (1)
  • server/llm/providers/google.ts

Comment on lines +154 to +165
const response = await ai.models.generateContent({
model: normalizeModelId(model),
contents: toGeminiMessages(message),
config: {
...config,
responseMimeType: "application/json",
responseJsonSchema: {
type: "array",
items: { type: "integer" },
},
},
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Handle selector API failures with graceful fallback.

If the selector generateContent call fails (network/400/500), the whole generation aborts before the main request. For this pre-filter step, fallback to first 20 tools instead of failing hard.

🛡️ Suggested resilience pattern
-    const response = await ai.models.generateContent({
-      model: normalizeModelId(model),
-      contents: toGeminiMessages(message),
-      config: {
-        ...config,
-        responseMimeType: "application/json",
-        responseJsonSchema: {
-          type: "array",
-          items: { type: "integer" },
-        },
-      },
-    });
-    try {
+    try {
+      const response = await ai.models.generateContent({
+        model: normalizeModelId(model),
+        contents: toGeminiMessages(message),
+        config: {
+          ...config,
+          responseMimeType: "application/json",
+          responseJsonSchema: {
+            type: "array",
+            items: { type: "integer" },
+          },
+        },
+      });
       const parsed =
         response.text === undefined ? [] : JSON.parse(response.text);
@@
-    } catch {
-      // Fallback to first MAX_FUNCTION_CALLINGS tools if parsing fails
+    } catch {
+      // Fallback if selector call or parsing fails
       indices = tools.slice(0, MAX_FUNCTION_CALLINGS).map((_, i) => i);
     }

Also applies to: 176-179

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/llm/providers/google.ts` around lines 154 - 165, The pre-filter
selector call using ai.models.generateContent (called with model:
normalizeModelId(model) and contents: toGeminiMessages(message)) must not abort
the whole generation on failure; wrap that generateContent call in a try/catch
and on any error (network/4xx/5xx) log the error and fallback to selecting the
first 20 tools instead of throwing; apply the same pattern to the other selector
invocation around the code referenced at the later block (the second
generateContent call at the 176-179 area), ensuring both use the same try/catch
fallback to first 20 tools.

masap added 2 commits March 1, 2026 12:29
Signed-off-by: Masashi Honma <masashi.honma@gmail.com>
Signed-off-by: Masashi Honma <masashi.honma@gmail.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
server/llm/providers/google.ts (1)

170-175: ⚠️ Potential issue | 🟠 Major

Enforce integer indices before indexing tools.

typeof i === "number" also accepts floats. A value like 1.5 passes this filter, then tools[i] is undefined and can fail later at Line 190.

🔧 Proposed fix
-      indices = [...new Set(parsed)]
-        .filter(
-          (i): i is number =>
-            typeof i === "number" && i >= 0 && i < tools.length,
-        )
-        .slice(0, MAX_FUNCTION_CALLINGS);
+      indices = [...new Set(parsed)]
+        .filter(
+          (i): i is number =>
+            Number.isInteger(i) && i >= 0 && i < tools.length,
+        )
+        .slice(0, MAX_FUNCTION_CALLINGS);
#!/bin/bash
# Verify current selector guard accepts all numbers (including floats)
rg -nP 'typeof i === "number"\s*&&\s*i >= 0\s*&&\s*i < tools.length' server/llm/providers/google.ts
# Verify downstream dereference of tools[i]
rg -nP 'tools\[i\]\.(name|description|parameters)' server/llm/providers/google.ts
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/llm/providers/google.ts` around lines 170 - 175, The indices filter
currently allows non-integer numbers (e.g., 1.5) because it only checks typeof i
=== "number"; update the validation in the block that assigns indices (the
parsed -> indices dedupe/filter logic) to also require integer indices (use
Number.isInteger(i)) and keep existing bounds and type checks so only integers 0
<= i < tools.length survive before any dereference of tools[i]; ensure you
modify the filter predicate that currently reads (i): i is number => typeof i
=== "number" && i >= 0 && i < tools.length to include a Number.isInteger(i)
guard.
🧹 Nitpick comments (1)
server/llm/providers/google.ts (1)

181-183: Use the structured logger instead of console.log.

Please route this through the project logger to keep server-side logging consistent.

As per coding guidelines: "Prefer the existing structured logging pattern and minimize use of console.* in committed code".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/llm/providers/google.ts` around lines 181 - 183, Replace the
console.log call that prints Gemini recommendation and used tool names with the
project's structured logger (e.g., logger.info or serverLogger.info). Locate the
statement that references MAX_FUNCTION_CALLINGS and indices.map((i) =>
tools[i].name) and emit a structured log containing a clear message plus fields
like { maxFunctionCallings: MAX_FUNCTION_CALLINGS, usedTools: indices.map(i =>
tools[i].name) }. Also ensure the appropriate logger is imported/available in
this module and remove the console.log usage.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@server/llm/providers/google.ts`:
- Around line 170-175: The indices filter currently allows non-integer numbers
(e.g., 1.5) because it only checks typeof i === "number"; update the validation
in the block that assigns indices (the parsed -> indices dedupe/filter logic) to
also require integer indices (use Number.isInteger(i)) and keep existing bounds
and type checks so only integers 0 <= i < tools.length survive before any
dereference of tools[i]; ensure you modify the filter predicate that currently
reads (i): i is number => typeof i === "number" && i >= 0 && i < tools.length to
include a Number.isInteger(i) guard.

---

Nitpick comments:
In `@server/llm/providers/google.ts`:
- Around line 181-183: Replace the console.log call that prints Gemini
recommendation and used tool names with the project's structured logger (e.g.,
logger.info or serverLogger.info). Locate the statement that references
MAX_FUNCTION_CALLINGS and indices.map((i) => tools[i].name) and emit a
structured log containing a clear message plus fields like {
maxFunctionCallings: MAX_FUNCTION_CALLINGS, usedTools: indices.map(i =>
tools[i].name) }. Also ensure the appropriate logger is imported/available in
this module and remove the console.log usage.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 22bfc31 and 8d92917.

📒 Files selected for processing (1)
  • server/llm/providers/google.ts

@snakajima
Copy link
Copy Markdown
Contributor

Addressing this issue with #144

@snakajima snakajima closed this Mar 22, 2026
@masap masap deleted the fix-123 branch March 23, 2026 04:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improve Gemini API error handling and user feedback

2 participants