Commit Graph

1 Commits

Author SHA1 Message Date
Nicky Leach 030dd9d15c
feat(adapter-utils): provider-delegable syncIn seam with ordered post-upload commands (#10340)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The adapter/runtime layer has to move files into sandboxes safely
and efficiently
> - The current sync-in path needs a provider-delegable seam so
providers can use their native upload transport when available
> - The upload contract also needs ordered post-upload commands so
extracted content can be finalized fail-fast after transfer
> - The fallback path still has to preserve current behavior when the
provider does not expose native sync verbs
> - This pull request adds the contract and runtime seam for
provider-delegable sync-in, plus the single-stream collapse flag
> - The benefit is fewer round trips, a cleaner provider-owned upload
path, and a compatible fallback for existing runners

## Linked Issues or Issue Description

No public GitHub issue exists for this change. The underlying feature
request is described below in the repository's feature-request format.

### Problem or motivation

Paperclip needs a sync-in path that lets each provider choose the best
available upload transport instead of forcing the harness to orchestrate
uploads the same way every time. The runtime also needs a way to
describe ordered post-upload commands so providers can finalize
extracted content fail-fast after transfer.

### Proposed solution

Extend the sync contract with ordered post-upload commands, forward that
contract through the plugin and environment runtime layers, and make
client syncIn always available. When a provider advertises native sync
verbs, the client should delegate to that transport; otherwise it should
fall back to the existing tarball/write/extract behavior and then run
the post-upload commands in order.

### Alternatives considered

Keeping upload orchestration entirely host-side would avoid a contract
change, but it would block provider-specific transport optimizations and
keep the harness responsible for a path the provider can do more
efficiently. A separate post-upload API would add another surface
without improving the existing sync flow.

### Roadmap alignment

This work aligns with the broader runtime and adapter roadmap because it
improves provider integration without changing the external product
model. It is an additive contract change that preserves backward
compatibility for providers that do not expose native sync verbs.

### Additional context

The fallback path still needs to preserve existing observable behavior,
including command ordering, cwd confinement, and fail-fast execution.
The single-stream progress flag is part of the same transport
improvement so smaller writes can collapse to a single round trip when
the runner supports it.

## What Changed

- Added ordered `postUploadCommands` support to the sync operation
contract and SDK mirror.
- Plumbed the sync-in contract through the plugin and environment
runtime layers.
- Implemented a runtime client `syncIn` path that delegates to native
provider transport when available, otherwise uses the generic
tarball/write/extract fallback.
- Preserved fail-fast execution of ordered post-upload commands in the
fallback path.
- Flipped the sandbox runner's single-stream stdin progress flag to
collapse small `writeFile` operations to a single round trip.
- Added and updated tests for contract forwarding, fallback behavior,
cwd rejection, fail-fast behavior, and single-stream collapse.

## Verification

- `pnpm --filter @paperclipai/plugin-sdk exec vitest run
protocol.postupload.test.ts`
- `pnpm --filter @paperclipai/plugin-sdk exec vitest run
environment-sync-negotiation.test.ts`
- `pnpm --filter @paperclipai/adapter-utils exec vitest run
command-managed-runtime.test.ts`
- `pnpm --filter @paperclipai/server exec vitest run
environment-execution-target.test.ts`
- Local typecheck and targeted suite runs reported in the handoff passed
before PR creation.

## Risks

- The new fallback path could diverge from the previous inline upload
behavior if the tarball/extract contract changes.
- Provider-native sync handling may expose provider-specific edge cases
if a runner advertises sync verbs but does not fully honor the contract.
- The single-stream flag changes transport behavior for small uploads,
so regressions would likely show up as round-trip or upload failures.

## Model Used

OpenAI Codex (GPT-5, tool-using coding agent).

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` /
`Closes: #` / `Refs: #` OR (b) described the issue in-PR following the
relevant issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change and contains no internal
Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-27 17:19:57 -07:00