Repository navigation
Add a shared filesystem for Daytona and Modal - #37
Merged
Merged
Conversation
Callers read, write, copy, list, and remove files through one handle, and a bad sandbox path fails before either provider is contacted. Co-authored-by: Cursor <cursoragent@cursor.com> Entire-Checkpoint: 01M6C1K9KW5FNR21W2BZS6BWZ3
Callers set parents to false when the parent must already exist. Daytona rejects that value because it always creates parents. Co-authored-by: Cursor <cursoragent@cursor.com> Entire-Checkpoint: 01M6C2XQHGRKY18E31FB5F53EK
…seconds, and classify local copy failures as local path errors. Co-authored-by: Cursor <cursoragent@cursor.com> Entire-Checkpoint: 01M6C55VEFDKRAEPJEGEGXQ4BH
…er limit, and classify a local copy path before the provider call. Co-authored-by: Cursor <cursoragent@cursor.com> Entire-Checkpoint: 01M6DBNWVAXVAMBM4EC9SS52CW
Co-authored-by: Cursor <cursoragent@cursor.com> Entire-Checkpoint: 01M6DBV2MFRNGSQPGPKD9BEDCN
Co-authored-by: Cursor <cursoragent@cursor.com> Entire-Checkpoint: 01M6E8MGMP5YKH6CDDZFVZ6R8P
…e, and errors. Co-authored-by: Cursor <cursoragent@cursor.com> Entire-Checkpoint: 01M6E9DP0J5EETXYBSZZF2QRGR
go work sync and go list -m all walk the full grpc requirement graph and record go.mod checksums for modules the build never imports; sandbox-kit test go now rejects that drift. Co-authored-by: Cursor <cursoragent@cursor.com> Entire-Checkpoint: 01M6EDB2EZ9MBSYEEPPZPTBVMD
Keep PathError mapping on copy only, and align naming and website path docs with the filesystem surface. Co-authored-by: Cursor <cursoragent@cursor.com> Entire-Checkpoint: 01M6EQHY2KBN7Z420A2Q52VP2H
Daytona's DownloadFile only calls os.WriteFile, so Kit creates the parent first and matches Modal and TypeScript Daytona. Co-authored-by: Cursor <cursoragent@cursor.com> Entire-Checkpoint: 01M6ERM5E74H2FH29EDWMSCBDA
Co-authored-by: Cursor <cursoragent@cursor.com> Entire-Checkpoint: 01M6G0HDXNMWEXE4XHEAM8D589
Keep guides, godoc/JSDoc, and Daytona TypeScript copy-out parent creation consistent with the eight file operations both providers implement. Co-authored-by: Cursor <cursoragent@cursor.com> Entire-Checkpoint: 01M6G1G8268BH20WQZFPK2TTE9
This was referenced Nov 3, 2026
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
WriteFilenormalizes only a nil buffer to an empty slice before the provider call. A non-nil empty slice is left alone.parentsdefaults to true, so creating a directory also creates missing parents. Set it to false when the parent must already exist. Daytona rejects that value. Modal requires the parent and returns an error if the new directory is already there.2000is two seconds.1500is rejected, and the field istimeout. An omitted timeout on those four calls is passed as0, so Daytona adds no transfer limit and the abort signal carries the client deadline. Directory, list, metadata, and delete calls use the abort signal, so1500ends the call at 1.5 seconds. Every Go file call uses the context as the deadline. Modal file calls use the context or the abort signal.local_path. Daytona and Modal, in Go and TypeScript, make that decision before the provider call. Copy onto the machine creates a missing local parent directory on every provider. A local destination that is already a directory is an invalid argument with the same field. Go Daytona creates that parent in Kit because Daytona'sDownloadFileonly callsos.WriteFile.path,permissions,owner, andgroupwhen Daytona sends them.modifiedAtkeeps a fractional timestamp. An empty field stays unset, and an unreadablemodifiedAtis omitted. TypeScript Daytona already mapped those fields.go.work.sumkeeps only the checksums written by loading the workspace packages.go work syncandgo list -m allwalk the fullgoogle.golang.org/grpcrequirement graph and downloadgo.modfiles for modules the build never imports, including plot, PDF, font, and example modules named by gRPC test requirements.sandbox-kit test gorebuilds that sum from package loads and fails when the committed file drifts. Update a module's dependencies inside that module withGOWORK=off(go get, thengo mod tidy).How a call moves
A relative path, a blank path, or a path that contains a NUL byte stops at the path check. The provider is not called. An omitted timeout uses the client deadline. Explicit zero adds no Kit deadline.
TypeScript Daytona read, write, and copy pass the timeout to Daytona as a whole number of seconds.
2000milliseconds is 2 seconds.1500milliseconds is 1.5 seconds, so those calls reject it. The field istimeout. An omitted timeout, and an explicit0, are passed as0. Daytona adds no transfer limit. The abort signal carries the client deadline. A read with that0uses Daytona's multi-file download for the one path, becausedownloadFile(path, 0)drops the0and keeps Daytona's 30-minute default.2000still usesdownloadFile(path, 2).makeDirectory,listDirectory,stat, andremoveuse the abort signal, so1500ends the call at 1.5 seconds. Every Go file call uses the context as the deadline, so1500 * time.Millisecondends the call at 1.5 seconds. Modal file calls use the context or the abort signal.One method, two native calls
flowchart TB subgraph kit [Sandbox Kit] readFile[ReadFile] writeFile[WriteFile] copyIn[CopyFromLocal] copyOut[CopyToLocal] mkdir[MakeDirectory] listDir[ListDirectory] stat[Stat] remove[Remove] end subgraph daytona [Daytona SDK] download[DownloadFile] upload[UploadFile] folder[CreateFolder] listFiles[ListFiles] details[GetFileInfo] deleteFile[DeleteFile] end subgraph modal [Modal SDK] readBytes[ReadBytes] writeBytes[WriteBytes] fromLocal[CopyFromLocal] toLocal[CopyToLocal] makeDir[MakeDirectory] listFilesM[ListFiles] statM[Stat] removeM[Remove] end readFile --> download readFile --> readBytes writeFile --> upload writeFile --> writeBytes copyIn --> upload copyIn --> fromLocal copyOut --> download copyOut --> toLocal mkdir --> folder mkdir --> makeDir listDir --> listFiles listDir --> listFilesM stat --> details stat --> statM remove --> deleteFile remove --> removeMGo Daytona list and stat call the toolbox
ListFilesandGetFileInfodirectly. The high-level Daytona file type omitspathon stat, and it omitspermissions,owner,group, and a fractionalmodifiedAton both calls.Creating a directory
parentsdefaults to true. An omitted flag and an explicit true both create missing parents.Modal accepts a directory that already exists when
parentsis true. Daytona returns the provider error when it already exists.Removedeletes a file or an empty directory unlessrecursiveis set.Staton a symlink describes the symlink. Modal can report a symlink. Daytona reports a file or a directory.permissions,owner, andgroupare set when the provider supplies them.modifiedAtis set when the provider supplies a time.Copying a local file
A missing file passed to copy from the local machine is not found before the provider reads it. A directory at that path is an invalid argument. The field is
local_path. Daytona and Modal, in Go and TypeScript, do this before the native copy call.Copy onto the machine creates a missing local parent directory for Daytona and Modal in both languages. A local destination that is already a directory is an invalid argument with the same field. Go Daytona creates the parent in Kit before
DownloadFile, because that SDK write usesos.WriteFileonly.Where it sits
Closing the client or the handle does not delete the files or the sandbox.
Test plan
GOWORK=off go testinsdks/go/sandbox,sdks/go/providers/daytona, andsdks/go/providers/modalnpm testinsdks/typescript/sandbox,sdks/typescript/providers/daytona, andsdks/typescript/providers/modalparents: falsebefore the provider is called, and Modal requires the parent to exist1500milliseconds and pass2000as 2 seconds0through the multi-file download, and write and copy pass01500milliseconds as the deadlinelocal_path, and a local directory is an invalid argument with the same fieldpath,permissions,owner,group, and a fractionalmodifiedAtwhen Daytona sends them[]byte{}before the provider callsandbox-kit test gofails whengo.work.sumcontains checksums that loading the workspace packages does not write