Files
PaperClipAI/packages/adapter-utils
Priya RamanandPaperclip d966069a78 fix(adapter-utils): skip the remote session close when the duplex channel is already lost
The teardown placed a remote session-close call over a duplex control
channel the runtime had already latched as lost. The call carries no
deadline of its own, so it blocked until the adapter execution timeout
released it, leaving the run row read as running long after the
outcome was known.

The turn-finalize settlement now marks a lost channel with
skipRemoteClose, and the end_session step releases the runtime locally
without placing the remote call when that flag is set.

Known residual: skipping the remote close also skips the vendored
runtime's only caller of closeBackendSession, so it keeps a retained
client for the run. A duplex loss proves only that the control channel
died, not that the backend process died. A separate tracked goal owns
that follow-up.

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-28 01:19:39 +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.