Migrate Gemini to Interactions API and add interaction threading#90
Migrate Gemini to Interactions API and add interaction threading#90Benjamin-Sayaque wants to merge 3 commits into
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📜 Recent review details🔇 Additional comments (25)
📝 WalkthroughSummary by CodeRabbit
WalkthroughThe PR migrates Gemini integration from the legacy ChangesGemini Interactions API migration
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches✨ Simplify code
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8c0eaf17c3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| parts.forEach(part => { | ||
| if (!part) return; | ||
| if (part.text) { | ||
| item.content.push({ type: "input_text", text: part.text }); |
There was a problem hiding this comment.
Send Gemini prompts as valid interaction content
When any Gemini chat contains a message added through addMessage, this helper sends OpenAI-shaped input items such as { role: "user", content: [{ type: "input_text", ... }] }. The Gemini Interactions API expects a string, Gemini content blocks such as type: "text", or step objects such as type: "user_input"; it has no input_text content type, so ordinary Gemini text turns are rejected before the model sees the prompt.
Useful? React with 👍 / 👎.
| max_output_tokens: max_tokens, | ||
| temperature: temperature, |
There was a problem hiding this comment.
Put Gemini generation settings under generation_config
Every Gemini Interactions request now puts max_output_tokens and temperature at the request root, but the Interactions API defines these only inside generation_config. With Gemini REST validation this makes chat.run({ model: "gemini...", max_tokens: ... }) send an invalid request rather than applying the caller's token and temperature settings.
Useful? React with 👍 / 👎.
| } | ||
| else { | ||
| endpointUrl = `https://${region}-aiplatform.googleapis.com/v1/projects/${gcpProjectId}/locations/${region}/publishers/google/models/${model}:generateContent`; | ||
| endpointUrl = `https://${region}-aiplatform.googleapis.com/v1beta1/projects/${gcpProjectId}/locations/${region}/interactions`; |
There was a problem hiding this comment.
Keep Vertex interaction paths on the global location
When callers use setGeminiAuth(project, "us-central1") with a non-Gemini-3 model, this branch posts to /locations/us-central1/interactions. The Vertex/Cloud Interactions create method is exposed as /projects/{project}/locations/global/interactions, so users with the normal regional Vertex configuration will get 404s unless they omit the region or happen to use a Gemini 3 model.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 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 983-985: The toolFunction.parameters.type assignment is converting
the type value to uppercase using .toUpperCase(), but the Gemini API expects
lowercase schema types like "object", "string", and "array". Remove the
.toUpperCase() method call from the line where toolFunction.parameters.type is
assigned so that the type value remains in its original lowercase format,
ensuring it matches the API's expected schema format.
- Around line 1848-1851: The `return` statement inside the `forEach` loop at the
`onlyArgs` check only skips the current iteration instead of exiting the entire
function. Replace the `forEach` loop with a traditional `for` loop so that when
`onlyArgs` is true and `onlyReturnArguments` is assigned, the function can use
`return` to exit immediately and stop processing remaining function calls,
similar to how the OpenAI handler at lines 1927-1933 handles early termination
with `return messages`.
- Around line 554-564: The Interactions API is only available through the Gemini
API and not yet supported on Vertex AI, so the Vertex AI endpoint branches
should be removed. Locate the else block that contains the comment "Enterprise
endpoint / Vertex AI API" and the conditions checking for region and gemini-3
model, then either remove this entire else block entirely, or replace it with an
error that explicitly states that Vertex AI is not supported for the
Interactions API. This ensures the code only uses the
generativelanguage.googleapis.com endpoint which is the only valid endpoint for
this API.
In `@src/testFunctions.gs`:
- Around line 195-208: The testGeminiInteractionThreading function verifies the
first interaction ID but fails to validate that threading actually succeeded on
the second turn. After calling chat.run() for the secondResponse, retrieve the
second interaction ID using chat.retrieveLastInteractionId() and assert that it
exists, then add an assertion to verify that the secondResponse actually
contains evidence of memory from the first turn (such as checking that the
response mentions the keyword "papaya" that was provided in the initial
message). This ensures the test will fail if continuation or threading is broken
rather than passing with incomplete validation.
- Around line 243-254: The testGeminiVertexInteractionThreading function is
named to indicate multi-turn conversation testing but only executes a single
message-response cycle. To properly test threading, add a second message to the
chat object using addMessage, execute another run call to get a follow-up
response, retrieve the new interaction ID using retrieveLastInteractionId, and
validate that the interaction progression is working correctly (such as
verifying the new interaction ID is different from or properly related to the
first one). This will ensure the function actually tests the multi-turn nature
of the chat threading.
- Around line 223-241: The testGeminiFunctionCallingInteractionContinuation
function only performs an initial chat run but never executes a continuation
turn to test the full function-calling workflow. After calling chat.run() and
retrieving the interaction ID, the test needs to simulate the function execution
by calling a continuation method on the chat object (likely
chat.continueWithFunctionResult or similar) with a mock weather result, then run
the chat again to verify the continuation returns a proper response. This
ensures the interaction ID is properly maintained across the function-calling
round-trip and the chat correctly handles the continuation contract.
- Around line 18-20: The testAll() function is missing an invocation of the
Vertex interaction threading test. Add a call to
testGeminiVertexInteractionThreading() in the testAll() function alongside the
other Gemini test invocations (testGeminiInteractionThreading,
testGeminiRetrieveLastInteractionId, and
testGeminiFunctionCallingInteractionContinuation) to ensure the Vertex
interaction threading path is tested during full-suite runs.
🪄 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: 94b7f5b1-9960-4dc1-90a0-9493409db5d6
📒 Files selected for processing (2)
src/code.gssrc/testFunctions.gs
📜 Review details
🔇 Additional comments (9)
src/code.gs (9)
66-69: LGTM!
373-379: LGTM!
402-411: LGTM!
457-470: LGTM!
588-596: LGTM!
628-649: LGTM!
693-693: LGTM!
1659-1663: LGTM!
1738-1811: LGTM!
| endpointUrl = `https://generativelanguage.googleapis.com/v1beta/interactions`; | ||
| } | ||
| else { | ||
| // Enterprise endpoint / Vertex AI API | ||
| // https://console.cloud.google.com/apis/api/aiplatform.googleapis.com | ||
| // requires scope "https://www.googleapis.com/auth/cloud-platform.read-only" in access token | ||
| if (!region || model.includes("gemini-3")) { // Gemini 3 requires global endpoint when using Vertex AI API | ||
| endpointUrl = `https://aiplatform.googleapis.com/v1/projects/${gcpProjectId}/locations/global/publishers/google/models/${model}:generateContent`; | ||
| endpointUrl = `https://aiplatform.googleapis.com/v1beta1/projects/${gcpProjectId}/locations/global/interactions`; | ||
| } | ||
| else { | ||
| endpointUrl = `https://${region}-aiplatform.googleapis.com/v1/projects/${gcpProjectId}/locations/${region}/publishers/google/models/${model}:generateContent`; | ||
| endpointUrl = `https://${region}-aiplatform.googleapis.com/v1beta1/projects/${gcpProjectId}/locations/${region}/interactions`; |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Gemini Interactions API endpoint URL v1beta 2026
💡 Result:
As of June 2026, the Gemini Interactions API utilizes the v1beta version of the Generative Language API [1]. The base service endpoint for these requests is: https://generativelanguage.googleapis.com/v1beta/interactions [1] Key operations available at this endpoint include: * Creating an interaction: POST https://generativelanguage.googleapis.com/v1beta/interactions [1] * Retrieving an interaction: GET https://generativelanguage.googleapis.com/v1beta/interactions/{id} [1] * Canceling an interaction: POST https://generativelanguage.googleapis.com/v1beta/interactions/{id}/cancel [1] * Deleting an interaction: DELETE https://generativelanguage.googleapis.com/v1beta/interactions/{id} [1] The Interactions API is currently in a Beta/preview stage [2][3]. It is designed to support server-side state management, agentic workflows, and complex multi-turn conversations [2]. Because it is in an early development phase, it is subject to breaking changes, and the standard generateContent API is recommended for stable production workloads [2].
Citations:
- 1: https://ai.google.dev/api/interactions-api
- 2: https://ai.google.dev/gemini-api/docs/interactions/interactions-overview
- 3: https://ai.google.dev/gemini-api/docs/changelog
🌐 Web query:
Vertex AI Interactions API endpoint URL aiplatform.googleapis.com v1beta1 2026
💡 Result:
As of June 22, 2026, the Interactions API is available within the Gemini Enterprise Agent Platform (often integrated under or alongside Vertex AI services) [1]. While earlier reports indicated it was limited to the Gemini API endpoint [2], documentation now explicitly lists the endpoint for the Interactions API under the aiplatform.googleapis.com service [1]. The base URL for the Interactions API is: https://aiplatform.googleapis.com/v1beta1/projects/{project}/locations/global/interactions [1] Key details include: - Scope: It is currently part of the Gemini Enterprise Agent Platform, which is accessed via the aiplatform.googleapis.com service [3][1]. - Version: The v1beta1 version is used for these interactions [1]. - Status: The API is in public beta and is subject to potential breaking changes [4][5]. For stable production workloads, the standard generateContent API remains the recommended service [4][5]. Developers should use the aiplatform.googleapis.com endpoint when configuring clients for this service, ensuring they specify the correct project and location pathing as required by the API structure [1].
Citations:
- 1: https://docs.cloud.google.com/gemini-enterprise-agent-platform/reference/models/interactions-api
- 2: https://discuss.ai.google.dev/t/is-interactions-api-available-in-vertexai/114356/7
- 3: https://cloud.google.com/vertex-ai/docs/reference/rest
- 4: https://ai.google.dev/gemini-api/docs/interactions/interactions-overview
- 5: https://blog.google/innovation-and-ai/technology/developers-tools/interactions-api/
🌐 Web query:
Vertex AI Interactions API regional endpoints locations gemini-3 models 2026
💡 Result:
As of June 22, 2026, the status of the Interactions API and Gemini 3 models on Vertex AI is as follows: Interactions API: This API is currently only available through the Gemini API (Google AI for Developers) at the endpoint https://generativelanguage.googleapis.com/v1beta/interactions [1][2][3]. It is not yet available as a native feature within Vertex AI, though it is on the product roadmap [3]. Gemini 3 Models on Vertex AI: Gemini 3 models (including variants like gemini-3-pro-preview and gemini-3.5-flash) are available on Vertex AI primarily through a global endpoint [4][5]. While Vertex AI supports various regional endpoints for other services, users have reported that many regional endpoints do not currently support Gemini 3 models, often returning errors such as 404 NOT_FOUND or 400 FAILED_PRECONDITION when attempted [4][5][6]. Developers requiring data residency or specific latency optimization are often restricted to the global endpoint or specific, limited regional access, which may require allowlisting for production projects [4][5]. For the most up-to-date information on supported regional endpoints for specific models, you should consult the official Google Cloud model endpoint locations table in the Gemini Enterprise Agent Platform documentation, which distinguishes between global and regional availability [4][7].
Citations:
- 1: https://ai.google.dev/api/interactions-api
- 2: https://ai.google.dev/gemini-api/docs/interactions/interactions-overview
- 3: https://discuss.ai.google.dev/t/is-interactions-api-available-in-vertexai/114356/7
- 4: https://docs.cloud.google.com/gemini-enterprise-agent-platform/resources/locations
- 5: https://discuss.ai.google.dev/t/request-for-regional-access-to-gemini-3-preview-models-in-vertex-ai/144515
- 6: https://discuss.ai.google.dev/t/vertex-ai-gemini-3-1-availability-in-europe/169430
- 7: https://cloud.google.com/vertex-ai/docs/general/googleapi-access-methods
Remove Vertex AI endpoints for Interactions API—currently unavailable on Vertex AI.
The Interactions API is only available through the Gemini API (generativelanguage.googleapis.com) and is not yet available as a native feature on Vertex AI, despite being on the product roadmap. The code should not implement Vertex AI endpoints (lines 561, 564) for this API. Remove the entire Vertex AI branch or raise an error if Vertex AI is selected.
🤖 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 554 - 564, The Interactions API is only available
through the Gemini API and not yet supported on Vertex AI, so the Vertex AI
endpoint branches should be removed. Locate the else block that contains the
comment "Enterprise endpoint / Vertex AI API" and the conditions checking for
region and gemini-3 model, then either remove this entire else block entirely,
or replace it with an error that explicitly states that Vertex AI is not
supported for the Interactions API. This ensures the code only uses the
generativelanguage.googleapis.com endpoint which is the only valid endpoint for
this API.
| if (parameters?.type) { | ||
| toolFunction.parameters.type = parameters.type.toUpperCase(); | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Gemini Interactions API function parameters schema type case
💡 Result:
In the Gemini API, function parameter schema definitions follow a subset of the OpenAPI 3.0 specification [1][2][3]. Regarding the casing of types and parameter names, the following rules apply: Parameter Names: Parameter names are case-sensitive [4][5][6]. It is recommended to use snake_case or camelCase consistently throughout your schema to ensure the model correctly maps arguments [1][2]. Type Values: While JSON Schema technically supports lowercase types (e.g., "string", "integer", "object", "array") [1][2][7], certain Google Cloud and Vertex AI documentation references indicate that uppercase types (e.g., "STRING", "INTEGER", "OBJECT", "ARRAY") are also accepted or sometimes utilized in their internal representations [3][8][9]. However, official developer documentation for the Gemini API (ai.google.dev) predominantly uses lowercase types [1][2][7]. When defining your parameters object, you must specify the type of the overall container (typically "object") and then define the properties within it, where each property also requires a type definition [1][2][4]. Example structure: { "type": "object", "properties": { "parameter_name": { "type": "string", "description": "Description of the parameter" } }, "required": ["parameter_name"] } Best Practice: Stick to lowercase types (e.g., "string", "number", "integer", "boolean", "array", "object") as shown in the primary ai.google.dev documentation [1][2], and ensure your parameter names are consistent, descriptive, and case-sensitive [4][5].
Citations:
- 1: https://ai.google.dev/gemini-api/docs/interactions/function-calling
- 2: https://ai.google.dev/gemini-api/docs/function-calling
- 3: https://docs.cloud.google.com/gemini-enterprise-agent-platform/reference/models/function-calling
- 4: https://cloud.google.com/vertex-ai/generative-ai/docs/reference/rest/v1beta1/FunctionDeclaration
- 5: https://googleapis.github.io/js-genai/release_docs/interfaces/types.FunctionDeclaration.html
- 6: https://github.com/google-gemini/generative-ai-js/blob/main/docs/reference/main/generative-ai.functiondeclaration.parameters.md
- 7: https://theneuralbase.com/gemini-api/learn/intermediate/function-declaration-schema-definition/
- 8: https://discuss.ai.google.dev/t/schema-used-in-functioncalling-and-responseschema-diverges/69272
- 9: https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/function-calling
Remove toUpperCase() call—Gemini API expects lowercase schema types.
Line 984 uppercases the type field (parameters.type.toUpperCase()), but the official Gemini API documentation uses and expects lowercase types (e.g., "object", "string", "array"). This conversion may cause schema validation failures. Remove the toUpperCase() call to ensure types match the API's expected format.
🤖 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 983 - 985, The toolFunction.parameters.type
assignment is converting the type value to uppercase using .toUpperCase(), but
the Gemini API expects lowercase schema types like "object", "string", and
"array". Remove the .toUpperCase() method call from the line where
toolFunction.parameters.type is assigned so that the type value remains in its
original lowercase format, ensuring it matches the API's expected schema format.
| if (onlyArgs) { | ||
| onlyReturnArguments = functionArgs; | ||
| return; | ||
| } |
There was a problem hiding this comment.
onlyArgs early exit doesn't terminate processing of other function calls.
Using return inside forEach only skips to the next iteration—it doesn't exit the function. If multiple function calls are returned by Gemini and one has onlyArgs=true, the loop continues processing (and executing) the remaining functions before returning.
Compare with the OpenAI handler (lines 1927-1933) which uses return messages to exit immediately.
🐛 Proposed fix using a for-loop with early return
function _handleGeminiToolCalls(responseMessage, tools, contents) {
const functionCalls = _extractGeminiFunctionCalls(responseMessage);
const functionResults = [];
let shouldEndWithResult = false;
let onlyReturnArguments = null;
- functionCalls.forEach(functionCall => {
+ for (const functionCall of functionCalls) {
const functionName = functionCall.name;
const functionArgs = functionCall.args || {};
- if (!functionName) return;
+ if (!functionName) continue;
let argsOrder = [];
let endWithResult = false;
let onlyArgs = false;
for (const t in tools) {
const currentFunction = tools[t].function._toJson();
if (currentFunction.name == functionName) {
argsOrder = currentFunction.argumentsInRightOrder;
endWithResult = currentFunction.endingFunction;
onlyArgs = currentFunction.onlyArgs;
break;
}
}
// No actual call to the function
if (onlyArgs) {
- onlyReturnArguments = functionArgs;
- return;
+ return {
+ contents: contents,
+ input: [],
+ endWithResult: false,
+ onlyReturnArguments: functionArgs
+ };
}
if (endWithResult) {
shouldEndWithResult = true;
}
let functionResponse = _callFunction(functionName, functionArgs, argsOrder);
// ... rest of loop body
- });
+ }🤖 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 1848 - 1851, The `return` statement inside the
`forEach` loop at the `onlyArgs` check only skips the current iteration instead
of exiting the entire function. Replace the `forEach` loop with a traditional
`for` loop so that when `onlyArgs` is true and `onlyReturnArguments` is
assigned, the function can use `return` to exit immediately and stop processing
remaining function calls, similar to how the OpenAI handler at lines 1927-1933
handles early termination with `return messages`.
| testGeminiInteractionThreading(); | ||
| testGeminiRetrieveLastInteractionId(); | ||
| testGeminiFunctionCallingInteractionContinuation(); |
There was a problem hiding this comment.
testAll() skips the Vertex threading test.
Line 18–20 adds new Gemini tests, but testGeminiVertexInteractionThreading() is never invoked, so the Vertex interaction path is not exercised in full-suite runs.
Suggested patch
function testAll() {
@@
testGeminiInteractionThreading();
testGeminiRetrieveLastInteractionId();
testGeminiFunctionCallingInteractionContinuation();
+ if (typeof GCP_PROJECT_ID === "string" && GCP_PROJECT_ID &&
+ typeof REGION === "string" && REGION) {
+ testGeminiVertexInteractionThreading();
+ }
// OpenAI-only tests - require valid Drive file IDs.📝 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.
| testGeminiInteractionThreading(); | |
| testGeminiRetrieveLastInteractionId(); | |
| testGeminiFunctionCallingInteractionContinuation(); | |
| testGeminiInteractionThreading(); | |
| testGeminiRetrieveLastInteractionId(); | |
| testGeminiFunctionCallingInteractionContinuation(); | |
| if (typeof GCP_PROJECT_ID === "string" && GCP_PROJECT_ID && | |
| typeof REGION === "string" && REGION) { | |
| testGeminiVertexInteractionThreading(); | |
| } |
🤖 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/testFunctions.gs` around lines 18 - 20, The testAll() function is missing
an invocation of the Vertex interaction threading test. Add a call to
testGeminiVertexInteractionThreading() in the testAll() function alongside the
other Gemini test invocations (testGeminiInteractionThreading,
testGeminiRetrieveLastInteractionId, and
testGeminiFunctionCallingInteractionContinuation) to ensure the Vertex
interaction threading path is tested during full-suite runs.
| function testGeminiInteractionThreading() { | ||
| GenAIApp.setGeminiAPIKey(GEMINI_API_KEY); | ||
| const chat = GenAIApp.newChat(); | ||
| chat.addMessage("Remember this keyword for the next turn: papaya."); | ||
| const firstResponse = chat.run({ model: GEMINI_MODEL, max_tokens: 500 }); | ||
| const interactionId = chat.retrieveLastInteractionId(); | ||
| if (!interactionId) { | ||
| throw new Error("Gemini interaction ID was not captured after the first response."); | ||
| } | ||
| console.log(`Gemini first interaction id: ${interactionId}`); | ||
| chat.addMessage("What keyword did I ask you to remember?"); | ||
| const secondResponse = chat.run({ model: GEMINI_MODEL, max_tokens: 500 }); | ||
| console.log(`Gemini threaded response:\n${secondResponse}`); | ||
| } |
There was a problem hiding this comment.
testGeminiInteractionThreading does not verify continuation success.
Line 205–207 runs a second turn but never validates that threading actually worked (no second interaction-ID check, no memory assertion), so this can pass even when continuation is broken.
Suggested patch
function testGeminiInteractionThreading() {
@@
- chat.addMessage("What keyword did I ask you to remember?");
+ chat.addMessage("What keyword did I ask you to remember? Reply with only that keyword.");
const secondResponse = chat.run({ model: GEMINI_MODEL, max_tokens: 500 });
+ const secondInteractionId = chat.retrieveLastInteractionId();
+ if (!secondInteractionId || secondInteractionId === interactionId) {
+ throw new Error("Gemini continuation did not produce a valid next interaction ID.");
+ }
+ if (!/papaya/i.test(secondResponse)) {
+ throw new Error("Gemini threaded response did not preserve prior-turn context.");
+ }
console.log(`Gemini threaded response:\n${secondResponse}`);
}📝 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.
| function testGeminiInteractionThreading() { | |
| GenAIApp.setGeminiAPIKey(GEMINI_API_KEY); | |
| const chat = GenAIApp.newChat(); | |
| chat.addMessage("Remember this keyword for the next turn: papaya."); | |
| const firstResponse = chat.run({ model: GEMINI_MODEL, max_tokens: 500 }); | |
| const interactionId = chat.retrieveLastInteractionId(); | |
| if (!interactionId) { | |
| throw new Error("Gemini interaction ID was not captured after the first response."); | |
| } | |
| console.log(`Gemini first interaction id: ${interactionId}`); | |
| chat.addMessage("What keyword did I ask you to remember?"); | |
| const secondResponse = chat.run({ model: GEMINI_MODEL, max_tokens: 500 }); | |
| console.log(`Gemini threaded response:\n${secondResponse}`); | |
| } | |
| function testGeminiInteractionThreading() { | |
| GenAIApp.setGeminiAPIKey(GEMINI_API_KEY); | |
| const chat = GenAIApp.newChat(); | |
| chat.addMessage("Remember this keyword for the next turn: papaya."); | |
| const firstResponse = chat.run({ model: GEMINI_MODEL, max_tokens: 500 }); | |
| const interactionId = chat.retrieveLastInteractionId(); | |
| if (!interactionId) { | |
| throw new Error("Gemini interaction ID was not captured after the first response."); | |
| } | |
| console.log(`Gemini first interaction id: ${interactionId}`); | |
| chat.addMessage("What keyword did I ask you to remember? Reply with only that keyword."); | |
| const secondResponse = chat.run({ model: GEMINI_MODEL, max_tokens: 500 }); | |
| const secondInteractionId = chat.retrieveLastInteractionId(); | |
| if (!secondInteractionId || secondInteractionId === interactionId) { | |
| throw new Error("Gemini continuation did not produce a valid next interaction ID."); | |
| } | |
| if (!/papaya/i.test(secondResponse)) { | |
| throw new Error("Gemini threaded response did not preserve prior-turn context."); | |
| } | |
| console.log(`Gemini threaded response:\n${secondResponse}`); | |
| } |
🤖 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/testFunctions.gs` around lines 195 - 208, The
testGeminiInteractionThreading function verifies the first interaction ID but
fails to validate that threading actually succeeded on the second turn. After
calling chat.run() for the secondResponse, retrieve the second interaction ID
using chat.retrieveLastInteractionId() and assert that it exists, then add an
assertion to verify that the secondResponse actually contains evidence of memory
from the first turn (such as checking that the response mentions the keyword
"papaya" that was provided in the initial message). This ensures the test will
fail if continuation or threading is broken rather than passing with incomplete
validation.
| function testGeminiFunctionCallingInteractionContinuation() { | ||
| GenAIApp.setGeminiAPIKey(GEMINI_API_KEY); | ||
| const weatherFunction = GenAIApp.newFunction() | ||
| .setName("getWeather") | ||
| .setDescription("To retrieve the weather in a city in °C") | ||
| .addParameter("cityName", "string", "The name of the city."); | ||
|
|
||
| const chat = GenAIApp.newChat(); | ||
| chat | ||
| .addMessage("What's the weather in Paris? Use the available function, then answer normally.") | ||
| .addFunction(weatherFunction); | ||
| const response = chat.run({ model: GEMINI_MODEL, max_tokens: 1000 }); | ||
| const interactionId = chat.retrieveLastInteractionId(); | ||
| if (!interactionId) { | ||
| throw new Error("Gemini interaction ID was not captured after function-call continuation."); | ||
| } | ||
| console.log(`Gemini function continuation response:\n${response}`); | ||
| console.log(`Gemini function continuation interaction id: ${interactionId}`); | ||
| } |
There was a problem hiding this comment.
testGeminiFunctionCallingInteractionContinuation never performs a continuation turn.
Lines 234–240 only validate the first run’s ID. This does not test the continuation contract after function-calling.
Suggested patch
function testGeminiFunctionCallingInteractionContinuation() {
@@
- const response = chat.run({ model: GEMINI_MODEL, max_tokens: 1000 });
- const interactionId = chat.retrieveLastInteractionId();
- if (!interactionId) {
+ const firstResponse = chat.run({ model: GEMINI_MODEL, max_tokens: 1000 });
+ const firstInteractionId = chat.retrieveLastInteractionId();
+ if (!firstInteractionId) {
throw new Error("Gemini interaction ID was not captured after function-call continuation.");
}
- console.log(`Gemini function continuation response:\n${response}`);
- console.log(`Gemini function continuation interaction id: ${interactionId}`);
+ chat.addMessage("Using one word only, what city did you check?");
+ const secondResponse = chat.run({ model: GEMINI_MODEL, max_tokens: 500 });
+ const secondInteractionId = chat.retrieveLastInteractionId();
+ if (!secondInteractionId || secondInteractionId === firstInteractionId) {
+ throw new Error("Gemini function-call continuation did not advance interaction state.");
+ }
+ if (!/paris/i.test(secondResponse)) {
+ throw new Error("Gemini function-call continuation did not preserve context.");
+ }
+ console.log(`Gemini function continuation first response:\n${firstResponse}`);
+ console.log(`Gemini function continuation second response:\n${secondResponse}`);
+ console.log(`Gemini function continuation interaction ids: ${firstInteractionId} -> ${secondInteractionId}`);
}🤖 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/testFunctions.gs` around lines 223 - 241, The
testGeminiFunctionCallingInteractionContinuation function only performs an
initial chat run but never executes a continuation turn to test the full
function-calling workflow. After calling chat.run() and retrieving the
interaction ID, the test needs to simulate the function execution by calling a
continuation method on the chat object (likely chat.continueWithFunctionResult
or similar) with a mock weather result, then run the chat again to verify the
continuation returns a proper response. This ensures the interaction ID is
properly maintained across the function-calling round-trip and the chat
correctly handles the continuation contract.
| function testGeminiVertexInteractionThreading() { | ||
| GenAIApp.setGeminiAuth(GCP_PROJECT_ID, REGION); | ||
| const chat = GenAIApp.newChat(); | ||
| chat.addMessage("Reply with the word vertex and a one-sentence explanation of interactions."); | ||
| const response = chat.run({ model: GEMINI_MODEL, max_tokens: 500 }); | ||
| const interactionId = chat.retrieveLastInteractionId(); | ||
| if (!interactionId) { | ||
| throw new Error("Vertex Gemini interaction ID was not captured."); | ||
| } | ||
| console.log(`Vertex Gemini interaction response:\n${response}`); | ||
| console.log(`Vertex Gemini interaction id: ${interactionId}`); | ||
| } |
There was a problem hiding this comment.
testGeminiVertexInteractionThreading is single-turn despite threading intent.
Line 243 names this as threading, but it only executes one call and checks one ID. It should perform a follow-up turn and validate interaction progression.
Suggested patch
function testGeminiVertexInteractionThreading() {
GenAIApp.setGeminiAuth(GCP_PROJECT_ID, REGION);
const chat = GenAIApp.newChat();
- chat.addMessage("Reply with the word vertex and a one-sentence explanation of interactions.");
- const response = chat.run({ model: GEMINI_MODEL, max_tokens: 500 });
- const interactionId = chat.retrieveLastInteractionId();
- if (!interactionId) {
+ chat.addMessage("Remember this token for the next turn: vertex-token.");
+ const firstResponse = chat.run({ model: GEMINI_MODEL, max_tokens: 500 });
+ const firstInteractionId = chat.retrieveLastInteractionId();
+ if (!firstInteractionId) {
throw new Error("Vertex Gemini interaction ID was not captured.");
}
- console.log(`Vertex Gemini interaction response:\n${response}`);
- console.log(`Vertex Gemini interaction id: ${interactionId}`);
+ chat.addMessage("Reply with only the remembered token.");
+ const secondResponse = chat.run({ model: GEMINI_MODEL, max_tokens: 300 });
+ const secondInteractionId = chat.retrieveLastInteractionId();
+ if (!secondInteractionId || secondInteractionId === firstInteractionId) {
+ throw new Error("Vertex Gemini continuation did not produce a valid next interaction ID.");
+ }
+ if (!/vertex-token/i.test(secondResponse)) {
+ throw new Error("Vertex Gemini threaded response did not preserve prior-turn context.");
+ }
+ console.log(`Vertex Gemini first response:\n${firstResponse}`);
+ console.log(`Vertex Gemini second response:\n${secondResponse}`);
+ console.log(`Vertex Gemini interaction ids: ${firstInteractionId} -> ${secondInteractionId}`);
}📝 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.
| function testGeminiVertexInteractionThreading() { | |
| GenAIApp.setGeminiAuth(GCP_PROJECT_ID, REGION); | |
| const chat = GenAIApp.newChat(); | |
| chat.addMessage("Reply with the word vertex and a one-sentence explanation of interactions."); | |
| const response = chat.run({ model: GEMINI_MODEL, max_tokens: 500 }); | |
| const interactionId = chat.retrieveLastInteractionId(); | |
| if (!interactionId) { | |
| throw new Error("Vertex Gemini interaction ID was not captured."); | |
| } | |
| console.log(`Vertex Gemini interaction response:\n${response}`); | |
| console.log(`Vertex Gemini interaction id: ${interactionId}`); | |
| } | |
| function testGeminiVertexInteractionThreading() { | |
| GenAIApp.setGeminiAuth(GCP_PROJECT_ID, REGION); | |
| const chat = GenAIApp.newChat(); | |
| chat.addMessage("Remember this token for the next turn: vertex-token."); | |
| const firstResponse = chat.run({ model: GEMINI_MODEL, max_tokens: 500 }); | |
| const firstInteractionId = chat.retrieveLastInteractionId(); | |
| if (!firstInteractionId) { | |
| throw new Error("Vertex Gemini interaction ID was not captured."); | |
| } | |
| chat.addMessage("Reply with only the remembered token."); | |
| const secondResponse = chat.run({ model: GEMINI_MODEL, max_tokens: 300 }); | |
| const secondInteractionId = chat.retrieveLastInteractionId(); | |
| if (!secondInteractionId || secondInteractionId === firstInteractionId) { | |
| throw new Error("Vertex Gemini continuation did not produce a valid next interaction ID."); | |
| } | |
| if (!/vertex-token/i.test(secondResponse)) { | |
| throw new Error("Vertex Gemini threaded response did not preserve prior-turn context."); | |
| } | |
| console.log(`Vertex Gemini first response:\n${firstResponse}`); | |
| console.log(`Vertex Gemini second response:\n${secondResponse}`); | |
| console.log(`Vertex Gemini interaction ids: ${firstInteractionId} -> ${secondInteractionId}`); | |
| } |
🤖 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/testFunctions.gs` around lines 243 - 254, The
testGeminiVertexInteractionThreading function is named to indicate multi-turn
conversation testing but only executes a single message-response cycle. To
properly test threading, add a second message to the chat object using
addMessage, execute another run call to get a follow-up response, retrieve the
new interaction ID using retrieveLastInteractionId, and validate that the
interaction progression is working correctly (such as verifying the new
interaction ID is different from or properly related to the first one). This
will ensure the function actually tests the multi-turn nature of the chat
threading.
Motivation
:generateContentusage with the newer Interactions API shape to support Gemini/Vertex multi-turn continuation and unified model specification in the request body.contents[]history to reduce payload size and align with Interactions API semantics.steps(model_output/function_call) and to batch function results for continuation.Description
https://generativelanguage.googleapis.com/v1beta/interactionsand Vertex AI global/regionalhttps://aiplatform.googleapis.com/v1beta1/.../interactionspaths, removing:generateContentmodel URLs. (src/code.gs)this._buildGeminiPayloadto emit an Interactions-style payload with top-levelmodel,input(converted from legacycontents[]via_geminiContentsToInteractionInput),max_output_tokens,temperature,tools, and optionalprevious_interaction_id; remove legacytool_configusage and map function call options totool_choiceand tool entries. (src/code.gs)previous_interaction_id,last_gemini_interaction_id,pending_gemini_input, andlast_gemini_content_count, plussetPreviousInteractionId()andretrieveLastInteractionId()methods;run()stores returned interactionidintolast_gemini_interaction_idand usesprevious_interaction_idfor continuation. (src/code.gs)steps: added helpers_extractGeminiResponseText,_extractGeminiFunctionCalls, and_geminiContentsToInteractionInput; update_callGenAIApifinish-reason mapping for Interactions responses. (src/code.gs)_handleGeminiToolCallsto detectfunction_callsteps, execute functions with_callFunction, batchfunction_resultentries and return{contents, input, endWithResult, onlyReturnArguments}so the caller can continue withprevious_interaction_idrather than resending full history. (src/code.gs)contents[]handling so it is used to build the initialinputbut not accumulated indefinitely when using interaction IDs; preserve backward-compatible fallbacks for legacy response shapes. (src/code.gs)src/testFunctions.gs:testGeminiInteractionThreading,testGeminiRetrieveLastInteractionId,testGeminiFunctionCallingInteractionContinuation, andtestGeminiVertexInteractionThreading, and include them intestAll(). (src/testFunctions.gs)Testing
node --checkon copies ofsrc/code.gsandsrc/testFunctions.gs, which succeeded.:generateContent,models/${model},generationConfig,tool_config,candidates) to confirm migration of those constructs, and validated no remaining:generateContentendpoints; the grep checks passed.git diff --checkwhich reported no whitespace/merge issues.src/testFunctions.gsfor interaction threading and interaction ID retrieval; these tests were added but not executed against live Gemini/Vertex APIs in this run (they require valid API credentials and network).Codex Task