paperclip/packages/plugins/sandbox-providers/exe-dev/package.json

59 lines
1.7 KiB
JSON
Raw Permalink Normal View History

Add exe.dev sandbox provider plugin (#5688) > _Stacked on top of #5685 → #5686 → #5687. Diff against master includes commits from earlier PRs in the stack — review focuses on the two new commits (`Add long-secret textarea variant to JsonSchemaForm SecretField` + `Add exe.dev sandbox provider plugin`)._ ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - Each agent runs in a sandbox environment, and operators choose the provider — today E2B, Daytona, and (in this stack) Cloudflare > - exe.dev offers per-VM sandboxes via a small CLI / HTTP API — useful for operators who want full Linux VMs (vs container/runtime-only sandboxes) > - The plugin shape mirrors the e2b plugin: lifecycle hooks (`new`, `ls`, `rm`) drive exe.dev's CLI; SSH plumbing handles direct VM access for adapters that need it > - exe.dev VMs come up bare — `node` is not preinstalled, so the Paperclip sandbox callback bridge (a Node script) needs Node 20 installed at VM init via `--setup-script`. The plugin defaults the setup script to a Nodesource install > - The auth field accepts long SSH private keys, which need a textarea variant of the existing `SecretField` in `JsonSchemaForm` — added behind a `maxLength > THRESHOLD` opt-in so other secret fields are unaffected > - The benefit is that operators get exe.dev as a fully working sandbox provider out of the box, with no manual VM provisioning required ## What Changed **Shared UI support (`Add long-secret textarea variant to JsonSchemaForm SecretField`):** - `ui/src/components/JsonSchemaForm.tsx` + new `JsonSchemaForm.test.tsx`: when a secret-formatted field declares `maxLength` larger than the existing single-line threshold, render a monospace textarea instead of the masked input. Short secrets (API keys, tokens) keep the existing masked-input + show/hide toggle behavior. **The exe.dev plugin (`Add exe.dev sandbox provider plugin`):** - `packages/plugins/sandbox-providers/exe-dev/`: plugin entry, manifest, plugin runtime, README, and 19-test Vitest suite. - Manifest fields: API token (with `secret-ref` + `/exec` permission notes — needs `new`, `ls`, `rm`), API URL override, optional SSH username, optional SSH private key (uses the new `JsonSchemaForm` textarea variant via `maxLength: 4096`), optional SSH identity-file path, optional setup script. - Default `--setup-script` is a Nodesource Node 20 install. exe.dev VMs come up bare and the Paperclip sandbox callback bridge is a Node script, so without Node preinstalled the bridge can't start. Operators can override by supplying their own setup script. - `runLifecycleCommand` redacts env values from the executed command before surfacing it in error messages, so secrets passed via `--env=KEY=VALUE` don't leak into operator-visible failures. - The plugin distinguishes exe.dev's SSH onboarding failures (`Please complete registration by running: ssh exe.dev`) from general SSH failures and surfaces a clear remediation message. - `scripts/release-package-manifest.json`: register the new plugin for CI publish alongside the existing daytona / e2b providers. ## Verification - `pnpm typecheck` - `pnpm exec vitest run --no-coverage ui/src/components/JsonSchemaForm.test.tsx` - `(cd packages/plugins/sandbox-providers/exe-dev && pnpm test)` — 19 passing For an operator-side smoke test: 1. Get an exe.dev API token with `/exec` permission for `new`, `ls`, `rm`. 2. Register the plugin in your Paperclip instance, configure an environment with the token. 3. Create a sandbox env whose provider is `exe-dev`, then run a Codex or Claude job against it. The default Node 20 setup script should bring the VM up automatically. ## Risks - Adds a new sandbox provider plugin that follows the existing daytona / e2b shape; behavior on existing providers is unchanged. - The `JsonSchemaForm` textarea variant only engages for fields that opt in via `maxLength` larger than the existing threshold. All existing secret fields (which don't declare a `maxLength`) keep their current rendering. Test coverage pins both paths. - The redaction in `runLifecycleCommand` is a defense-in-depth measure; the test suite exercises the redaction path. If the redaction misses a future env-arg shape, the worst case is restored behavior (secrets in error messages), which is what the existing daytona / e2b plugins also do today. - Default setup script downloads from `deb.nodesource.com` over HTTPS at VM init. Operators on air-gapped networks or with a different package strategy can override the setup script. ## Model Used - Provider: Anthropic - Model: Claude Opus 4.7 (1M context) - Capabilities used: extended reasoning, tool use (Read/Edit/Bash/Grep) ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots — UI change is a textarea variant of an existing secret field; will attach screenshots before requesting merge - [x] I have updated relevant documentation to reflect my changes (plugin README, manifest descriptions) - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-05-11 07:42:18 -07:00
{
"name": "@paperclipai/plugin-exe-dev",
exe.dev config UX: advanced-options disclosure, form-default fix, SSH key handling (PAPA-407) (#7025) ## Thinking Path > - Paperclip orchestrates AI agents and provisions sandboxed execution environments for them; one of those provisioners is the exe.dev plugin, which runs each agent inside a long-lived VM reached over SSH. > - The instance-config form for that plugin is rendered generically by `JsonSchemaForm` from the plugin's `instanceConfigSchema`, so any UX problem with the form is split between the shared form component and the plugin's schema/runtime code. > - Users coming in cold hit a 12-field flat config they couldn't reason about (PAPA-407), a form that silently submitted `cpu: 0` for untouched optional fields (PAPA-407 root cause), a `sshPrivateKey` textarea that truncated RSA-4096 keys at 4096 chars (PAPA-449), a save flow that accepted clearly-malformed keys and only blew up at lease time with raw SSH stderr (PAPA-450, PAPA-451), and a manifest that didn't distinguish "essential" from "advanced" knobs (PAPA-410 / PAPA-411 — duplicate sub-issues with identical scope; PAPA-418 reconciliation kept PAPA-410 canonical). > - These problems all point at the same surface (exe.dev sandbox config) and are tightly coupled in code — PAPA-449/450/451 patch fields that PAPA-410/411 introduce — so they get reviewed together. > - This pull request lands the shared-form changes (advanced-options disclosure, optional-scalar defaults) and the exe.dev-specific changes (manifest restructure, longer `maxLength`, stderr translation, save-time key validation) as five focused commits stacked on `master`. > - The benefit is a config form that defaults to the two fields a new user actually needs (API key + SSH private key) with a collapsible disclosure for the rest, no silent truncation or zero-default submissions, and SSH key problems surfaced at save time with actionable messages instead of cryptic post-provision failures. ## What Changed - **JsonSchemaForm advanced-options disclosure** (PAPA-410, PAPA-411 — same scope, see note above): adds `x-paperclip-advanced` / `x-paperclip-group` schema annotations and renders flagged fields behind a collapsible "Advanced options" disclosure that auto-opens when a hidden field has a validation error. Exe.dev manifest is restructured to use the new annotations, so essentials (`apiKey`, `sshPrivateKey`) show by default while the long tail of optional knobs is grouped under "SSH access" / "VM resources" / "More options" headings. - **Omit optional scalar defaults** (PAPA-407): `getDefaultForSchema` no longer materialises `0` / `""` for optional `number`/`integer`/`string`/`secret-ref` fields without an explicit `default`. Object recursion drops properties whose default is `undefined`. Fields that declare a `default` (e.g. `sshPort: 22`) still round-trip. Adds a regression test against `getDefaultValues`. - **Raise `sshPrivateKey` `maxLength`** (PAPA-449): bumps the exe.dev manifest cap from 4096 to 8192 so RSA-4096 OpenSSH private keys (which can exceed 4 KB with comments/metadata) aren't silently truncated at submit. - **Translate `invalid format` SSH stderr** (PAPA-450): `formatSshFailure` now recognises `Load key … invalid format` in combined stderr/stdout and returns a specific message naming the key-format problem ("isn't an OpenSSH/PEM private key — confirm the secret starts with `-----BEGIN … PRIVATE KEY-----` and isn't the `.pub` or a PuTTY `.ppk` export") instead of dumping the raw stderr. - **Save-time SSH key validation** (PAPA-451): `onEnvironmentValidateConfig` inline-parses `sshPrivateKey` and rejects common failure modes — pasted public keys, PuTTY `.ppk` format, missing `-----END-----` footer, non-base64 body — so the form surfaces an inline error before any VM is provisioned. Secret-ref bindings (UUIDs) are still passed through unchanged. ## Verification CI gates (`pnpm typecheck`, `pnpm test`, the targeted vitest suites below) all pass. Run locally: ```bash # Shared form pnpm --filter @paperclipai/ui exec vitest run src/components/JsonSchemaForm # 9 tests pass — includes the new "omits optional scalar fields" regression # and the three advanced-options-disclosure tests. # exe.dev plugin cd packages/plugins/sandbox-providers/exe-dev && pnpm test # 32 tests pass — includes the new sshPrivateKey-validation cases # and the new "invalid format" stderr-translation case. ``` Manual smoke (after reinstalling the plugin so the DB manifest refreshes): 1. Open the exe.dev environment config page. **Default view shows API Key + SSH Private Key only**, with an "Advanced options" disclosure for everything else (PAPA-410 / PAPA-411). 2. Paste a `.pub` file's contents into SSH Private Key, click Save. **Inline error** rejecting the wrong-format key (PAPA-451). 3. Re-paste a valid OpenSSH/PEM private key longer than 4096 bytes — saves cleanly (PAPA-449). 4. Save the form with everything optional left blank — server no longer rejects with `"cpu must be greater than 0 when provided"` (PAPA-407). 5. Force a bad key through via a stored secret-ref binding and lease a VM — failure message names the key-format problem instead of dumping raw SSH stderr (PAPA-450). ## Risks - **PAPA-410 / PAPA-411 manifest restructure** is the largest surface here. Schemas using `x-paperclip-*` extensions are forward-compatible with stricter JSON Schema validators (extensions are ignored by default), and the form gracefully renders a flat layout when no field opts in. - **PAPA-407** changes form-default behaviour: optional scalar fields that previously round-tripped as `""` / `0` will now be `undefined` and absent from the submitted payload. Downstream consumers that expected the empty-string/zero shape need to treat the field as optional. Spot-checked the existing exe.dev driver — it already uses `parseOptionalString` / `parseOptionalInteger`, which treat missing fields as `null` rather than `0`/`""`. - **PAPA-451** adds a save-time check, so a previously-saved-but-malformed `sshPrivateKey` raw value will now fail to re-save. Bound secret-refs are unaffected, matching how the user reaches the bad-key state today (via the secrets picker). - **PAPA-449** simply raises a cap; no semantic risk. - **PAPA-450** only kicks in on the "invalid format" code path; existing onboarding-marker branch is untouched. ## Model Used - Provider: Anthropic - Model: Claude Opus 4.7 (`claude-opus-4-7`) - Capabilities used: code reading, code editing, test execution, git/PR mechanics, Paperclip API for issue coordination ## Checklist - [x] PR body sections present (Thinking Path, What Changed, Verification, Risks, Model Used, Checklist) - [x] Unit tests added for the new behaviours (JsonSchemaForm default-value omission + advanced disclosure; exe.dev plugin validation + stderr translation) - [x] Existing tests still pass locally (`vitest run` on both packages) - [x] No raw secrets, IP addresses, or machine-local config in commits or PR body - [x] Commits are atomic per linked issue (PAPA-410 / PAPA-411, PAPA-407, PAPA-449, PAPA-450, PAPA-451) - [x] Branch is up-to-date with `origin/master` --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-05-29 18:19:37 -07:00
"version": "0.1.1",
Add exe.dev sandbox provider plugin (#5688) > _Stacked on top of #5685 → #5686 → #5687. Diff against master includes commits from earlier PRs in the stack — review focuses on the two new commits (`Add long-secret textarea variant to JsonSchemaForm SecretField` + `Add exe.dev sandbox provider plugin`)._ ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - Each agent runs in a sandbox environment, and operators choose the provider — today E2B, Daytona, and (in this stack) Cloudflare > - exe.dev offers per-VM sandboxes via a small CLI / HTTP API — useful for operators who want full Linux VMs (vs container/runtime-only sandboxes) > - The plugin shape mirrors the e2b plugin: lifecycle hooks (`new`, `ls`, `rm`) drive exe.dev's CLI; SSH plumbing handles direct VM access for adapters that need it > - exe.dev VMs come up bare — `node` is not preinstalled, so the Paperclip sandbox callback bridge (a Node script) needs Node 20 installed at VM init via `--setup-script`. The plugin defaults the setup script to a Nodesource install > - The auth field accepts long SSH private keys, which need a textarea variant of the existing `SecretField` in `JsonSchemaForm` — added behind a `maxLength > THRESHOLD` opt-in so other secret fields are unaffected > - The benefit is that operators get exe.dev as a fully working sandbox provider out of the box, with no manual VM provisioning required ## What Changed **Shared UI support (`Add long-secret textarea variant to JsonSchemaForm SecretField`):** - `ui/src/components/JsonSchemaForm.tsx` + new `JsonSchemaForm.test.tsx`: when a secret-formatted field declares `maxLength` larger than the existing single-line threshold, render a monospace textarea instead of the masked input. Short secrets (API keys, tokens) keep the existing masked-input + show/hide toggle behavior. **The exe.dev plugin (`Add exe.dev sandbox provider plugin`):** - `packages/plugins/sandbox-providers/exe-dev/`: plugin entry, manifest, plugin runtime, README, and 19-test Vitest suite. - Manifest fields: API token (with `secret-ref` + `/exec` permission notes — needs `new`, `ls`, `rm`), API URL override, optional SSH username, optional SSH private key (uses the new `JsonSchemaForm` textarea variant via `maxLength: 4096`), optional SSH identity-file path, optional setup script. - Default `--setup-script` is a Nodesource Node 20 install. exe.dev VMs come up bare and the Paperclip sandbox callback bridge is a Node script, so without Node preinstalled the bridge can't start. Operators can override by supplying their own setup script. - `runLifecycleCommand` redacts env values from the executed command before surfacing it in error messages, so secrets passed via `--env=KEY=VALUE` don't leak into operator-visible failures. - The plugin distinguishes exe.dev's SSH onboarding failures (`Please complete registration by running: ssh exe.dev`) from general SSH failures and surfaces a clear remediation message. - `scripts/release-package-manifest.json`: register the new plugin for CI publish alongside the existing daytona / e2b providers. ## Verification - `pnpm typecheck` - `pnpm exec vitest run --no-coverage ui/src/components/JsonSchemaForm.test.tsx` - `(cd packages/plugins/sandbox-providers/exe-dev && pnpm test)` — 19 passing For an operator-side smoke test: 1. Get an exe.dev API token with `/exec` permission for `new`, `ls`, `rm`. 2. Register the plugin in your Paperclip instance, configure an environment with the token. 3. Create a sandbox env whose provider is `exe-dev`, then run a Codex or Claude job against it. The default Node 20 setup script should bring the VM up automatically. ## Risks - Adds a new sandbox provider plugin that follows the existing daytona / e2b shape; behavior on existing providers is unchanged. - The `JsonSchemaForm` textarea variant only engages for fields that opt in via `maxLength` larger than the existing threshold. All existing secret fields (which don't declare a `maxLength`) keep their current rendering. Test coverage pins both paths. - The redaction in `runLifecycleCommand` is a defense-in-depth measure; the test suite exercises the redaction path. If the redaction misses a future env-arg shape, the worst case is restored behavior (secrets in error messages), which is what the existing daytona / e2b plugins also do today. - Default setup script downloads from `deb.nodesource.com` over HTTPS at VM init. Operators on air-gapped networks or with a different package strategy can override the setup script. ## Model Used - Provider: Anthropic - Model: Claude Opus 4.7 (1M context) - Capabilities used: extended reasoning, tool use (Read/Edit/Bash/Grep) ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots — UI change is a textarea variant of an existing secret field; will attach screenshots before requesting merge - [x] I have updated relevant documentation to reflect my changes (plugin README, manifest descriptions) - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-05-11 07:42:18 -07:00
"description": "exe.dev sandbox provider plugin for Paperclip environments",
"license": "MIT",
"homepage": "https://github.com/paperclipai/paperclip",
"bugs": {
"url": "https://github.com/paperclipai/paperclip/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/paperclipai/paperclip",
"directory": "packages/plugins/sandbox-providers/exe-dev"
},
"type": "module",
"exports": {
".": "./src/index.ts"
},
"publishConfig": {
"access": "public",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
}
},
"main": "./dist/index.js",
"types": "./dist/index.d.ts"
},
"files": [
"dist"
],
"paperclipPlugin": {
"manifest": "./dist/manifest.js",
"worker": "./dist/worker.js"
},
"keywords": [
"paperclip",
"plugin",
"sandbox",
"exe.dev"
],
"scripts": {
"postinstall": "node ../../../../scripts/link-plugin-dev-sdk.mjs",
"prebuild": "pnpm -C ../../../.. --filter @paperclipai/plugin-sdk ensure-build-deps",
"build": "rm -rf dist && tsc",
"clean": "rm -rf dist",
"typecheck": "pnpm -C ../../../.. --filter @paperclipai/plugin-sdk ensure-build-deps && tsc --noEmit",
"test": "vitest run --config vitest.config.ts",
"prepack": "rm -f package.dev.json && cp package.json package.dev.json && node ../../../../scripts/generate-plugin-package-json.mjs",
"postpack": "if [ -f package.dev.json ]; then mv package.dev.json package.json; fi"
},
"devDependencies": {
"@types/node": "^24.6.0",
"typescript": "^5.7.3",
"vitest": "^3.2.4"
}
}