Skip to content

Fixed tool config and removed tool combination setter#81

Open
aubrypaul wants to merge 4 commits into
mainfrom
tool-combination-fix
Open

Fixed tool config and removed tool combination setter#81
aubrypaul wants to merge 4 commits into
mainfrom
tool-combination-fix

Conversation

@aubrypaul

Copy link
Copy Markdown
Contributor

No description provided.

@coderabbitai

coderabbitai Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • Breaking Changes

    • Removed the public runtime toggle for server-side tool invocation; callers can no longer enable/disable this behavior at runtime.
  • Improvements

    • Tool-related settings are now included only when user-defined tools are present, reducing unnecessary payload data.
    • When tools are present, function-calling defaults to automatic behavior and browsing tools are appended when browsing is enabled; server-side invocation flags apply only when relevant.

Walkthrough

Removes the Chat class's tool_combination_enabled state and public enableToolCombination() method; refactors _buildGeminiPayload() to initialize only base fields and to add function-calling tool_config, function declarations, and set includeServerSideToolInvocations only when user tools exist; browsing tools are still appended when browsing is enabled.

Changes

Gemini Tool Configuration Refactoring

Layer / File(s) Summary
Remove tool combination public API and state
src/code.gs
Removed the tool_combination_enabled instance variable from the constructor and the public enableToolCombination(enabled) method that previously controlled Gemini server-side tool invocation behavior.
Refactor Gemini payload generation
src/code.gs
_buildGeminiPayload() now initializes base fields (contents, model, generationConfig) unconditionally; tool_config.function_calling_config, function declarations (payload.tools), and tool_config.includeServerSideToolInvocations are created only when tools.length > 0. advancedParametersObject.function_call overrides are applied only inside that guarded path. When browsing is enabled, url_context and google_search are appended unconditionally, but the server-side invocation flag is set only if user tools exist.

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive No pull request description was provided by the author, making it impossible to evaluate whether the description is related to the changeset. Add a pull request description explaining the rationale behind removing the tool combination setter and the tool configuration changes.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main changes: removing the tool combination setter method and fixing tool configuration logic in the Gemini payload builder.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch tool-combination-fix
  • 🛠️ JSDoc Checks

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/code.gs`:
- Around line 317-322: The method enableCodeInterpreter is missing its closing
brace and the fluent return; fix the function by adding the terminating "};" and
a "return this;" before the closing so the method sets
this._codeInterpreterEnabled = true, optionally assigns
this._codeInterpreterContainerId when containerId is provided, and then returns
this to maintain chaining (refer to enableCodeInterpreter,
_codeInterpreterEnabled, and _codeInterpreterContainerId to locate the code).
- Around line 879-884: The bug is that the string branch can overwrite a prior
numeric/zero-index match when fileIdOrIndex is an empty string; in the method
that sets targetFile (references: variable targetFile, parameter fileIdOrIndex,
and array this._generatedFiles), change the second conditional from `if (typeof
fileIdOrIndex === "string")` to `else if (typeof fileIdOrIndex === "string")`
(or otherwise short-circuit after the numeric branch) so that a numeric/zero
path doesn't fall through and get clobbered by the string find() for an empty
string.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: b7c517f5-1d35-4bfc-8a69-3d41406c4d28

📥 Commits

Reviewing files that changed from the base of the PR and between 31b0d21 and 6cc6838.

📒 Files selected for processing (1)
  • src/code.gs
📜 Review details
🔇 Additional comments (9)
src/code.gs (9)

55-59: LGTM!


453-455: LGTM!


539-549: LGTM!


640-642: LGTM!

Also applies to: 659-661


773-790: LGTM!


794-847: LGTM!

Also applies to: 853-855, 891-896


910-954: LGTM!


1561-1561: LGTM!

Also applies to: 1591-1598, 1622-1624


956-972: src/code.gs:956-972 — Missing includeServerSideToolInvocations is OK for browsing-only
Gemini’s includeServerSideToolInvocations is required when combining built-in tools (like google_search / url_context) with custom function calling in the same request. In the browsing-only path here, payload.tools adds only the built-in browsing tools and tool_config is intentionally left unset, so this should not prevent google_search / url_context from working.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/code.gs`:
- Around line 317-322: The method enableCodeInterpreter is missing its closing
brace and the fluent return; fix the function by adding the terminating "};" and
a "return this;" before the closing so the method sets
this._codeInterpreterEnabled = true, optionally assigns
this._codeInterpreterContainerId when containerId is provided, and then returns
this to maintain chaining (refer to enableCodeInterpreter,
_codeInterpreterEnabled, and _codeInterpreterContainerId to locate the code).
- Around line 879-884: The bug is that the string branch can overwrite a prior
numeric/zero-index match when fileIdOrIndex is an empty string; in the method
that sets targetFile (references: variable targetFile, parameter fileIdOrIndex,
and array this._generatedFiles), change the second conditional from `if (typeof
fileIdOrIndex === "string")` to `else if (typeof fileIdOrIndex === "string")`
(or otherwise short-circuit after the numeric branch) so that a numeric/zero
path doesn't fall through and get clobbered by the string find() for an empty
string.
🪄 Autofix (Beta)

