Skip to content

Add Code Interpreter tooling and generated file download support#71

Open
Benjamin-Sayaque wants to merge 4 commits into
mainfrom
codex/add-code-interpreter-support-to-chat-class
Open

Add Code Interpreter tooling and generated file download support#71
Benjamin-Sayaque wants to merge 4 commits into
mainfrom
codex/add-code-interpreter-support-to-chat-class

Conversation

@Benjamin-Sayaque
Copy link
Copy Markdown
Contributor

Motivation

  • Provide first-class Code Interpreter integration so chat workflows can request model-managed containers and retrieve generated files.
  • Allow reusing an explicit container ID or creating an automatic container and expose generated-file metadata for downstream storage.
  • Reuse existing API auth/retry infrastructure to fetch file content from OpenAI container endpoints.

Description

  • Added Chat instance state: _codeInterpreterEnabled, _codeInterpreterContainerId, _generatedFiles, and _lastContainerId, plus a chainable enableCodeInterpreter(containerId?) method with JSDoc and example.
  • Updated OpenAI payload construction in this._buildOpenAIPayload() to append either a { type: "code_interpreter", container: { type: "auto" } } tool when enabled or { type: "container", container_id: ... } when a container ID is supplied, and set parallel_tool_calls = false when using the tool.
  • Implemented response parsing helper this._extractContainerFileCitations(response) to collect { containerId, fileId, filename } entries and store them to this._generatedFiles after each run(), also capturing _lastContainerId.
  • Added download helper this._downloadContainerFile(containerId, fileId, filename) which fetches https://api.openai.com/v1/containers/{containerId}/files/{fileId}/content and returns a Blob with content type and filename applied.
  • Exposed public APIs getGeneratedFiles(), downloadGeneratedFile(fileIdOrIndex) and getContainerId() with JSDoc and usage examples.
  • Extended internal _callGenAIApi() to accept an HTTP method and returnRawResponse flag so the download helper can reuse existing auth/retry logic for GET file-content requests.
  • Added OpenAI-only test helpers in src/testFunctions.gs: testCodeInterpreterExcel(driveFileId) and testCodeInterpreterPDF(driveFileId), and registered them behind configurable Drive file ID constants.

Testing

  • Performed repository sanity checks including git diff and created a commit for the changes to src/code.gs and src/testFunctions.gs, and the commit succeeded.
  • Verified static edits by printing relevant file regions and diffs to ensure payload, helpers, and new functions are present.
  • Did not execute Apps Script runtime tests (testCodeInterpreterExcel / testCodeInterpreterPDF) because they require valid API keys and Drive file IDs and cannot run in this environment.

Codex Task

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 22, 2026

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

New Features

  • OpenAI Code Interpreter support is now enabled, allowing code execution and file generation
  • Added methods to enable Code Interpreter functionality, retrieve generated file metadata, download generated files by ID or index, and access runtime configuration information
  • Generated files from Code Interpreter runs are automatically cached and accessible through the public API

Walkthrough

Adds OpenAI Code Interpreter support to Chat: state and enablement, payload/tool integration, response file extraction and download helpers, HTTP adjustments for raw responses, run lifecycle updates, public file APIs, and test helpers.

Changes

Code Interpreter Feature

Layer / File(s) Summary
Code Interpreter state and enablement
src/code.gs
New internal fields track Code Interpreter enablement, configured container id, generated files, and last container id. enableCodeInterpreter(containerId?) activates the feature on a chat instance.
Run lifecycle updates
src/code.gs
Clears generated-file metadata and last container id at run() start; after API response extracts container file citations and stores generated files and container id.
OpenAI payload: Code Interpreter tool
src/code.gs
_buildOpenAIPayload() conditionally disables parallel_tool_calls and adds either an explicit container tool or a code_interpreter tool for auto-created containers.
Container file extraction & download
src/code.gs
Adds _extractContainerFileCitations(response) to normalize container file metadata and _downloadContainerFile(containerId,fileId,filename) to fetch file content preserving content type and filename.
Public APIs for generated files and container
src/code.gs
getGeneratedFiles(), downloadGeneratedFile(fileIdOrIndex), and getContainerId() expose the most recent run’s generated files and effective container id.
HTTP layer updates for file operations
src/code.gs
_callGenAIApi now accepts method and returnRawResponse, uses the provided HTTP method in UrlFetchApp options, always sets muteHttpExceptions, conditionally attaches payload, and can return the raw UrlFetchApp response for successful requests.
Code Interpreter test configuration and helpers
src/testFunctions.gs
Adds Drive file ID constants, conditional runs in testAll(), and testCodeInterpreterExcel / testCodeInterpreterPDF helpers that run Code Interpreter chats with Drive inputs and create Drive files from outputs.

