You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 6713fab
Browse filesBrowse the repository at this point in the historyBrowse files
feat(desktop): import local files from the background executor (#8672)
* feat(desktop): import local files from the background executor
A chat whose turn runs on the desktop can now import a local file or folder
into the workspace while the user is elsewhere, instead of the background
executor answering import_local_files as not run.
- Sim: PUT /api/desktop/tool/import stores one entry of a claimed import.
The entry is admitted before its body is read: the caller's session must
own the device, the call must be a running import_local_files bound to that
device, and the request must carry the token that claimed it. The target
workspace and folder come from Sim's record of the call, never from the
request, and writing there is authorized as any file creation is. Each
path segment becomes a folder under the target, reusing folders already
there (find or create, converging when two land at once); a file never
overwrites one already there.
- Desktop: the runner reads the manifest from the call's own arguments,
sends each directory, then each file in chunks checked against the
manifest's revision, and reports what landed. A failure part way reports
the partial result as outcome unknown, not to be retried. Stop aborts
between entries and mid-upload.
- The chunked read, the size check and the result projections move to
@sim/desktop-bridge/tool-results, so the chat view's import and the
background one report the same shapes.
* fix(desktop): imports arrive whole, survive the rate limit, and record their folders
- The proxy no longer runs for the desktop's raw upload routes (import, and
the browser file transfer that has the same shape). Running it made Next
buffer the body and cut it off at its 10 MB proxy limit. The import route
also requires a declared length and refuses a body that does not match
it, so a cut-off file is never stored as complete.
- A file entry with no body is refused instead of stored as an empty file.
- A name Sim cannot store (one with a backslash) is refused for the whole
import before anything lands, and at the contract.
- A chunk that runs past the size the manifest listed is refused, like one
that ends early.
- A rate-limited entry is sent again after the limit clears. A 429 means
nothing was stored, so a large tree no longer fails part way.
- Folders an import creates are audited as folder creations and announced to
the workspace's file views, as folders made by hand are.
- Tests record what the fake Sim stored instead of asserting mock calls. The
integration suite removes its audit rows.
* fix(desktop): an import the rate limit never let start stays safe to ask for again
When Sim's rate limit outlasts every retry, it refused the entry outright,
so the result lists exactly what landed instead of being outcome unknown.
An import where nothing landed is no longer marked do-not-retry.
* fix(desktop): harden the raw upload routes now that they skip the proxy
- The desktop import and browser file routes refuse the dedicated MCP host
themselves, as the proxy did before they left its matcher.
- The import's execution token travels in a header, not the query string,
so it stays out of load balancer, CDN and trace URLs.
- A name that trims to nothing or to a dot segment is refused at the
contract and, for the whole import, before anything lands, through one
shared rule. Such a name no longer surfaces as a 500 part way through.
- The browser download route also requires a declared length and refuses a
body that does not match it.
- Route tests cover 411, 413, a length mismatch, an entry that is not
admitted reading no body, the 401 mappings, the missing token header and
an unstorable name.
* fix(desktop): keep accepting downloads from shells that send no declared length
The truncation check applies whenever a download declares its length. A
shell already in use that streams one without a length is still accepted
under the byte ceiling. The E2E fixture's import route now refuses a file
without a declared length, as Sim's does, so the device is proven to send
one.
* docs(desktop): document the import entry parser
* test(desktop): the raw upload routes serve nothing on the dedicated MCP host
* test(desktop): an import entry's execution token travels in a header, never the URL
* docs(desktop): document the import entry input
0 commit comments