❌ Autofix failed (check again to retry)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: b7c517f5-1d35-4bfc-8a69-3d41406c4d28

📥 Commits

Reviewing files that changed from the base of the PR and between 31b0d21 and 6cc6838.

📒 Files selected for processing (1)
  • src/code.gs
📜 Review details
🔇 Additional comments (9)
src/code.gs (9)

55-59: LGTM!


453-455: LGTM!


539-549: LGTM!


640-642: LGTM!

Also applies to: 659-661


773-790: LGTM!


794-847: LGTM!

Also applies to: 853-855, 891-896


910-954: LGTM!


1561-1561: LGTM!

Also applies to: 1591-1598, 1622-1624


956-972: src/code.gs:956-972 — Missing includeServerSideToolInvocations is OK for browsing-only
Gemini’s includeServerSideToolInvocations is required when combining built-in tools (like google_search / url_context) with custom function calling in the same request. In the browsing-only path here, payload.tools adds only the built-in browsing tools and tool_config is intentionally left unset, so this should not prevent google_search / url_context from working.

🛑 Comments failed to post (2)
src/code.gs (2)

317-322: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Critical: enableCodeInterpreter is missing closing brace and return statement.

The function definition is incomplete—it lacks return this; for method chaining (consistent with all other fluent methods) and the closing };. This will cause a JavaScript syntax error at parse time, breaking the entire library.

