mirror of
https://github.com/paperclipai/paperclip
synced 2026-05-08 16:12:20 +02:00
## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - Sandbox environments are part of that execution layer, and the recent core refactor moved provider-specific behavior to a generic plugin seam > - This pull request adds a dedicated `@paperclipai/plugin-e2b` package so E2B can live entirely outside core host code > - Because the feature is still unreleased, the plugin should model third-party packaging directly instead of carrying extra backward-compatibility complexity in core or the workspace lockfile > - This branch therefore makes the E2B provider a standalone publishable package, documents the package-local dev flow, and keeps the publish manifest/runtime dependency story correct > - The benefit is that E2B becomes a true plugin reference implementation that can be installed by package name without reopening core Paperclip code ## What Changed - Added `packages/plugins/paperclip-plugin-e2b` as the E2B sandbox provider plugin package - Implemented config validation, lease acquire/resume/release/destroy handlers, workspace realization, and command execution for E2B sandboxes - Excluded the E2B plugin package from the root workspace so the repo no longer needs `pnpm-lock.yaml` churn for its third-party dependency graph - Added package-local development/install support plus a prepack manifest generator so the published tarball still declares `@paperclipai/plugin-sdk` and `e2b` runtime dependencies - Addressed review feedback by fixing sandbox cleanup on acquire failures, rejecting blank templates, normalizing fractional `timeoutMs`, and always passing the configured template name to the E2B SDK - Updated focused Vitest coverage for config normalization, validation, acquire cleanup, command execution, and lease release behavior - Updated the Dockerfile deps stage to copy the E2B package manifest so the policy check stays in sync ## Verification - `cd packages/plugins/paperclip-plugin-e2b && pnpm install --ignore-workspace --no-lockfile` - `cd packages/plugins/paperclip-plugin-e2b && pnpm build` - `cd packages/plugins/paperclip-plugin-e2b && pnpm --ignore-workspace test` - `cd packages/plugins/paperclip-plugin-e2b && pnpm --ignore-workspace typecheck` - `cd packages/plugins/paperclip-plugin-e2b && npm pack --dry-run` ## Risks - The package now relies on a prepack manifest rewrite so the publish-time dependency list stays correct while the repo-local dev manifest stays workspace-light - The current repo snapshot is still unreleased, so the generated publish manifest points at the repo SDK version until the normal release flow rewrites versions before publish - Real-world E2B environments may still expose edge cases around lifecycle timing or sandbox metadata beyond the mocked unit coverage > 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 Codex via `codex_local` - Model ID: `gpt-5.4` - Reasoning effort: `high` - Context window observed in runtime session metadata: `258400` tokens - Capabilities used: terminal tool execution, git, GitHub CLI, and local build/test inspection ## 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 - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge
47 lines
1.6 KiB
JavaScript
47 lines
1.6 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
import { dirname, join, resolve } from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
const repoRoot = resolve(__dirname, "..");
|
|
const packageDir = process.cwd();
|
|
const packageJsonPath = join(packageDir, "package.json");
|
|
const sdkPackageJsonPath = join(repoRoot, "packages", "plugins", "sdk", "package.json");
|
|
|
|
if (!existsSync(packageJsonPath)) {
|
|
throw new Error(`No package.json found in plugin directory: ${packageDir}`);
|
|
}
|
|
|
|
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
|
const sdkPackageJson = JSON.parse(readFileSync(sdkPackageJsonPath, "utf8"));
|
|
const publishConfig = packageJson.publishConfig ?? {};
|
|
const dependencies = {
|
|
...(packageJson.dependencies ?? {}),
|
|
"@paperclipai/plugin-sdk": sdkPackageJson.version,
|
|
};
|
|
|
|
const publishPackageJson = {
|
|
name: packageJson.name,
|
|
version: packageJson.version,
|
|
description: packageJson.description,
|
|
license: packageJson.license,
|
|
homepage: packageJson.homepage,
|
|
bugs: packageJson.bugs,
|
|
repository: packageJson.repository,
|
|
type: packageJson.type,
|
|
exports: publishConfig.exports ?? packageJson.exports,
|
|
main: publishConfig.main,
|
|
types: publishConfig.types,
|
|
publishConfig,
|
|
files: packageJson.files,
|
|
paperclipPlugin: packageJson.paperclipPlugin,
|
|
keywords: packageJson.keywords,
|
|
dependencies,
|
|
};
|
|
|
|
writeFileSync(packageJsonPath, `${JSON.stringify(publishPackageJson, null, 2)}\n`);
|
|
|
|
console.log(` ✓ Generated publishable plugin package.json for ${packageJson.name}`);
|