Skip to content

Add shared Process.Run for Daytona and Modal - #40

Merged
Nabhag8848 merged 12 commits into
mainfrom
feat/sandbox-process
Nov 4, 2026
Merged

Nabhag8848 merged 12 commits into
mainfrom
feat/sandbox-process

Conversation

@Nabhag8848

@Nabhag8848 Nabhag8848 commented Nov 3, 2026 •

Copy link
Copy Markdown
Member

Summary

Adds a shared blocking command API on the sandbox handle, documents it across examples and the docs site, and hardens Go cloning / timeout / Modal cancel behavior against real Daytona and Modal SDK behavior.

Surface Go TypeScript
Entry instance.Process().Run(ctx, opts) sandbox.process.run(opts)
Command exactly one of Argv / Shell exactly one of argv / shell
Result exit_code, stdout, stderr exitCode, stdout, stderr

Non-zero exit codes are successful results, not SDK errors. Sessions, PTY, streaming handles, and Daytona code_run stay out of this cut.


What changed (by layer)

flowchart TB
  subgraph contracts [Contracts]
    Proto["proto ExecOptions / ExecResult"]
    Inventory["specs/validation.yaml ExecOptions"]
  end
  subgraph core [Core SDKs]
    GoCore["Go sandbox.Process"]
    TSCore["TS sandbox.process"]
    Clone["Go cloneExecOptions / cloneExecResult"]
  end
  subgraph providers [Providers]
    DGo["Go Daytona"]
    DTS["TS Daytona"]
    MGo["Go Modal + stream close on cancel"]
    MTS["TS Modal"]
  end
  subgraph docs [Docs and site]
    Guide["docs/process.md + /docs/process"]
    Examples["20 process examples"]
    Site["Provider switch + home sample"]
  end
  Proto --> GoCore
  Proto --> TSCore
  Inventory --> GoCore
  Inventory --> TSCore
  GoCore --> Clone
  GoCore --> DGo
  GoCore --> MGo
  TSCore --> DTS
  TSCore --> MTS
  GoCore --> Guide
  TSCore --> Guide
  Guide --> Examples
  Guide --> Site
Loading

Call path

sequenceDiagram
  participant App
  participant Kit as Kit Process.Run
  participant Validate as Kit validation
  participant Adapter as Daytona or Modal adapter
  participant Native as Provider SDK
  App->>Kit: Run(argv|shell, cwd?, env?, timeout?)
  Kit->>Validate: argv XOR shell, blank shell, absolute cwd
  alt invalid
    Validate-->>App: InvalidArgument (field set)
  else valid
    Kit->>Kit: operation deadline from timeout / client
    Kit->>Adapter: mapped request
    Adapter->>Adapter: whole-second timeout gate
    Adapter->>Native: executeCommand / sandbox.exec
    Native-->>Adapter: exit + streams
    Adapter-->>Kit: ExecResult
    Note over Kit: Go preserves empty env / empty stdout|stderr after clone
    Kit-->>App: ExecResult (nonzero exit is OK)
  end
Loading

Provider mapping

flowchart LR
  subgraph kit [Kit ExecOptions]
    Argv["argv"]
    Shell["shell"]
    Cwd["working_directory"]
    Env["environment"]
    Timeout["timeout"]
  end
  subgraph daytona [Daytona]
    DCmd["POSIX-quoted shell string"]
    DShell["shell as-is"]
    DExec["executeCommand"]
    DOut["stdout only; stderr empty"]
    DT0["timeout 0 when Kit omit/zero<br/>avoids native 10s default"]
  end
  subgraph modal [Modal]
    MArgv["argv as-is"]
    MBash["bash -c shell"]
    MExec["sandbox.exec + drain pipes"]
    MOut["stdout + stderr"]
    MT0["Go Timeout 0 / TS omit timeoutMs<br/>never send timeoutMs: 0"]
  end
  Argv --> DCmd --> DExec --> DOut
  Shell --> DShell --> DExec
  Timeout --> DT0 --> DExec
  Argv --> MArgv --> MExec --> MOut
  Shell --> MBash --> MExec
  Timeout --> MT0 --> MExec
  Cwd --> DExec
  Cwd --> MExec
  Env --> DExec
  Env --> MExec