Sequence Diagram

sequenceDiagram
  participant User
  participant Chat
  participant OpenAIAPI
  participant ContainerAPI
  participant Drive

  User->>Chat: enableCodeInterpreter(containerId?)
  User->>Chat: addMessage()/run()
  Chat->>OpenAIAPI: POST (payload with code_interpreter or container tool)
  OpenAIAPI-->>Chat: Response with container file citations
  Chat->>Chat: _extractContainerFileCitations -> store generated files & container id
  User->>Chat: getGeneratedFiles()
  Chat-->>User: generated files metadata
  User->>Chat: downloadGeneratedFile(fileId)
  Chat->>ContainerAPI: GET /v1/containers/{containerId}/files/{fileId}/content
  ContainerAPI-->>Chat: File blob (content-type, filename)
  Chat-->>User: Blob
  User->>Drive: create file from blob
Loading

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title directly summarizes the main changes: adding Code Interpreter tooling and generated file download support to the Chat class.
Description check ✅ Passed The description is comprehensively related to the changeset, detailing motivation, implementation specifics, testing approach, and all major features added.
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 codex/add-code-interpreter-support-to-chat-class
  • 🛠️ 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.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e54cf05716

ℹ️ 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".

Comment thread src/code.gs
Comment on lines +764 to +766
payload.tools.push({
type: "container",
container_id: this._codeInterpreterContainerId
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Use code_interpreter tool when reusing container IDs

When enableCodeInterpreter(containerId) is used, the payload adds a tool with type: "container", but the Responses API expects the Code Interpreter tool itself (type: "code_interpreter") with the container ID in its container field. This makes the explicit-container path fail at request time, so users cannot reuse an existing container despite supplying a valid ID.

Useful? React with 👍 / 👎.

Comment thread src/code.gs Outdated
Comment on lines +791 to +792
const citation = annotation?.container_file_citation;
if (citation?.container_id && citation?.file_id) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Parse container_file_citation fields from annotations directly

The extraction logic looks for annotation.container_file_citation, but container file annotations are emitted with top-level fields like type, container_id, and file_id. As written, getGeneratedFiles() stays empty even when Code Interpreter generates files, which breaks downloadGeneratedFile() for normal successful runs.

Useful? React with 👍 / 👎.

Comment thread src/code.gs

this._downloadContainerFile = function (containerId, fileId, filename) {
const endpointUrl = `${apiBaseUrl}/v1/containers/${containerId}/files/${fileId}/content`;
const response = _callGenAIApi(endpointUrl, null, "GET", true);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid null payload call path in _callGenAIApi retries

This call passes payload = null, but _callGenAIApi still references payload.model in several non-200 branches (rate limits/server errors/generic failures). If the file download endpoint returns anything other than 200, the retry/error handling can throw a TypeError instead of surfacing the real API failure, making download errors hard to diagnose and bypassing intended retry behavior.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

@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: 4

Caution

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

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

1517-1637: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Guard the new GET/raw-response path against payload === null.

_downloadContainerFile() now calls _callGenAIApi(endpoint, null, "GET", true). Any network error or non-200 response on that path hits log/throw branches that read payload.model, which will raise a TypeError and hide the actual download failure.

Proposed fix
   function _callGenAIApi(endpoint, payload, method = "post", returnRawResponse = false) {
+    const requestLabel = payload?.model || endpoint;
     let authMethod = 'Bearer ' + openAIKey;
@@
         catch (err) {
           if (verbose) {
-            console.warn(`[GenAIApp] - Network error calling ${payload.model}: ${err.message}. Retrying (${retries + 1}/${maxRetries})`);
+            console.warn(`[GenAIApp] - Network error calling ${requestLabel}: ${err.message}. Retrying (${retries + 1}/${maxRetries})`);
           }
@@
-          console.warn(`[GenAIApp] - Context length exceeded when calling ${payload.model} with MCP connectors, retrying (${retries}/${maxRetries}).`);
+          console.warn(`[GenAIApp] - Context length exceeded when calling ${requestLabel} with MCP connectors, retrying (${retries}/${maxRetries}).`);
@@
-        console.warn(`[GenAIApp] - Rate limit reached when calling ${payload.model}, retrying (${retries}/${maxRetries}).`);
+        console.warn(`[GenAIApp] - Rate limit reached when calling ${requestLabel}, retrying (${retries}/${maxRetries}).`);
@@
-          console.warn(`[GenAIApp] - Request to ${payload.model} failed with response code ${responseCode} - ${response.getContentText()}, retrying (${retries}/${maxRetries})`);
+          console.warn(`[GenAIApp] - Request to ${requestLabel} failed with response code ${responseCode} - ${response.getContentText()}, retrying (${retries}/${maxRetries})`);
         }
@@
-        console.error(`[GenAIApp] - Request to ${payload.model} failed with response code ${responseCode} - ${response.getContentText()}`);
+        console.error(`[GenAIApp] - Request to ${requestLabel} failed with response code ${responseCode} - ${response.getContentText()}`);
         break;
       }
     }
 
     if (!success) {
-      throw new Error(`[GenAIApp] - Failed to call ${payload.model} after ${retries} retries.`);
+      throw new Error(`[GenAIApp] - Failed to call ${requestLabel} after ${retries} retries.`);
     }
@@
-        message: `[GenAIApp] - Got response from ${payload.model}`,
+        message: `[GenAIApp] - Got response from ${requestLabel}`,
         responseMessage: responseMessage
       });
