Skip to content

v0.2.0: Project sync into sandboxes, background processes, and opencode auth login - #2

Open
cooleel wants to merge 12 commits into
mainfrom
sw/new_features
Open

v0.2.0: Project sync into sandboxes, background processes, and opencode auth login#2
cooleel wants to merge 12 commits into
mainfrom
sw/new_features

Conversation

@cooleel

@cooleel cooleel commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

New features added:

  • Project sync into sandbox
    • Git repos: worktree pushed to a TensorLake-hosted repo and cloned inside the sandbox, with credentials set up so the agent can push changes back.
    • Plain folders: uploaded to a cloud volume and mounted (writes persist durably); skips node_modules and other build junk.
    • Mode auto-detected, overridable via TENSORLAKE_SYNC_MODE=git|volume|off.
    • bash/ls/glob/grep now default to the synced project directory, and the system prompt tells the model where the project lives.
  • Migration to the new Tensorlake SDK API
    Moved off the deprecated SandboxClient to the Sandbox.create()/Sandbox.connect() statics.
  • Real background processes in the bash tool
    • background=true now uses sandbox.startProcess() and returns a real pid instead of fire-and-forget.
    • New bash_output tool (status + output lines new since last call) and bash_kill tool.
    • Processes stay queryable after exit/kill.
  • Reliability hardening
    • Stale sandbox handles (e.g. sandbox resumed on another host) are detected via typed SDK errors, dropped, and idempotent calls retried once — commands never retry, so nothing runs twice.
    • Re-sync is fast-forward-only, so commits made inside the sandbox are never clobbered.
    • Fixed a sandbox stuck mid-suspension being treated as live, and a latent deadlock in the cached-terminated path.
    • Project re-sync no longer blocks the first tool call when the sandbox already has a project copy — refresh runs in the background.
    • bash_output replay after a plugin restart is capped at 200 lines with stale-pid cleanup.
  • OpenCode-native auth
    • TensorLake registers as a provider in opencode auth login — no more mandatory env var.
    • Only project-scoped keys (tl_apiKey_…) accepted; the key is validated against the management API before OpenCode stores it in its standard auth.json, and its org/project scope comes from introspection so users never enter IDs separately.
    • Credentials resolved lazily on every use, so logging in mid-session works without restarting OpenCode.
    • TENSORLAKE_API_KEY still works and takes precedence (CI use case); missing credentials now produce an actionable error in chat, a toast, and a log line.
  • Housekeeping
    Dependency pins loosened to caret ranges (tensorlake ^0.5.109, @opencode-ai/plugin ^1.18.18), and the README updated throughout (login flow, testing guide, troubleshooting).

cooleel and others added 12 commits August 18, 2026 13:46
Fixes the "sandbox is empty" feedback: the local project is now synced
into the sandbox at /tmp/workspace/<project-name> on first use.

- Git repos: pushWorktree to a TensorLake-hosted repo, clone inside the
  sandbox, credentials configured so the agent can push changes back.
- Plain folders: upload to a cloud volume and mount it into the sandbox
  (writes persist durably); skips node_modules and other build junk.
- Mode auto-detected; TENSORLAKE_SYNC_MODE=git|volume|off overrides.
- bash/ls/glob/grep now default to the synced project directory and the
  system prompt tells the model where the project lives.
- Org/project scope resolved via API key introspection when not in env.
- Bump tensorlake to 0.5.109 and @opencode-ai/plugin to 1.18.18.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tatics

Sandbox handles are now cached per sandbox id so repeated operations
reuse resolved proxy routing. resume() refreshes routing on the same
handle; terminate drops the cached handle. Removes the SDK's startup
deprecation warning.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
background=true now uses sandbox.startProcess() instead of a
fire-and-forget run, returning a pid. New bash_output tool reports
process status plus output lines new since the last call; new
bash_kill tool stops the process. Processes are started unnamed
(non-managed) so the daemon keeps status and output queryable after
exit or kill.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- client: route proxy-bound operations through withSandbox(), which drops
  stale handles (sandbox resumed on another host) and retries idempotent
  calls once; command execution never retries to avoid double-running.
  Use typed SDK errors instead of matching message strings.