Loading
Kit input Daytona Modal
argv: ["echo", "hi"] POSIX-quoted shell string argv as-is
shell: "echo hi" shell as-is ["bash", "-c", "echo hi"]
omitted / zero timeout command timeout 0 no limit (TS omits timeoutMs; Go Timeout: 0)
fractional timeout (1500 ms) rejected (timeout) rejected (timeout)
stderr empty (Go: non-nil empty slice) collected from pipe
empty environment {} Kit keeps explicit; TS native SDK may coerce to omit (same runtime: add no vars) Kit keeps explicit

Review fixes in this branch

1. Go empty-collection cloning (bug fix)

proto.Clone drops empty maps and empty byte slices. Process used the naive cloneMessage, so:

  • Environment: map[string]string{} became nil before the provider
  • Daytona Stderr: []byte{} (and empty stdout) became nil after return

Fix: cloneExecOptions / cloneExecResult (same pattern as Create). Covered by unit + Process.Run tests.

flowchart LR
  In["ExecOptions / ExecResult<br/>empty env or []byte{}"] --> Clone["cloneExec*"]
  Clone --> Out["owned copy<br/>empties preserved"]
  Out --> Provider["provider sees non-nil empty env"]
  Out --> Caller["caller sees non-nil empty stderr"]
Loading

2. Go Modal cancel no longer hangs on stdio drain (bug fix)

Modal wires exec stdout/stderr with context.Background() (and no stream deadline when command timeout is 0). Kit's Wait(ctx) respects cancel, but the old collectProcess still wg.Wait()'d on io.ReadAll, so a client deadline could leave the caller blocked until the remote process EOFs.