🐛 Proposed fix
       this.enableCodeInterpreter = function (containerId) {
         this._codeInterpreterEnabled = true;
         if (containerId) {
           this._codeInterpreterContainerId = containerId;
         }
+        return this;
+      };

       /**
        * Includes the content of a web page in the prompt sent to openAI
📝 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.

      this.enableCodeInterpreter = function (containerId) {
        this._codeInterpreterEnabled = true;
        if (containerId) {
          this._codeInterpreterContainerId = containerId;
        }
        return this;
      };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/code.gs` around lines 317 - 322, The method enableCodeInterpreter is
missing its closing brace and the fluent return; fix the function by adding the
terminating "};" and a "return this;" before the closing so the method sets
this._codeInterpreterEnabled = true, optionally assigns
this._codeInterpreterContainerId when containerId is provided, and then returns
this to maintain chaining (refer to enableCodeInterpreter,
_codeInterpreterEnabled, and _codeInterpreterContainerId to locate the code).

879-884: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Logic error: missing else causes empty string handling to break.

When fileIdOrIndex is an empty string "", lines 876-877 correctly set targetFile = this._generatedFiles[0]. However, line 879 uses if instead of else if, so execution falls through to line 882 where typeof "" === "string" is true, overwriting targetFile with find() (which returns undefined for empty string).

🐛 Proposed fix
       else if (typeof fileIdOrIndex === "string" && fileIdOrIndex.trim() === "") {
         targetFile = this._generatedFiles[0];
       }
-      if (typeof fileIdOrIndex === "number") {
+      else if (typeof fileIdOrIndex === "number") {
         targetFile = this._generatedFiles[fileIdOrIndex];
       }
       else if (typeof fileIdOrIndex === "string") {
📝 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.

        else if (typeof fileIdOrIndex === "number") {
          targetFile = this._generatedFiles[fileIdOrIndex];
        }
        else if (typeof fileIdOrIndex === "string") {
          targetFile = this._generatedFiles.find(file => file.fileId === fileIdOrIndex);
        }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/code.gs` around lines 879 - 884, The bug is that the string branch can
overwrite a prior numeric/zero-index match when fileIdOrIndex is an empty
string; in the method that sets targetFile (references: variable targetFile,
parameter fileIdOrIndex, and array this._generatedFiles), change the second
conditional from `if (typeof fileIdOrIndex === "string")` to `else if (typeof
fileIdOrIndex === "string")` (or otherwise short-circuit after the numeric
branch) so that a numeric/zero path doesn't fall through and get clobbered by
the string find() for an empty string.

@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Note

Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.

Autofix skipped. No unresolved CodeRabbit review comments with fix instructions found.

@aubrypaul

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Note

Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.

Autofix skipped. No unresolved CodeRabbit review comments with fix instructions found.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/code.gs (2)

949-955: ⚠️ Potential issue | 🟠 Major

Fix Gemini function_calling_config.allowed_function_names type

In src/code.gs lines 949-955, allowed_function_names is assigned advancedParametersObject.function_call (a string per README/JSDoc), but Gemini expects a list/array of function names for allowed_function_names (used with mode "ANY"). Normalize single values to a one-element array before assigning.

Suggested fix
           if (advancedParametersObject?.function_call) {
+            const allowedFunctionNames = Array.isArray(advancedParametersObject.function_call)
+              ? advancedParametersObject.function_call
+              : [advancedParametersObject.function_call];
+
             payload.tool_config.function_calling_config.mode = "ANY";
             payload.tool_config.function_calling_config.allowed_function_names =
-              advancedParametersObject.function_call;
+              allowedFunctionNames;
 
             delete advancedParametersObject.function_call;
           }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/code.gs` around lines 949 - 955, The code assigns
advancedParametersObject.function_call (documented as a string) directly to
payload.tool_config.function_calling_config.allowed_function_names, but Gemini
expects an array; update the assignment in the block handling
advancedParametersObject?.function_call so that if
advancedParametersObject.function_call is a string you wrap it into a
one-element array, and if it is already an array you assign it as-is; keep the
rest of the logic (setting mode to "ANY" and deleting
advancedParametersObject.function_call) unchanged and reference
payload.tool_config.function_calling_config.allowed_function_names and
advancedParametersObject.function_call when making the change.

958-973: ⚠️ Potential issue | 🟠 Major

Guard includeServerSideToolInvocations for Gemini 2.5 when combining browsing + function calling.

In src/code.gs (_buildGeminiPayload), when browsing is enabled and tools.length > 0, the code always injects Gemini built-in browsing tools (url_context, google_search) and unconditionally sets payload.tool_config.includeServerSideToolInvocations = true. Google documents this built-in+custom tool “tool context circulation” path as a Gemini 3 capability, so this should be rejected/disabled for gemini-2.5-* models to avoid unsupported requests. https://ai.google.dev/gemini-api/docs/tool-combination

Suggested guard
         if (browsing) {
+          const isGemini3Model = model.startsWith("gemini-3");
+          if (tools.length > 0 && !isGemini3Model) {
+            throw new Error("[GenAIApp] - Combining Gemini browsing with function calling is only supported on Gemini 3 models.");
+          }
+
           if (tools.length > 0) {
             payload.tool_config.includeServerSideToolInvocations = true;
           }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/code.gs` around lines 958 - 973, When building Gemini payload in
_buildGeminiPayload, the code unconditionally sets
payload.tool_config.includeServerSideToolInvocations = true and injects built-in
browsing tools when browsing && tools.length > 0; guard this behavior for
gemini-2.5 models by checking the model identifier (e.g., model or modelName)
and skip setting includeServerSideToolInvocations and injecting the built-in
url_context/google_search tools when the model string matches "gemini-2.5-*" (or
otherwise indicates 2.5); only enable includeServerSideToolInvocations and push
those built-in tools for models that support tool-combination (non-2.5). Ensure
you reference the existing symbols browsing, tools, payload, and
payload.tool_config.includeServerSideToolInvocations in the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/code.gs`:
- Around line 949-955: The code assigns advancedParametersObject.function_call
(documented as a string) directly to
payload.tool_config.function_calling_config.allowed_function_names, but Gemini
expects an array; update the assignment in the block handling
advancedParametersObject?.function_call so that if
advancedParametersObject.function_call is a string you wrap it into a
one-element array, and if it is already an array you assign it as-is; keep the
rest of the logic (setting mode to "ANY" and deleting
advancedParametersObject.function_call) unchanged and reference
payload.tool_config.function_calling_config.allowed_function_names and
advancedParametersObject.function_call when making the change.
- Around line 958-973: When building Gemini payload in _buildGeminiPayload, the
code unconditionally sets payload.tool_config.includeServerSideToolInvocations =
true and injects built-in browsing tools when browsing && tools.length > 0;
guard this behavior for gemini-2.5 models by checking the model identifier
(e.g., model or modelName) and skip setting includeServerSideToolInvocations and
injecting the built-in url_context/google_search tools when the model string
matches "gemini-2.5-*" (or otherwise indicates 2.5); only enable
includeServerSideToolInvocations and push those built-in tools for models that
support tool-combination (non-2.5). Ensure you reference the existing symbols
browsing, tools, payload, and
payload.tool_config.includeServerSideToolInvocations in the change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 0b9ffb40-df9a-40b4-a7ba-e3472e7d4670

📥 Commits

Reviewing files that changed from the base of the PR and between ea8fc74 and d014d91.

📒 Files selected for processing (1)
  • src/code.gs
📜 Review details
🔇 Additional comments (1)
src/code.gs (1)

317-323: LGTM!

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.

1 participant