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
Two independent reviews of #13 landed on the same gap from opposite sides, and both fixes there are partial because the underlying semantics are undecided.
What is undefined
defineAgent().createSession({ sessionId }) accepts a caller-supplied id, and sandbox/docker/container.tsadopts a container that already carries that name rather than failing. So a supplied id can mean either "resume the sandbox I had" or "create one under a name I chose", and nothing in the API distinguishes them.
Three behaviours currently follow from that ambiguity:
Re-seeding over live work.onSession seeds the workspace on every session, so reconnecting with a known id overwrites files the previous session edited (the example's sum.js goes back to its buggy original). Per-session seeding is the documented design; what is missing is what a reopen should do instead.
Reaping the wrong container.feat(core): add defineAgent and defineSandbox as the first public API #13 originally destroyed the sandbox on any createSession failure, which threw away an adopted container's resumable state. It now reaps only when the id was generated here (created = options?.sessionId === undefined).
The residual leak that fix leaves.created records how the id was obtained, not whether this call created the container. A caller-supplied id whose container did not previously exist is created by onCreate and then not reaped on failure — it leaks, and on a paid backend it bills until its own timeout.
Why it is not a one-line fix
The precise signal exists in the backend — container.ts knows whether it adopted or created — but SandboxProvider exposes only session(sandboxId) and portEndpoint(...), so there is no vendor-neutral way to ask. Surfacing it is a contract change, and per CLAUDE.md that is an API decision to surface rather than invent.
What needs deciding
Does a supplied sessionId mean resume or name? If both are wanted, they are two call shapes, not one.
Should the sandbox contract report whether a session handle was adopted or created?
On a reopen, does the workspace re-seed, skip, or merge?
Two independent reviews of #13 landed on the same gap from opposite sides, and both fixes there are partial because the underlying semantics are undecided.
What is undefined
defineAgent().createSession({ sessionId })accepts a caller-supplied id, andsandbox/docker/container.tsadopts a container that already carries that name rather than failing. So a supplied id can mean either "resume the sandbox I had" or "create one under a name I chose", and nothing in the API distinguishes them.Three behaviours currently follow from that ambiguity:
onSessionseeds the workspace on every session, so reconnecting with a known id overwrites files the previous session edited (the example'ssum.jsgoes back to its buggy original). Per-session seeding is the documented design; what is missing is what a reopen should do instead.createSessionfailure, which threw away an adopted container's resumable state. It now reaps only when the id was generated here (created = options?.sessionId === undefined).createdrecords how the id was obtained, not whether this call created the container. A caller-supplied id whose container did not previously exist is created byonCreateand then not reaped on failure — it leaks, and on a paid backend it bills until its own timeout.Why it is not a one-line fix
The precise signal exists in the backend —
container.tsknows whether it adopted or created — butSandboxProviderexposes onlysession(sandboxId)andportEndpoint(...), so there is no vendor-neutral way to ask. Surfacing it is a contract change, and perCLAUDE.mdthat is an API decision to surface rather than invent.What needs deciding
sessionIdmean resume or name? If both are wanted, they are two call shapes, not one.Where this came from
packages/core/src/agent/define.ts— thecreateSessiontry/catch, and theonSessionseed above it./code-reviewpass (low, "no defined semantics yet").