Add Code Interpreter tooling and generated file download support#71
Add Code Interpreter tooling and generated file download support#71Benjamin-Sayaque wants to merge 4 commits into
Conversation
📝 WalkthroughSummary by CodeRabbitNew Features
WalkthroughAdds 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. ChangesCode Interpreter Feature
Sequence DiagramsequenceDiagram
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
🎯 4 (Complex) | ⏱️ ~45 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
Warning Review ran into problems🔥 ProblemsGit: Failed to clone repository. Please run the Comment |
There was a problem hiding this comment.
💡 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".
| payload.tools.push({ | ||
| type: "container", | ||
| container_id: this._codeInterpreterContainerId |
There was a problem hiding this comment.
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 👍 / 👎.
| const citation = annotation?.container_file_citation; | ||
| if (citation?.container_id && citation?.file_id) { |
There was a problem hiding this comment.
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 👍 / 👎.
|
|
||
| this._downloadContainerFile = function (containerId, fileId, filename) { | ||
| const endpointUrl = `${apiBaseUrl}/v1/containers/${containerId}/files/${fileId}/content`; | ||
| const response = _callGenAIApi(endpointUrl, null, "GET", true); |
There was a problem hiding this comment.
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 👍 / 👎.
There was a problem hiding this comment.
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 winGuard 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 readpayload.model, which will raise aTypeErrorand 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
📒 Files selected for processing (2)
src/code.gssrc/testFunctions.gs
📜 Review details
🔇 Additional comments (1)
src/testFunctions.gs (1)
4-5: LGTM!Also applies to: 18-24
| this._generatedFiles = this._extractContainerFileCitations(responseMessage); | ||
| if (this._generatedFiles.length > 0) { | ||
| this._lastContainerId = this._generatedFiles[0].containerId; | ||
| } |
There was a problem hiding this comment.
🧩 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 || trueRepository: 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 || trueRepository: 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.gsRepository: 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 || trueRepository: 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.
| 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.
| if (this._codeInterpreterContainerId) { | ||
| payload.tools.push({ | ||
| type: "container", | ||
| container_id: this._codeInterpreterContainerId | ||
| }); |
There was a problem hiding this comment.
🧩 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:
- 1: https://developers.openai.com/api/docs/guides/tools-code-interpreter
- 2: https://team400.ai/blog/2026-04-openai-code-interpreter-containers-guide
- 3: https://github.com/langchain-ai/langchainjs/blob/75e9d56926988dc355c9e5cf63af05a4b378cdf2/libs/providers/langchain-openai/src/tools/codeInterpreter.ts
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.
| 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).
There was a problem hiding this comment.
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
📒 Files selected for processing (2)
src/code.gssrc/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!
| 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); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 winClear the pinned container when switching back to auto mode.
Line 319 only updates
_codeInterpreterContainerIdwhencontainerIdis truthy. AfterenableCodeInterpreter("cntr_..."), a laterenableCodeInterpreter()call on the sameChatinstance 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
📒 Files selected for processing (2)
src/code.gssrc/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 documentedcode_interpretertool schema for explicit container reuse.OpenAI documents explicit reuse as the
code_interpretertool withcontainerset 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
Motivation
Description
_codeInterpreterEnabled,_codeInterpreterContainerId,_generatedFiles, and_lastContainerId, plus a chainableenableCodeInterpreter(containerId?)method with JSDoc and example.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 setparallel_tool_calls = falsewhen using the tool.this._extractContainerFileCitations(response)to collect{ containerId, fileId, filename }entries and store them tothis._generatedFilesafter eachrun(), also capturing_lastContainerId.this._downloadContainerFile(containerId, fileId, filename)which fetcheshttps://api.openai.com/v1/containers/{containerId}/files/{fileId}/contentand returns a Blob with content type and filename applied.getGeneratedFiles(),downloadGeneratedFile(fileIdOrIndex)andgetContainerId()with JSDoc and usage examples._callGenAIApi()to accept an HTTPmethodandreturnRawResponseflag so the download helper can reuse existing auth/retry logic for GET file-content requests.src/testFunctions.gs:testCodeInterpreterExcel(driveFileId)andtestCodeInterpreterPDF(driveFileId), and registered them behind configurable Drive file ID constants.Testing
git diffand created a commit for the changes tosrc/code.gsandsrc/testFunctions.gs, and the commit succeeded.testCodeInterpreterExcel/testCodeInterpreterPDF) because they require valid API keys and Drive file IDs and cannot run in this environment.Codex Task