Add temporary chat file attachments - #245
Merged
Merged
Conversation
Two things that I think would be helpful: 1) SessionAttachmentManager._session_root roots everything at _user_root(user), which for a non-BeakerUser request falls back to root_dir — i.e. the working directory. In local mode (BeakerNotebookApp), that means running beaker notebook in any shell drops a .beaker/session-attachments/ tree into whatever CWD you launched from (which is also why the PR needs the new .gitignore entry). For a "temporary" store, I'd rather not scatter state across arbitrary working directories. - Suggestion: key the location on the app rather than on request identity, and send local-mode attachments to the shared data dir we already use for notebook snapshots (BEAKER_LOCAL_DATA_PATH). I've got a small patch that adds a local_mode property (False on BaseBeakerApp, True on BeakerNotebookApp) and branches placement in a _attachments_base() helper — local → BEAKER_LOCAL_DATA_PATH/session-attachments, server → the existing per-user virtual-home path. 2) Also tightens cleanup() so it doesn't remove dirs above the session-attachments dir. The two-level climb could remove the shared data root, potentially causing a race condition where one session tries to write to a path that it thinks exists but has just been deleted.
Collaborator
|
This is very cool and very slick and works well. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds temporary, session-scoped file attachments to the notebook chat interface.
Users can drag files onto the chat composer or select them with the attachment button. Files are uploaded before the message is sent, displayed as removable attachment chips, and made available to the agent for the duration of the notebook session.
ZIP archives are extracted automatically using configurable safety limits. The original ZIP is retained so the agent can inspect or troubleshoot it if automatic extraction fails.
Attachments remain separate from the notebook filesystem and are not serialized into the notebook document.
User experience
Please inspect the attached file(s).The existing file browser remains the mechanism for permanent notebook files. Chat attachments are intentionally temporary.
Storage and lifecycle
Attachments are stored beneath a hidden runtime directory:
.beaker/session-attachments/<server-instance>/<session-hash>/<attachment-id>/Each attachment has:
Files are scoped to the owning user and notebook session.
Draft attachments become committed when their IDs are included in an LLM request and retrieved by the authenticated kernel. Attachments from prior messages remain available to the agent for the rest of the session.
Cleanup occurs when:
The runtime attachment directory is ignored by Git so uploaded files cannot be committed accidentally.
ZIP handling
ZIP files are detected by filename or MIME type and extracted into the attachment's temporary directory.
Extraction rejects:
..traversal.Extraction is performed in a temporary directory and moved into place only after it succeeds.
If extraction fails:
Agent integration
The query message sends attachment IDs to the Beaker kernel.
Before starting the agent loop, the kernel:
The agent receives a conditional
session_attachmentsstate block containing:The agent also receives a
get_session_attachmenttool that:run_code.This allows workflows such as uploading a CSV and asking the agent to analyze it without first copying it into the permanent notebook filesystem.
Authentication and ownership
Attachment API operations resolve the notebook session and enforce either:
The handler does not trust a kernel ID parsed directly from a request header. The identity provider verifies the token first and returns the authenticated kernel ID. Digest comparison uses
hmac.compare_digest.Invalid or forged kernel headers return HTTP 403 rather than falling back to browser authentication.
A broader redesign of the existing kernel authentication protocol—such as HMAC tokens, nonce expiration, and replay protection—is intentionally left for a separate authentication-focused PR.
Configuration
The following settings are configurable through Beaker configuration or environment variables:
ATTACHMENT_MAX_UPLOAD_BYTESATTACHMENT_MAX_SESSION_BYTESATTACHMENT_MAX_EXTRACTED_BYTESATTACHMENT_MAX_ARCHIVE_ENTRIESATTACHMENT_MAX_ARCHIVE_RATIOTesting
Automated verification completed:
git diff --checkThe Playwright test covers:
Manual testing also covered individual files, multiple files, ZIP archives, and agent access to uploaded content.
Follow-up hardening
These are intentionally visible for reviewer discussion:
Out of scope