Fix: on Wait failure, close stdout/stderr so blocked reads unblock (matches Modal's Close-unblocks-read contract), then return the wait error.

sequenceDiagram
  participant Kit as collectProcess
  participant Wait as process.Wait(ctx)
  participant Out as stdout/stderr ReadAll
  Kit->>Out: start drain goroutines
  Kit->>Wait: wait for exit
  Note over Wait: ctx canceled / deadline
  Wait-->>Kit: error
  Kit->>Out: Close streams
  Out-->>Kit: reads unblock
  Kit-->>Kit: return wait error
Loading

3. Shared whole-second timeout helper

sdk.WholeSecondDuration shared by Go Daytona and Modal adapters. Behavior unchanged: nil/zero → 0; non-whole seconds rejected.

4. Docs honesty

  • Daytona omit/zero → always send 0 (native default is 10s)
  • Modal TS must omit timeoutMs (Modal rejects 0)
  • TypeScript abort is soft on the remote side: Kit rejects the await; Daytona/Modal exec often ignore AbortSignal so the command may keep running. The handle still stays busy until that provider call settles (see §7).
  • Empty env wording matches runtime (incl. Daytona TS {} coerce)

5. Daytona TypeScript process tests

Covers argv POSIX quoting, omit/zero → 0, cwd/env forwarding, fractional reject, empty stderr.

6. Small cleanups

  • Shared Go absolutePath for sandbox path + working directory
  • Modal #file → #withSandbox
  • Portable proto timeout comment + regenerated contracts; provider details stay in docs / Go alias

7. TypeScript handle serialization holds through in-flight abort (bug fix)

Abort/timeout must reject the caller promptly, but the next lifecycle, filesystem, or process call on the same handle must not overlap native work that providers ignore mid-call. Matching Go and the documented one-at-a-time contract:

  1. #serialized starts the provider promise (work) once the gate is acquired.
  2. awaitWithSignal(work, signal) races that already-started promise so abort rejects without dropping it.
  3. finally unlocks when work settles (not when the caller rejects), so a queued follow-up waits.

Lifecycle / process / filesystem paths stop wrapping provider calls in a second factory-style awaitWithSignal that could start work after unlock. Docs (concepts, lifecycle, filesystem, process) state the busy-until-settle rule.

sequenceDiagram
  participant App
  participant Gate as Sandbox.#serialized
  participant Native as Provider call
  App->>Gate: start({ signal })
  Gate->>Native: work = body(signal)
  Note over App: abort / deadline
  Gate-->>App: reject Canceled (prompt)
  Note over Gate,Native: gate still held
  App->>Gate: start() / run() / readFile()
  Note over Gate: waits on previous unlock
  Native-->>Gate: settles
  Gate->>Gate: unlock
  Gate->>Native: second provider call
  Native-->>App: result
Loading
flowchart TB
  subgraph before [Before: unlock on caller reject]
    B1["acquire gate"] --> B2["awaitWithSignal factory"]
    B2 -->|"abort rejects"| B3["finally unlock"]
    B3 --> B4["next call starts<br/>while native still in flight"]
  end
  subgraph after [After: unlock when work settles]
    A1["acquire gate"] --> A2["work = body(signal)"]
    A2 --> A3["awaitWithSignal(work)"]
    A3 -->|"abort rejects caller"| A4["finally: unlock on work.then"]
    A4 --> A5["next call waits<br/>until native settles"]
  end
Loading
flowchart LR
  subgraph api [awaitWithSignal]
    Factory["() => Promise<br/>start only if not aborted"]
    Started["Promise<br/>keep alive after abort"]
  end
  Queue["wait for previous tail"] --> Factory
  InFlight["race in-flight provider work"] --> Started
  Started --> Unlock["unlock when settled"]
Loading

Covered by client tests: aborted in-flight start, process.run, and filesystem.readFile keep maximumActive === 1 until release.


Docs site

  • /docs/process guide with provider-specific tables via <ForProvider>
  • Page-level Daytona / Modal control (persisted); Concepts + rewritten Quickstart / Configuration / Create / Lifecycle / Filesystem / Errors / Examples
  • One-viewport home with TypeScript/Go create-and-run sample
  • Static Pages fixes: no double /kit prefix; Copy / View markdown / Open in AI target prerendered .md files

Examples

20 runnable projects under examples/{go,typescript}/{daytona,modal}/process/:

Topic Projects
argv command run-*-command
shell string run-*-shell-command
working directory run-*-with-cwd
environment run-*-with-env
non-zero exit run-*-check-exit

Test plan

  • Go: sdks/go/sandbox, sandbox/tests, Daytona + Modal providers (clone, timeouts, process)
  • TypeScript: sandbox + Daytona + Modal package tests (Modal omit-timeoutMs, Daytona process mapping)
  • TypeScript: handle serialization held until aborted in-flight lifecycle / process / filesystem calls settle
  • Contracts regenerated after proto comment update
  • Docs site typecheck; provider switch / landing verified locally
  • Smoke-run process examples against live Daytona and Modal
  • Confirm relative cwd, blank shell, and argv+shell fail with documented fields
  • Spot-check Go Modal client-deadline cancel returns promptly while a long command runs (omit command timeout)
  • Spot-check /docs/process, provider switch, landing, and markdown actions after Pages deploy

Nabhag8848 and others added 5 commits November 3, 2026 13:23
Expose one blocking command surface on the sandbox handle so callers get exit
code, stdout, and stderr without provider-specific exec APIs. Reject argv/shell
and path mistakes in Kit, map whole-second timeouts honestly, and keep
sessions, PTY, and streaming out of this cut.

Co-authored-by: Cursor <cursoragent@cursor.com>
Entire-Checkpoint: 01M6G6CECRB6HJBQW71VA48Q5S
Expand shell/cwd/env/exit coverage across providers and keep npm, pkg.go.dev, and website docs aligned with the shared process surface.

Co-authored-by: Cursor <cursoragent@cursor.com>
Entire-Checkpoint: 01M6G76W4MQK433BRHYDBMDZPC
Guide samples and edge cases follow the selected provider, and the landing page shows a TypeScript/Go create-and-run snippet without scrolling.

Co-authored-by: Cursor <cursoragent@cursor.com>
Entire-Checkpoint: 01M6GA167VFNR88C6H0YC83GD8
Avoid double-prefixing markdown URLs under /kit, point AI open links at the static .md files, and style the provider menu like the other page actions.

Co-authored-by: Cursor <cursoragent@cursor.com>
Entire-Checkpoint: 01M6GAMHJX21Q5MJYBW5WSNNPM
Omit Modal TypeScript timeoutMs when unset or zero so native exec no longer
rejects the default path, keep Daytona stderr non-nil empty, and align
validation inventory, tests, and user-facing process docs with the wire
behavior.

Co-authored-by: Cursor <cursoragent@cursor.com>
Entire-Checkpoint: 01M6H0V2KEEVBD4ZW1N7C7KFKS
@Nabhag8848 Nabhag8848 self-assigned this Nov 3, 2026
Nabhag8848 and others added 7 commits November 4, 2026 12:00
Preserve empty env maps and empty stdout/stderr through Go Process.Run,
share whole-second timeout mapping, and document Daytona/Modal timeout,
empty-env, and TypeScript soft-abort behavior honestly.

Co-authored-by: Cursor <cursoragent@cursor.com>
Entire-Checkpoint: 01M6JM18BHS64VZ626305YECMT
Close exec stdout/stderr after a failed Wait so ReadAll does not hang on
Background-wired Modal streams after the Kit deadline.

Co-authored-by: Cursor <cursoragent@cursor.com>
Entire-Checkpoint: 01M6JMP3MEVCQZY68M33PP2S6W
Clarify timeouts, cancel, env, and provider output in guides, npm/pkg.go.dev
READMEs, and process example edge cases without kit-builder jargon.

Co-authored-by: Cursor <cursoragent@cursor.com>
Entire-Checkpoint: 01M6JN1QZXJ7MR7WGZJHWBX5WF
Build the sidebar page tree in the component instead of serializePageTree, which pulls in react-dom/server.edge and breaks client-side route changes with no server to call on github.io.

Co-authored-by: Cursor <cursoragent@cursor.com>
Entire-Checkpoint: 01M6JNSSH6Z8AKV63P026ND35D
…ettle.

Abort and timeout still reject the caller promptly, but the next lifecycle,
filesystem, or process call on the same handle waits until the native work
finishes—matching Go and the documented one-at-a-time contract.

Co-authored-by: Cursor <cursoragent@cursor.com>
Entire-Checkpoint: 01M6JQBRJZNMFPVHRK29TFY1CY
Code blocks that use Client, providers, LifecycleCapability, or Go sandbox
types now show the imports needed to copy them into a project.

Co-authored-by: Cursor <cursoragent@cursor.com>
Entire-Checkpoint: 01M6JR1CT5HHXA8TTCX1M4KYSF
Document shell blankness after trim in the validation inventory so the
timeout and cancel story matches what callers and tests already enforce.

Co-authored-by: Cursor <cursoragent@cursor.com>
Entire-Checkpoint: 01M6JSRGZB4B1SSGVCP2WFVTF0
@Nabhag8848

Copy link
Copy Markdown
Member Author

someone cut corners## Summary

Adds a shared blocking command API on the sandbox handle, documents it across examples and the docs site, and hardens Go cloning / timeout / Modal cancel behavior against real Daytona and Modal SDK behavior.

Surface Go TypeScript
Entry instance.Process().Run(ctx, opts) sandbox.process.run(opts)
Command exactly one of Argv / Shell exactly one of argv / shell
Result exit_code, stdout, stderr exitCode, stdout, stderr

Non-zero exit codes are successful results, not SDK errors. Sessions, PTY, streaming handles, and Daytona code_run stay out of this cut.


What changed (by layer)

flowchart TB
  subgraph contracts [Contracts]
    Proto["proto ExecOptions / ExecResult"]
    Inventory["specs/validation.yaml ExecOptions"]
  end
  subgraph core [Core SDKs]
    GoCore["Go sandbox.Process"]
    TSCore["TS sandbox.process"]
    Clone["Go cloneExecOptions / cloneExecResult"]
  end
  subgraph providers [Providers]
    DGo["Go Daytona"]
    DTS["TS Daytona"]
    MGo["Go Modal + stream close on cancel"]
    MTS["TS Modal"]
  end
  subgraph docs [Docs and site]
    Guide["docs/process.md + /docs/process"]
    Examples["24 process examples"]
    Site["Provider switch + home sample"]
  end
  Proto --> GoCore
  Proto --> TSCore
  Inventory --> GoCore
  Inventory --> TSCore
  GoCore --> Clone
  GoCore --> DGo
  GoCore --> MGo
  TSCore --> DTS
  TSCore --> MTS
  GoCore --> Guide
  TSCore --> Guide
  Guide --> Examples
  Guide --> Site
Loading

Call path

sequenceDiagram
  participant App
  participant Kit as Kit Process.Run
  participant Validate as Kit validation
  participant Adapter as Daytona or Modal adapter
  participant Native as Provider SDK
  App->>Kit: Run(argv|shell, cwd?, env?, timeout?)
  Kit->>Validate: argv XOR shell, blank shell after trim, absolute cwd
  alt invalid
    Validate-->>App: InvalidArgument (field set)
  else valid
    Kit->>Kit: operation deadline from timeout / client
    Kit->>Adapter: mapped request
    Adapter->>Adapter: whole-second timeout gate
    Adapter->>Native: executeCommand / sandbox.exec
    Native-->>Adapter: exit + streams
    Adapter-->>Kit: ExecResult
    Note over Kit: Go preserves empty env / empty stdout|stderr after clone
    Kit-->>App: ExecResult (nonzero exit is OK)
  end
Loading

Provider mapping

flowchart LR
  subgraph kit [Kit ExecOptions]
    Argv["argv"]
    Shell["shell"]
    Cwd["working_directory"]
    Env["environment"]
    Timeout["timeout"]
  end
  subgraph daytona [Daytona]
    DCmd["POSIX-quoted shell string"]
    DShell["shell as-is"]
    DExec["executeCommand"]
    DOut["stdout only; stderr empty"]
    DT0["timeout 0 when Kit omit/zero<br/>avoids native 10s default"]
  end
  subgraph modal [Modal]
    MArgv["argv as-is"]
    MBash["bash -c shell"]
    MExec["sandbox.exec + drain pipes"]
    MOut["stdout + stderr"]
    MT0["Go Timeout 0 / TS omit timeoutMs<br/>never send timeoutMs: 0"]
  end
  Argv --> DCmd --> DExec --> DOut
  Shell --> DShell --> DExec
  Timeout --> DT0 --> DExec
  Argv --> MArgv --> MExec --> MOut
  Shell --> MBash --> MExec
  Timeout --> MT0 --> MExec
  Cwd --> DExec
  Cwd --> MExec
  Env --> DExec
  Env --> MExec
Loading
Kit input Daytona Modal
argv: ["echo", "hi"] POSIX-quoted shell string argv as-is
shell: "echo hi" shell as-is ["bash", "-c", "echo hi"]
omitted / zero timeout command timeout 0 no limit (TS omits timeoutMs; Go Timeout: 0)
fractional timeout (1500 ms) rejected (timeout) rejected (timeout)
stderr empty (Go: non-nil empty slice) collected from pipe
empty environment {} Kit keeps explicit; TS native SDK may coerce to omit (same runtime: add no vars) Kit keeps explicit

Review fixes in this branch

1. Go empty-collection cloning (bug fix)

proto.Clone drops empty maps and empty byte slices. Process used the naive cloneMessage, so:

  • Environment: map[string]string{} became nil before the provider
  • Daytona Stderr: []byte{} (and empty stdout) became nil after return

Fix: cloneExecOptions / cloneExecResult (same pattern as Create). Covered by unit + Process.Run tests.

flowchart LR
  In["ExecOptions / ExecResult<br/>empty env or []byte{}"] --> Clone["cloneExec*"]
  Clone --> Out["owned copy<br/>empties preserved"]
  Out --> Provider["provider sees non-nil empty env"]
  Out --> Caller["caller sees non-nil empty stderr"]
Loading

2. Go Modal cancel no longer hangs on stdio drain (bug fix)

Modal wires exec stdout/stderr with context.Background() (and no stream deadline when command timeout is 0). Kit's Wait(ctx) respects cancel, but the old collectProcess still wg.Wait()'d on io.ReadAll, so a client deadline could leave the caller blocked until the remote process EOFs.

Fix: on Wait failure, close stdout/stderr so blocked reads unblock (matches Modal's Close-unblocks-read contract), then return the wait error.

sequenceDiagram
  participant Kit as collectProcess
  participant Wait as process.Wait(ctx)
  participant Out as stdout/stderr ReadAll
  Kit->>Out: start drain goroutines
  Kit->>Wait: wait for exit
  Note over Wait: ctx canceled / deadline
  Wait-->>Kit: error
  Kit->>Out: Close streams
  Out-->>Kit: reads unblock
  Kit-->>Kit: return wait error
Loading

3. Shared whole-second timeout helper

sdk.WholeSecondDuration shared by Go Daytona and Modal adapters. Behavior unchanged: nil/zero → 0; non-whole seconds rejected.

4. Docs honesty

  • Daytona omit/zero → always send 0 (native default is 10s)
  • Modal TS must omit timeoutMs (Modal rejects 0)
  • TypeScript abort is soft on the remote side: Kit rejects the await; Daytona/Modal exec often ignore AbortSignal so the command may keep running. The handle still stays busy until that provider call settles (see §7).
  • Empty env wording matches runtime (incl. Daytona TS {} coerce)
  • shell blankness is after TrimSpace / trim() (whitespace-only fails); inventory comment matches

5. Daytona TypeScript process tests

Covers argv POSIX quoting, omit/zero → 0, cwd/env forwarding, fractional reject, empty stderr.

6. Small cleanups

  • Shared Go absolutePath for sandbox path + working directory
  • Modal #file → #withSandbox
  • Portable proto timeout comment + regenerated contracts; provider details stay in docs / Go alias

7. TypeScript handle serialization holds through in-flight abort (bug fix)

Abort/timeout must reject the caller promptly, but the next lifecycle, filesystem, or process call on the same handle must not overlap native work that providers ignore mid-call. Matching Go and the documented one-at-a-time contract:

  1. #serialized starts the provider promise (work) once the gate is acquired.
  2. awaitWithSignal(work, signal) races that already-started promise so abort rejects without dropping it.
  3. finally unlocks when work settles (not when the caller rejects), so a queued follow-up waits.

Lifecycle / process / filesystem paths stop wrapping provider calls in a second factory-style awaitWithSignal that could start work after unlock. Docs (concepts, lifecycle, filesystem, process) state the busy-until-settle rule.

sequenceDiagram
  participant App
  participant Gate as Sandbox.#serialized
  participant Native as Provider call
  App->>Gate: start({ signal })
  Gate->>Native: work = body(signal)
  Note over App: abort / deadline
  Gate-->>App: reject Canceled (prompt)
  Note over Gate,Native: gate still held
  App->>Gate: start() / run() / readFile()
  Note over Gate: waits on previous unlock
  Native-->>Gate: settles
  Gate->>Gate: unlock
  Gate->>Native: second provider call
  Native-->>App: result
Loading
flowchart TB
  subgraph before [Before: unlock on caller reject]
    B1["acquire gate"] --> B2["awaitWithSignal factory"]
    B2 -->|"abort rejects"| B3["finally unlock"]
    B3 --> B4["next call starts<br/>while native still in flight"]
  end
  subgraph after [After: unlock when work settles]
    A1["acquire gate"] --> A2["work = body(signal)"]
    A2 --> A3["awaitWithSignal(work)"]
    A3 -->|"abort rejects caller"| A4["finally: unlock on work.then"]
    A4 --> A5["next call waits<br/>until native settles"]
  end
Loading

Covered by client tests: aborted in-flight start, process.run, and filesystem.readFile keep maximumActive === 1 until release.

8. Go process cancel + serialization parity (follow-up)

Go now mirrors the TypeScript busy-handle story for Process:

sequenceDiagram
  participant App
  participant Gate as operationGate
  participant Run as Process.Run
  participant Native as provider RunCommand
  App->>Run: Run(ctx1, sleep)
  Run->>Gate: acquire
  Run->>Native: start (blocks)
  App->>App: cancel ctx1
  Note over Native: still held until release
  App->>Run: Run(ctx2, true)
  Note over Gate: second call waits
  Native-->>Run: ctx canceled
  Run->>Gate: release
  Run-->>App: ErrorKindCanceled
  Gate->>Native: second RunCommand
  Native-->>App: result
Loading
  • TestProcessCancelEndsWait
  • TestProcessHoldsSerializationUntilCanceledInFlightSettles

Docs site

  • /docs/process guide with provider-specific tables via provider switch
  • Page-level Daytona / Modal control (persisted); Concepts + rewritten Quickstart / Configuration / Create / Lifecycle / Filesystem / Errors / Examples
  • One-viewport home with TypeScript/Go create-and-run sample
  • Static Pages fixes: no double /kit prefix; Copy / View markdown / Open in AI target prerendered .md files
  • Timeout section + links to run-*-with-timeout examples

Examples

24 runnable projects under examples/{go,typescript}/{daytona,modal}/process/:

Topic Projects
argv command run-*-command
shell string run-*-shell-command
working directory run-*-with-cwd
environment run-*-with-env
timeout run-*-with-timeout
non-zero exit run-*-check-exit
flowchart LR
  subgraph topics [Process example topics]
    A[command]
    B[shell]
    C[cwd]
    D[env]
    E[timeout]
    F[check-exit]
  end
  subgraph matrix [x2 providers x2 languages]
    G[Go Daytona]
    H[TS Daytona]
    I[Go Modal]
    J[TS Modal]
  end
  topics --> matrix
Loading

Test plan

  • Go: sdks/go/sandbox, sandbox/tests, Daytona + Modal providers (clone, timeouts, process)
  • Go: Process cancel ends wait; serialization held until canceled in-flight run settles
  • TypeScript: sandbox + Daytona + Modal package tests (Modal omit-timeoutMs, Daytona process mapping)
  • TypeScript: handle serialization held until aborted in-flight lifecycle / process / filesystem calls settle
  • Timeout examples typecheck / Go modules resolve
  • Contracts regenerated after proto comment update
  • Docs site typecheck; provider switch / landing verified locally
  • Smoke-run process examples against live Daytona and Modal
  • Confirm relative cwd, blank shell, and argv+shell fail with documented fields
  • Spot-check Go Modal client-deadline cancel returns promptly while a long command runs (omit command timeout)
  • Spot-check /docs/process, provider switch, landing, and markdown actions after Pages deploy

@Nabhag8848
Nabhag8848 merged commit c1ce728 into main Nov 4, 2026
3 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.

1 participant