Files
PaperClipAI/packages/adapter-utils
Priya RamanandPaperclip aa55a49370 feat(sandbox): select the duplex transport behind two gates with a liveness-only readiness contract
Select the duplex transport only when the experimental setting
enableSandboxDuplexBridge is exactly true and the resolved capability
duplexCommandStream is exactly true. Any other value of either gate
selects the file bridge.

The host assigns the loopback port and one random per-open nonce, and
passes both to the gateway only through the launch environment. The host
builds the sandbox-facing origin http://127.0.0.1:<assigned port> from
its own stored port. No field of any channel frame contributes to the
endpoint. Change the READY frame from an address string to a strict
version-plus-nonce schema in the host codec, the embedded gateway codec,
and the shared fixture; the gateway echoes the nonce and sends READY only
after it binds the assigned port. The gateway binds exactly that port or
writes a diagnostic and exits nonzero.

Readiness fails closed. On a mismatched nonce, an address-bearing or
incomplete READY frame, protocol contamination before READY, a bind
failure, or a timeout, the host closes the partial channel inside a
bounded budget and selects the file bridge, and leaves no live provider
session. The broker starts only after readiness passes, so no request
that carries the bridge token reaches a rejected endpoint. Teardown
closes the channel before lease release.

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-20 02:57:40 +00:00
..

@paperclipai/adapter-utils

Shared utilities for Paperclip adapters: process spawning, environment injection, sandbox/SSH transport, workspace sync, and the round-trip helpers that move code between the local execution-workspace cwd and wherever the agent actually runs.

For the adapter-author guide see docs/adapters/creating-an-adapter.md and the in-repo notes at packages/adapters/AUTHORING.md.

No-remote-git contract

The local execution-workspace cwd is the only persistence boundary across runs. No adapter may depend on a git remote for cross-run state.

Adapters that run the agent on a different host should use the SSH round-trip helpers in src/ssh.ts:

  • prepareWorkspaceForSshExecution({ spec, localDir, remoteDir }) — bundles the local cwd (tracked files, dirty edits, untracked additions, and the git history needed to reconstruct it) to remoteDir before the run starts. Runs with no git remote configured.
  • restoreWorkspaceFromSshExecution({ spec, localDir, remoteDir, ... }) — syncs the remote cwd back into localDir after the run, including any new commits the agent created. Also runs with no git remote configured.

prepareRemoteManagedRuntime in src/remote-managed-runtime.ts wraps both calls for adapters that want a per-run remote workspace and an automatic restoreWorkspace() finally hook.

The invariant is pinned by the no-remote-git contract case in src/ssh-fixture.test.ts, which asserts that a remote-only commit propagates to the local worktree through the prepare → restore round-trip with no git remote configured at any point. Do not regress that test.