- project-sync: re-syncs fast-forward only instead of git reset --hard, so
  in-sandbox commits or changes are never clobbered; divergence is logged.
- bash_output: cap replay after a plugin restart to the last 200 buffered
  lines and drop stale offsets when a pid disappears.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…sync

- The in-memory-cache branch of _getSandbox now handles 'suspending'
  (wait for suspend to land, then resume) and waits for any other
  non-running status, matching the persisted-storage branch. Previously a
  cached sandbox mid-suspension was returned as if it were live.
- Fix a latent deadlock on the cached terminated path: the recursive
  getSandbox() call returned the session's own still-pending in-flight
  promise, resolving the promise to itself. Recurse via _getSandbox.
- Project sync no longer blocks the first tool call of every process when
  the sandbox already holds a project copy (e.g. resumed sandbox synced by
  an earlier process): ensureProjectAvailable() checks for the project dir
  once and lets the refresh push/clone run in the background; only a
  sandbox with no copy at all awaits the initial sync. Syncs are deduped
  per sandbox via an in-flight map.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
tensorlake ^0.5.109 picks up patch fixes but blocks 0.6.x breaking
changes; @opencode-ai/plugin is types-only so ^1.18.18 is safe.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Git-mode sync now pushes the repo's actual refs (git push HEAD:main) to
the TensorLake-hosted mirror, so the sandbox clone has real commits,
authors, and dates — git log/blame/diff work as expected and branches
created in the sandbox share ancestry with the original repo.

- Uncommitted local changes (modified + untracked) are captured with a
  temporary index and replayed onto the sandbox working tree uncommitted,
  but only when the sandbox tree is clean and at the same HEAD — agent
  work is never overwritten.
- Non-fast-forward pushes (local rebase/amend) recreate the disposable
  mirror and push fresh, with a warning that mirror-only commits are lost.
- Credentials go in an HTTP header (redacted from errors), never the URL.
- Repos with no commits fall back to the previous pushWorktree snapshot.
- Sandbox gets a fallback git identity so agents can commit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Key the cached org/project scope by API key so a no-restart auth login
  with a key from another project no longer reuses the stale scope
- Distinguish a mirror that is ahead (agent commits) from rewritten local
  history before recreating the hosted mirror on non-fast-forward pushes
- Track uploaded paths in a volume sync manifest so local deletions
  propagate without touching agent-created files
- Use POSIX joins for guest sandbox paths on Windows hosts

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Deletion propagation: track every path still present locally (oversized,
  symlink, unreadable included) so files skipped from an upload are never
  deleted from the volume; drop the prototype-chain-prone `in` check.
- Move the sync manifest off the volume onto the laptop's storage dir so
  sandbox agents can't see, commit, or tamper with the file driving remote
  deletions; validate delete paths and scrub the legacy on-volume manifest.
- Mirror ancestry check: treat only merge-base exit 1 as "not an ancestor"
  (other errors route to the indeterminate path instead of recreating the
  mirror), and fetch into a throwaway ref with --no-write-fetch-head so the
  user's FETCH_HEAD is never clobbered.
- Mount readiness: always wait for the guest even when the control plane
  already lists the mount, probe for a real mountpoint instead of `test -d`
  (the sync-failure fallback mkdirs a decoy at that path), and bound each
  probe to 5s so the 30s deadline is honest.
- Project-dir fast path requires a non-empty directory so the empty decoy
  left by a failed sync doesn't count as a project copy.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Rename TensorLakeClient, TensorLakeSessionManager, and
createTensorLakeTools along with all prose, tool descriptions,
log messages, and README references.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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