b18669452f
## 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>
85 lines
2.8 KiB
TypeScript
85 lines
2.8 KiB
TypeScript
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;
|