🤖 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 1517 - 1637, The code in _callGenAIApi assumes
payload.model exists when logging or throwing, causing a TypeError when called
with payload === null (as from _downloadContainerFile); update _callGenAIApi to
derive a safe identifier (e.g., const modelName = payload && payload.model ?
payload.model : endpoint || method) and use modelName in all
console.warn/console.error messages and in the final thrown Error instead of
payload.model, and also guard any other access to payload properties
(payload.tools) with null checks so the GET/raw-response path won’t crash and
will surface the real network/download error.
🤖 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 763-767: The current code pushes a nonstandard { type:
"container", container_id: ... } tool into payload.tools when
this._codeInterpreterContainerId is set; instead, emit the documented
code_interpreter tool schema and remove the ad-hoc container tool. Update the
logic around this._codeInterpreterContainerId /
enableCodeInterpreter(containerId) to push a tool object named
"code_interpreter" that follows the API schema with a top-level container field
set to this._codeInterpreterContainerId (and remove the separate { type:
"container", container_id: ... } entry).
- Around line 539-542: The code only sets this._lastContainerId from
this._generatedFiles (via _extractContainerFileCitations) and misses container
IDs surfaced on response items of type code_interpreter_call; update the
handling after receiving responseMessage so that you also inspect
responseMessage outputs (or the top-level outputs list) for any
code_interpreter_call item, extract its container_id, and set
this._lastContainerId to that container_id (fall back to existing
_generatedFiles logic if both exist). Modify the logic around
this._generatedFiles = this._extractContainerFileCitations(responseMessage) to
also call a helper or inline extraction for code_interpreter_call entries and
assign the container id to this._lastContainerId when present so follow-up runs
can reuse the auto-created container.

