Skip to content

Studio: keep grouped Python scripts visible and save them natively - #7528

Merged
danielhanchen merged 3 commits into
unslothai:mainfrom
oobabooga:fix/studio-python-tool-visibility-download
Jul 28, 2026
Merged

Studio: keep grouped Python scripts visible and save them natively#7528
danielhanchen merged 3 commits into
unslothai:mainfrom
oobabooga:fix/studio-python-tool-visibility-download

Conversation

@oobabooga

Copy link
Copy Markdown
Member

#7240 keeps executed Python scripts visible outside the tool card's collapsed output and adds a script.py download. Two paths still bypassed that behavior:

  1. Assistant messages with multiple adjacent tool calls are wrapped in a separate ToolGroup. Reopening the thread from history mounts that outer group closed, hiding every Python script and download control again.
  2. The download button used a browser Blob directly. In the desktop app this bypassed Studio's native save chooser, and the native chooser did not yet allow .py files.

Reproduction

  1. Persist a chat turn containing two adjacent completed Python tool calls.
  2. Reopen the thread from history.
  3. Observe the closed 2 tool calls group.

The executed scripts and both download controls are hidden until the group is expanded.

In the desktop app, clicking Download also follows the browser-anchor path instead of invoking save_native_file.

Fix

  • Render any adjacent tool-call range containing Python as standalone cards, matching the existing render_html exception, so the executed source cannot be hidden by the aggregate collapse. Ranges without Python remain grouped, and non-Python siblings in a mixed range retain their own collapsed cards.
  • Route Python downloads through the shared downloadFile boundary. Browsers retain the normal download, while Tauri uses the native save chooser.
  • Keep native chooser cancellation silent and show an error only for a real save failure.
  • Add a Python file filter so the native chooser accepts and defaults to script.py.

Python status, output, and images remain collapsible. Copy and Download continue to use the full executed source even when the displayed code is truncated.

Verification

  • Playwright against compiled Studio reproduced the closed outer group on current main, then confirmed both scripts and both download controls remain visible after history hydration with this change.
  • Browser Download saved script.py with byte-exact executed source.
  • Tauri-mode UI checks confirmed one native save invocation, no browser download, byte-exact UTF-8 source, the encoded script.py filename, silent cancellation, and an error toast on native rejection.
  • Native file-dialog tests: 9 passed.
  • npm run typecheck
  • npm run build
  • cargo fmt --check
  • git diff --check
  • Targeted ESLint reported only the files' existing restricted-import, ref-during-render, and fast-refresh findings.

oobabooga and others added 2 commits July 27, 2026 22:50
Main's unslothai#7455 extracted the tool script block into a shared ToolCodeCell and
re-introduced a plain blob-anchor download there, so this branch's change to
tool-ui-python.tsx no longer applies. Take main's refactor and re-apply the
native-save fix where the download now lives:

- tool-code-cell.tsx routes Download through the shared downloadFile boundary,
  so browsers keep the normal download and Tauri gets the native save chooser.
  Cancellation stays silent, a real failure toasts.
- The terminal card downloads command.sh through that same cell, so add a shell
  arm to the Tauri save_filter and cover both names in the generic fallback.
- tool-group.tsx keeps the python ungrouping exception (merged cleanly).
@danielhanchen

Copy link
Copy Markdown
Member

@codex review

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

Copy link
Copy Markdown

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: 30e41d5d22

ℹ️ 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 on lines +278 to 279
if (toolCount <= 1 || containsUngroupedTool) {
return <>{children}</>;

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 Keep completed Python content visible after ungrouping

When a persisted completed turn is reopened, this return only removes the outer aggregate group; each Python child still mounts ToolFallbackRoot defaultOpen={isRunning} with isRunning === false, and ToolCodeCell remains inside ToolFallbackContent (tool-ui-python.tsx, lines 91–104). Consequently, the scripts and Download controls in the reported history-hydration scenario are still hidden behind individually collapsed Python cards, so the change does not provide the promised persistent visibility unless those cards are opened or the code cell is moved outside their collapsible content.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Correct, and confirmed against a running Studio: with only the ungrouping change, reopening a persisted turn with two adjacent Python calls left two tool-fallback-root cards in data-state="closed" and zero Download controls in the DOM.

Fixed in d4169a4 by rendering ToolCodeCell outside ToolFallbackContent for Python, restoring the #7240 behaviour that #7455 folded back inside when it unified the code cell. Same scenario now shows both scripts and both Download controls with no clicks, and Download still saves byte-exact script.py. Status, output and images still collapse; the terminal card keeps its command inside the collapsible.

Ungrouping the aggregate tool group was not enough on its own. Each Python
card still mounts with defaultOpen={isRunning}, so on a reopened turn the
script and its Copy/Download controls stayed hidden behind the card's own
chevron and the reported issue persisted.

Render ToolCodeCell outside ToolFallbackContent for Python, restoring the
behaviour from unslothai#7240 that unslothai#7455 folded back inside when it unified the code
cell. Status, output and images still collapse. Terminal keeps its command
inside the collapsible: a one-line command is not the artifact a user reopens
a thread to retrieve, a script is.

Verified against a running Studio: reopening a persisted turn with two
adjacent Python calls now shows both scripts and both Download controls with
no clicks, and Download still saves byte-exact script.py.
@danielhanchen

Copy link
Copy Markdown
Member

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Another round soon, please!

Reviewed commit: d4169a43b4

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

@danielhanchen
danielhanchen merged commit e3ae08e into unslothai:main Jul 28, 2026
35 of 36 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants