-
Notifications
You must be signed in to change notification settings - Fork 3k
feat(web-shell): unify file uploads and references #9477
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
5bcd903
feat(web-shell): unify file upload and reference flow
daca1ee
fix(web-shell): address attachment review feedback
4624b55
fix(web-shell): address attachment review feedback
1726d54
Merge remote-tracking branch 'origin/main' into codex/web-shell-drop-…
85a261e
fix(web-shell): address attachment review feedback
1242625
Merge remote-tracking branch 'origin/main' into codex/web-shell-drop-…
c918199
fix(webui): restore optimistic text prompts
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| # Session attachment references | ||
|
|
||
| ## Problem | ||
|
|
||
| Embedding image base64 and file bytes in daemon requests, queues, events, and | ||
| replay data duplicates potentially large payloads. Attachments also need to | ||
| remain previewable after the daemon restarts. | ||
|
|
||
| ## Design | ||
|
|
||
| The daemon writes image and arbitrary file bytes to the workspace runtime's attachment | ||
| directory and returns a filename-based reference: | ||
|
|
||
| ```ts | ||
| { | ||
| type: 'image' | 'resource'; | ||
| attachmentId: string; | ||
| mimeType: string; | ||
| size: number; | ||
| } | ||
| ``` | ||
|
|
||
| The attachment ID is the stored filename. Duplicate names use the platform | ||
| convention `name (1).ext`, `name (2).ext`, and so on. There is no in-memory | ||
| attachment index or sidecar metadata; MIME type and size are derived from the | ||
| stored file when it is read. | ||
|
|
||
| Prompt and mid-turn APIs carry references through queues, events, and | ||
| transcript metadata. The bridge resolves them only when dispatching to the ACP | ||
| child. The TypeScript session client hydrates the same references for previews | ||
| and replay rendering through the authenticated attachment route. | ||
| Text resources resolve as ACP text; other file formats resolve as ACP blobs, so | ||
| their original bytes are not decoded or altered in the browser. | ||
|
|
||
| ## Ownership and lifecycle | ||
|
|
||
| - Storage lives at `~/.qwen/tmp/<workspace-hash>/attachments/session-<id>/` | ||
| (or the equivalent custom runtime directory). | ||
| - The resolved live-session owner and client authorization protect every | ||
| upload, read, and removal operation. | ||
| - Closing a daemon or detaching a client closes handles but keeps the files. | ||
| - Permanently deleting a session removes its attachment directory. | ||
| - No TTL, sweeper, retained-media cache, or restart reconstruction index is | ||
| used. | ||
| - Each attachment is limited to 8 MiB. Sessions have no cumulative attachment | ||
| size or count limit. | ||
|
|
||
| The unified capability is `session_attachments`; the unified HTTP surface is | ||
| `/session/:id/attachments`. There is no `session_media`, `/media`, or `mediaId` | ||
| compatibility path. |
This file was deleted.
Oops, something went wrong.
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| # Web Shell dropped-file intent choice | ||
|
|
||
| ## Problem | ||
|
|
||
| The composer currently infers intent from file type: image-only drops become | ||
| prompt attachments, while ordinary or mixed drops upload to the workspace and | ||
| insert `@` references. File type does not express user intent. A user may want | ||
| an image persisted in the workspace, or a text file attached only to the next | ||
| prompt. | ||
|
|
||
| ## Design | ||
|
|
||
| When workspace upload is available, a drop containing one or more files opens | ||
| one modal with their names, sizes, and three actions: | ||
|
|
||
| - **Reference content** uses the existing prompt-attachment ingestion path. | ||
| The original browser files remain local to the draft. On submit they upload | ||
| unchanged to the daemon's session attachment store under the | ||
| workspace-scoped Qwen runtime temp directory. Prompt JSON carries | ||
| filename-based attachment IDs; the bridge resolves them only at dispatch. | ||
| - **Upload to workspace** uses the existing upload queue, configured upload | ||
| directory, progress UI, and server-confirmed `@` reference insertion. | ||
| - **Cancel** discards the drop. | ||
|
|
||
| Every file type can be referenced. Multi-file drops use the same choice as | ||
| single files; the browser does not pre-disable referencing based on the | ||
| the files already present in the current draft. | ||
|
|
||
| The browser `File` objects are copied synchronously during the drop event, so | ||
| the choice does not depend on a `DataTransfer` after the event returns. The | ||
| dialog closes if the composer target changes or upload becomes unavailable. | ||
|
|
||
| When workspace upload is unavailable, drops keep the existing attachment | ||
| behavior instead of showing an upload action that cannot succeed. Host-level | ||
| `fileUploadEnabled={false}` retains its existing contract and disables all | ||
| file drag-in. Clipboard paste and the `@` panel upload item are unchanged. | ||
|
|
||
| File attachment chips are interactive before and after optimistic submission. | ||
| Opening one shows the referenced file in the right-side preview panel. | ||
| Completed workspace uploads and their file tags open the same panel by reading | ||
| the uploaded workspace path. Image attachments retain their existing thumbnail | ||
| and image-panel behavior. | ||
|
|
||
| ## Storage and compatibility | ||
|
|
||
| The default attachment root is | ||
| `~/.qwen/tmp/<workspace-hash>/attachments/`, resolved through | ||
| `Storage.getProjectTempDir()` so custom runtime directories continue to work. | ||
| Each session owns `session-<encoded-session-id>/`. Files use their stored names | ||
| as attachment IDs, with ` (1)` suffixes for duplicates. Daemon shutdown and | ||
| client detach keep the directory; permanent session deletion removes it. | ||
|
|
||
| Images and files use the same `session_attachments` capability, | ||
| `/attachments` routes, and `attachmentId` references. There is no retained | ||
| media cache, TTL cleanup, in-memory filename index, or legacy `mediaId` path. | ||
|
|
||
| ## Scope | ||
|
|
||
| Attachment admission limits are enforced by ingestion and the daemon rather | ||
| than by the choice dialog. |
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
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
Oops, something went wrong.
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.