In `@src/testFunctions.gs`:
- Line 171: Guard against calling chat.downloadGeneratedFile(0) when there are
no generated files: before each download call (the usages of
chat.downloadGeneratedFile at the two locations), check the chat object's
generated-files collection/count (e.g., chat.generatedFiles?.length or a
provided getGeneratedFiles()/getGeneratedFilesCount() API) and fail fast with a
clear error message if the count is zero; update both occurrences so they
validate existence first and throw/log a descriptive error (e.g., "No generated
files returned by Code Interpreter") instead of attempting the download.
- Line 170: The tests currently log full model/file-derived outputs via
console.log(`Code Interpreter Excel response:\n${response}`) (and a similar log
at the later occurrence), which may leak sensitive document content; update the
logging in the testFunctions.gs helper where response is produced to avoid
dumping full content and instead log structured metadata only (e.g., status,
number of files processed, file IDs or names, and any error codes). Locate the
console.log statements referencing the response variable in the function that
runs the Code Interpreter Excel test and replace them with concise, non-content
logs that extract and print only status, fileCount, ids, or error fields from
the response object.

---

Outside diff comments:
In `@src/code.gs`:
- Around line 1517-1637: The code in _callGenAIApi assumes payload.model exists
when logging or throwing, causing a TypeError when called with payload === null
(as from _downloadContainerFile); update _callGenAIApi to derive a safe
identifier (e.g., const modelName = payload && payload.model ? payload.model :
endpoint || method) and use modelName in all console.warn/console.error messages
and in the final thrown Error instead of payload.model, and also guard any other
access to payload properties (payload.tools) with null checks so the
GET/raw-response path won’t crash and will surface the real network/download
error.
🪄 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: 1170fa5b-8db0-4ecb-b3a1-f9405fcc186e

📥 Commits

Reviewing files that changed from the base of the PR and between 3598bae and e54cf05.

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

4-5: LGTM!

Also applies to: 18-24

Comment thread src/code.gs
Comment on lines +539 to +542
this._generatedFiles = this._extractContainerFileCitations(responseMessage);
if (this._generatedFiles.length > 0) {
this._lastContainerId = this._generatedFiles[0].containerId;
}
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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

According to the current OpenAI Code Interpreter docs, where should clients read the container ID for an auto-created container from a Responses API result?

💡 Result:

Clients should read the auto-created container ID from the Responses API output item named "code_interpreter_call"—the docs say to “look for the code_interpreter_call item in the output of this API request to find the container_id that was generated or used.” [1]

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate and print the relevant section around the referenced lines
echo "== src/code.gs: around lines 520-580 =="
nl -ba src/code.gs | sed -n '510,580p'

echo
echo "== Search for _lastContainerId usage =="
rg -n "_lastContainerId" src/code.gs || true

echo
echo "== Search for container_file_citation extraction =="
rg -n "container_file_citation|_extractContainerFileCitations|getContainerId" src/code.gs || true

Repository: scriptit-fr/GenAIApp

Length of output: 165


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== src/code.gs: around lines 520-580 =="
awk 'NR>=510 && NR<=580 {printf "%d:%s\n", NR, $0}' src/code.gs | sed -n '1,200p'

echo
echo "== Search for _lastContainerId usage =="
rg -n "_lastContainerId" src/code.gs || true

echo
echo "== Search for container_file_citation extraction / getContainerId =="
rg -n "container_file_citation|_extractContainerFileCitations|getContainerId" src/code.gs || true

Repository: scriptit-fr/GenAIApp

Length of output: 4731


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== src/code.gs: extractContainerFileCitations implementation =="
awk 'NR>=760 && NR<=920 {printf "%d:%s\n", NR, $0}' src/code.gs | sed -n '1,220p'

echo
echo "== Search for container_id parsing in code.gs =="
rg -n "container_id|containerId|getContainerId|container_file_citation|code_interpreter_call" src/code.gs

echo
echo "== Show around getContainerId =="
awk 'NR>=820 && NR<=890 {printf "%d:%s\n", NR, $0}' src/code.gs

Repository: scriptit-fr/GenAIApp

Length of output: 11513


🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n "code_interpreter_call" -S src || true
rg -n "container_id" -S src || true

Repository: scriptit-fr/GenAIApp

Length of output: 292


Capture the auto-created code interpreter container_id from code_interpreter_call

src/code.gs currently sets _lastContainerId only from container_file_citation (via _extractContainerFileCitations), which only appears when the assistant emits annotated generated-file citations. In auto mode, the container id for the generated/reused container is instead surfaced on the code_interpreter_call output item, so follow-up runs can’t reuse the container when no annotated files are produced. https://developers.openai.com/api/docs/guides/tools-code-interpreter

Proposed fix
           this._generatedFiles = this._extractContainerFileCitations(responseMessage);
-          if (this._generatedFiles.length > 0) {
-            this._lastContainerId = this._generatedFiles[0].containerId;
-          }
+          const codeInterpreterCall = Array.isArray(responseMessage?.output)
+            ? responseMessage.output.find(item => item?.type === "code_interpreter_call" && item?.container_id)
+            : null;
+          this._lastContainerId =
+            codeInterpreterCall?.container_id ||
+            this._generatedFiles[0]?.containerId ||
+            null;
📝 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
this._generatedFiles = this._extractContainerFileCitations(responseMessage);
if (this._generatedFiles.length > 0) {
this._lastContainerId = this._generatedFiles[0].containerId;
}
this._generatedFiles = this._extractContainerFileCitations(responseMessage);
const codeInterpreterCall = Array.isArray(responseMessage?.output)
? responseMessage.output.find(item => item?.type === "code_interpreter_call" && item?.container_id)
: null;
this._lastContainerId =
codeInterpreterCall?.container_id ||
this._generatedFiles[0]?.containerId ||
null;
🤖 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 539 - 542, The code only sets this._lastContainerId
from this._generatedFiles (via _extractContainerFileCitations) and misses
container IDs surfaced on response items of type code_interpreter_call; update
the handling after receiving responseMessage so that you also inspect
responseMessage outputs (or the top-level outputs list) for any
code_interpreter_call item, extract its container_id, and set
this._lastContainerId to that container_id (fall back to existing
_generatedFiles logic if both exist). Modify the logic around
this._generatedFiles = this._extractContainerFileCitations(responseMessage) to
also call a helper or inline extraction for code_interpreter_call entries and
assign the container id to this._lastContainerId when present so follow-up runs
can reuse the auto-created container.

Comment thread src/code.gs
Comment on lines +763 to +767
if (this._codeInterpreterContainerId) {
payload.tools.push({
type: "container",
container_id: this._codeInterpreterContainerId
});
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.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

According to the current OpenAI Responses API documentation, what is the correct tools payload for reusing an existing Code Interpreter container in explicit mode?

💡 Result:

According to the official OpenAI API documentation for the Code Interpreter tool, you can reuse an existing container in "explicit mode" by passing the specific container ID as the value for the container field within your tool configuration payload [1][2]. In explicit mode, you must first create a container using the /v1/containers endpoint [1][2]. Once you have obtained the container ID (e.g., cntr_abc123), you include it directly in the tool configuration as follows [1][3][2]: { "type": "code_interpreter", "container": "cntr_abc123" } This payload is used within the tools array when making a request to the Responses API (e.g., v1/responses) [1][2]. By providing this ID, the model is directed to perform its code execution tasks within that specific, pre-existing sandboxed environment, allowing for persistent file access and state across multiple requests [1][2]. This contrasts with "auto mode," where the container field would instead be an object specifying configuration settings like {"type": "auto", ...} [1][2].

Citations:


Use the documented code_interpreter tool schema when reusing an existing container

OpenAI’s Responses API expects explicit container reuse to be configured via the code_interpreter tool with a top-level container field containing the container ID. Emitting a separate { type: "container", container_id: ... } tool shape does not match the documented schema, so enableCodeInterpreter(containerId) is likely to break for the explicit reuse path.

Proposed fix
-          if (this._codeInterpreterContainerId) {
-            payload.tools.push({
-              type: "container",
-              container_id: this._codeInterpreterContainerId
-            });
-          }
+          if (this._codeInterpreterContainerId) {
+            payload.tools.push({
+              type: "code_interpreter",
+              container: this._codeInterpreterContainerId
+            });
+          }
📝 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
if (this._codeInterpreterContainerId) {
payload.tools.push({
type: "container",
container_id: this._codeInterpreterContainerId
});
if (this._codeInterpreterContainerId) {
payload.tools.push({
type: "code_interpreter",
container: this._codeInterpreterContainerId
});
🤖 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 763 - 767, The current code pushes a nonstandard {
type: "container", container_id: ... } tool into payload.tools when
this._codeInterpreterContainerId is set; instead, emit the documented
code_interpreter tool schema and remove the ad-hoc container tool. Update the
logic around this._codeInterpreterContainerId /
enableCodeInterpreter(containerId) to push a tool object named
"code_interpreter" that follows the API schema with a top-level container field
set to this._codeInterpreterContainerId (and remove the separate { type:
"container", container_id: ... } entry).

Comment thread src/testFunctions.gs Outdated
Comment thread src/testFunctions.gs Outdated
Copy link
Copy Markdown
Contributor

@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: 1

🤖 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 860-870: The blank-string fallback is being overwritten because
the numeric-type check is a separate if; change the standalone "if (typeof
fileIdOrIndex === \"number\")" to "else if (typeof fileIdOrIndex ===
\"number\")" (or return immediately after setting targetFile) so the earlier
blank/undefined branches that set targetFile = this._generatedFiles[0] are not
replaced; locate the logic around fileIdOrIndex / targetFile /
this._generatedFiles (e.g., in the downloadGeneratedFile call) and make the
numeric branch part of the same else-if chain.
🪄 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: 253f0eb0-fd5f-4fbd-b313-04b5d7eb358b

📥 Commits

Reviewing files that changed from the base of the PR and between e54cf05 and 6b2b62a.

📒 Files selected for processing (2)
  • src/code.gs
  • src/testFunctions.gs
📜 Review details
🔇 Additional comments (4)
src/testFunctions.gs (3)

169-171: Avoid content-heavy response logging in Code Interpreter tests.

This still logs full model output, which can include file-derived sensitive text. Keep only structured metadata in logs.

Also applies to: 186-187


172-172: Guard generated-file existence before downloading.

These calls can fail when no file is returned; add a pre-check and fail fast with a clear message.

Also applies to: 188-188


168-168: LGTM!

Also applies to: 184-184

src/code.gs (1)

781-820: LGTM!

Comment thread src/code.gs
Comment on lines +860 to +870
if (fileIdOrIndex === undefined || fileIdOrIndex === null) {
targetFile = this._generatedFiles[0];
}
else if (typeof fileIdOrIndex === "string" && fileIdOrIndex.trim() === "") {
targetFile = this._generatedFiles[0];
}
if (typeof fileIdOrIndex === "number") {
targetFile = this._generatedFiles[fileIdOrIndex];
}
else if (typeof fileIdOrIndex === "string") {
targetFile = this._generatedFiles.find(file => file.fileId === fileIdOrIndex);
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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Keep the blank-string fallback from being overwritten.

Lines 863-865 default blank input to the first generated file, but Line 869 immediately overrides that with a lookup for the empty string because this branch is no longer chained with else if. downloadGeneratedFile("") and whitespace-only input will still throw.

Suggested fix
-        if (typeof fileIdOrIndex === "number") {
+        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 860 - 870, The blank-string fallback is being
overwritten because the numeric-type check is a separate if; change the
standalone "if (typeof fileIdOrIndex === \"number\")" to "else if (typeof
fileIdOrIndex === \"number\")" (or return immediately after setting targetFile)
so the earlier blank/undefined branches that set targetFile =
this._generatedFiles[0] are not replaced; locate the logic around fileIdOrIndex
/ targetFile / this._generatedFiles (e.g., in the downloadGeneratedFile call)
and make the numeric branch part of the same else-if chain.

Copy link
Copy Markdown
Contributor

@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.

Caution

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

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

317-321: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Clear the pinned container when switching back to auto mode.

Line 319 only updates _codeInterpreterContainerId when containerId is truthy. After enableCodeInterpreter("cntr_..."), a later enableCodeInterpreter() call on the same Chat instance still reuses the old container, so you can't switch that instance back to auto-created containers.

Proposed fix
       this.enableCodeInterpreter = function (containerId) {
         this._codeInterpreterEnabled = true;
-        if (containerId) {
-          this._codeInterpreterContainerId = containerId;
-        }
+        this._codeInterpreterContainerId =
+          typeof containerId === "string" && containerId.trim() !== ""
+            ? containerId.trim()
+            : null;
         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 - 321, In enableCodeInterpreter (method on
Chat) ensure that when called with no containerId you clear the pinned container
instead of leaving the previous value: keep setting this._codeInterpreterEnabled
= true, and if containerId is provided set this._codeInterpreterContainerId =
containerId, otherwise explicitly clear it (e.g., set to null/undefined) so the
instance will return to auto-created containers rather than reusing the old
container.
🤖 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 317-321: In enableCodeInterpreter (method on Chat) ensure that
when called with no containerId you clear the pinned container instead of
leaving the previous value: keep setting this._codeInterpreterEnabled = true,
and if containerId is provided set this._codeInterpreterContainerId =
containerId, otherwise explicitly clear it (e.g., set to null/undefined) so the
instance will return to auto-created containers rather than reusing the old
container.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f2c8f538-e5c3-4593-9ead-09a2f2876a20

📥 Commits

Reviewing files that changed from the base of the PR and between 6b2b62a and 62b1e68.

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

170-170: LGTM!

Also applies to: 183-183

src/code.gs (2)

778-782: Use the documented code_interpreter tool schema for explicit container reuse.

OpenAI documents explicit reuse as the code_interpreter tool with container set directly to the container ID. The current { type: "container", container_id: ... } entry does not match that schema, so the explicit reuse path is still broken. (platform.openai.com)


55-59: LGTM!

Also applies to: 455-457

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant