Add Novita sandbox provider plugin (#7595)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Paperclip already separates agent adapters from execution environments, so agents can run locally, over SSH, or through sandbox providers. > - Sandbox provider plugins let Paperclip add new cloud runtimes without changing each agent adapter. > - Novita Agent Sandbox is a cloud runtime for AI agent workloads with isolated filesystems, command execution, templates, timeout controls, and pause/resume behavior. > - Paperclip currently has sandbox provider examples for Daytona and Cloudflare, but not Novita. > - This pull request adds a Novita sandbox provider plugin using the existing provider-plugin lifecycle. > - The benefit is that Paperclip users can run existing adapters such as Codex, Claude, Gemini, OpenCode, Cursor, or ACPX inside Novita Agent Sandbox environments. ## Linked Issues or Issue Description Fixes #7596 ## What Changed - Added `packages/plugins/sandbox-providers/novita` as a standalone sandbox provider plugin package. - Registered provider key `novita` with `kind: "sandbox_provider"` and `environment.drivers.register` capability. - Implemented Novita environment lifecycle hooks: validate config, probe, acquire lease, resume lease, release lease, destroy lease, realize workspace, and execute commands. - Added config support for `apiKey`, `domain`, `template`, `requestedCwd`, `timeoutMs`, `requestTimeoutMs`, `secure`, `autoPause`, and `reuseLease`. - Added README documentation for setup, configuration, and lifecycle behavior. - Added tests for manifest shape, config parsing, safe shell command wrapping, stdin delimiter safety, and env-key validation. ## Verification From `packages/plugins/sandbox-providers/novita`: - `pnpm typecheck` - `pnpm test` The tests avoid live Novita API calls and cover the provider's static contract and command-wrapping behavior. Live end-to-end verification requires a Paperclip instance with the plugin installed and a Novita API key configured as either a Paperclip secret or `NOVITA_API_KEY` in the worker environment. ## Risks - This adds a new direct dependency on the Novita Sandbox JS SDK (`novita-sandbox`). Socket/Snyk should review the package as part of normal dependency checks. - The implementation relies on Novita SDK command execution semantics; live provider behavior should be verified with a real Novita sandbox before marking the plugin production-ready. - `reuseLease` maps Paperclip release behavior to Novita `betaPause()`. If pause is unavailable for a selected template, the plugin falls back to best-effort kill during release. - Low migration risk for existing users because this is a new standalone provider plugin and does not change existing adapters or built-in providers. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used OpenAI GPT-5 Codex via Codex CLI, with repository file access, shell command execution, GitHub CLI/API usage, and local TypeScript/Vitest verification. Web and local documentation context were used for Novita Sandbox SDK/API behavior. ## 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 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 - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] 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> Co-authored-by: Devin Foley <devin@paperclip.ing>
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
import type { PaperclipPluginManifestV1 } from "@paperclipai/plugin-sdk";
|
||||
|
||||
const PLUGIN_ID = "paperclip.novita-sandbox-provider";
|
||||
const PLUGIN_VERSION = "0.1.0";
|
||||
|
||||
const manifest: PaperclipPluginManifestV1 = {
|
||||
id: PLUGIN_ID,
|
||||
apiVersion: 1,
|
||||
version: PLUGIN_VERSION,
|
||||
displayName: "Novita Sandbox Provider",
|
||||
description:
|
||||
"Sandbox provider plugin that provisions Novita Agent Sandbox environments for Paperclip agent runs.",
|
||||
author: "Novita AI",
|
||||
categories: ["automation"],
|
||||
capabilities: ["environment.drivers.register"],
|
||||
entrypoints: {
|
||||
worker: "./dist/worker.js",
|
||||
},
|
||||
environmentDrivers: [
|
||||
{
|
||||
driverKey: "novita",
|
||||
kind: "sandbox_provider",
|
||||
displayName: "Novita Agent Sandbox",
|
||||
description:
|
||||
"Provisions Novita Agent Sandbox instances with configurable templates, idle timeout, workspace path, and lease reuse.",
|
||||
configSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
apiKey: {
|
||||
type: "string",
|
||||
format: "secret-ref",
|
||||
description:
|
||||
"Environment-specific Novita API key. Paste a key or an existing Paperclip secret reference; saved environments store pasted values as company secrets. Falls back to NOVITA_API_KEY if omitted.",
|
||||
},
|
||||
domain: {
|
||||
type: "string",
|
||||
description:
|
||||
"Optional Novita API domain override. Leave empty to use the SDK default.",
|
||||
},
|
||||
template: {
|
||||
type: "string",
|
||||
description:
|
||||
"Novita sandbox template ID or name. Leave blank to use the SDK's default base template.",
|
||||
},
|
||||
requestedCwd: {
|
||||
type: "string",
|
||||
default: "/home/user/paperclip-workspace",
|
||||
description: "Workspace directory to create inside the sandbox lease.",
|
||||
},
|
||||
timeoutMs: {
|
||||
type: "number",
|
||||
default: 300000,
|
||||
description:
|
||||
"Sandbox lifetime and default per-command timeout in milliseconds.",
|
||||
},
|
||||
requestTimeoutMs: {
|
||||
type: "number",
|
||||
default: 30000,
|
||||
description:
|
||||
"HTTP/RPC request timeout for Novita SDK calls in milliseconds.",
|
||||
},
|
||||
secure: {
|
||||
type: "boolean",
|
||||
default: true,
|
||||
description: "Use secure connections when supported by the Novita SDK.",
|
||||
},
|
||||
autoPause: {
|
||||
type: "boolean",
|
||||
default: false,
|
||||
description: "Enable Novita sandbox auto-pause behavior when supported by the selected template.",
|
||||
},
|
||||
reuseLease: {
|
||||
type: "boolean",
|
||||
default: false,
|
||||
description:
|
||||
"Pause and later resume the sandbox across Paperclip runs instead of killing it on release.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default manifest;
|
||||
Reference in New Issue
Block a user