merge: refresh config safety branch

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-08-06 19:12:29 +00:00
commit 674f5d5f2c
9 files changed
+102 -8

No files matched your search

@@ -1,6 +1,6 @@
{
"name": "@paperclipai/plugin-daytona",
"version": "0.1.0",
"version": "0.1.1",
"description": "Daytona sandbox provider plugin for Paperclip environments",
"license": "MIT",
"homepage": "https://github.com/paperclipai/paperclip",
@@ -1,7 +1,7 @@
import type { PaperclipPluginManifestV1 } from "@paperclipai/plugin-sdk";
const PLUGIN_ID = "paperclip.daytona-sandbox-provider";
const PLUGIN_VERSION = "0.1.0";
const PLUGIN_VERSION = "0.1.1";
const manifest: PaperclipPluginManifestV1 = {
id: PLUGIN_ID,
@@ -60,6 +60,7 @@ const manifest: PaperclipPluginManifestV1 = {
type: "string",
description:
"Optional base image or Daytona Image reference. If set, the sandbox is created from this image instead of a snapshot.",
default: "daytonaio/sandbox:0.8.0",
},
language: {
type: "string",
@@ -70,17 +71,20 @@ const manifest: PaperclipPluginManifestV1 = {
type: "integer",
description: "Optional CPU allocation in cores.",
minimum: 1,
default: 4,
},
memory: {
type: "integer",
description:
"Optional memory allocation in GiB. Leave unset to use Daytona defaults; supported sandbox sizes are 1, 2, 4, and 8 GiB.",
"Optional memory allocation in GiB. Supported sandbox sizes are 1, 2, 4, and 8 GiB.",
enum: [1, 2, 4, 8],
default: 4,
},
disk: {
type: "integer",
description: "Optional disk allocation in GiB.",
minimum: 1,
default: 10,
},
gpu: {
type: "integer",
@@ -3901,6 +3901,43 @@ describe("daytona manifest memory config", () => {
});
});
describe("daytona manifest form defaults", () => {
const configSchema = (
manifest.environmentDrivers?.[0]?.configSchema as {
properties?: Record<
string,
{ format?: string; enum?: unknown[]; minimum?: number; default?: unknown }
>;
}
);
const properties = configSchema.properties ?? {};
it("pre-fills sizing and image fields for the environment form", () => {
expect(properties.cpu?.default).toBe(4);
expect(properties.memory?.default).toBe(4);
expect(properties.disk?.default).toBe(10);
expect(properties.image?.default).toBe("daytonaio/sandbox:0.8.0");
});
it("keeps each default within its own schema constraints", () => {
expect(properties.memory?.enum).toContain(properties.memory?.default);
expect(properties.cpu?.default as number).toBeGreaterThanOrEqual(
properties.cpu?.minimum ?? 1,
);
expect(properties.disk?.default as number).toBeGreaterThanOrEqual(
properties.disk?.minimum ?? 1,
);
});
it("declares no default on secret-ref fields, which would be persisted as a company secret", () => {
for (const prop of Object.values(properties)) {
if (prop.format === "secret-ref") {
expect(prop.default).toBeUndefined();
}
}
});
});
describe("buildBwrapCommand advisory wrapper builder", () => {
it("uses su to drop to sandbox user without --unshare-user", () => {
const command = buildBwrapCommand(
@@ -1,6 +1,6 @@
{
"name": "@paperclipai/plugin-exe-dev",
"version": "0.1.1",
"version": "0.1.2",
"description": "exe.dev sandbox provider plugin for Paperclip environments",
"license": "MIT",
"homepage": "https://github.com/paperclipai/paperclip",
@@ -1,7 +1,7 @@
import type { PaperclipPluginManifestV1 } from "@paperclipai/plugin-sdk";
const PLUGIN_ID = "paperclip.exe-dev-sandbox-provider";
const PLUGIN_VERSION = "0.1.1";
const PLUGIN_VERSION = "0.1.2";
const manifest: PaperclipPluginManifestV1 = {
id: PLUGIN_ID,
@@ -80,18 +80,21 @@ const manifest: PaperclipPluginManifestV1 = {
cpu: {
type: "number",
description: "Optional CPU count passed to `exe.dev new --cpu`.",
default: 4,
"x-paperclip-advanced": true,
"x-paperclip-group": "VM resources",
},
memory: {
type: "string",
description: "Optional memory size such as `4GB`.",
default: "4GB",
"x-paperclip-advanced": true,
"x-paperclip-group": "VM resources",
},
disk: {
type: "string",
description: "Optional disk size such as `20GB`.",
default: "20GB",
"x-paperclip-advanced": true,
"x-paperclip-group": "VM resources",
},
@@ -15,6 +15,7 @@ vi.mock("node:child_process", async () => {
});
import plugin, { validateSshPrivateKey } from "./plugin.js";
import manifest from "./manifest.js";
class MockChildProcess extends EventEmitter {
stdout = new EventEmitter();
@@ -842,3 +843,26 @@ describe("exe.dev sandbox provider plugin", () => {
expect(result?.cwd).toBe("/srv/paperclip/no-vm");
});
});
describe("exe-dev manifest form defaults", () => {
const configSchema = (
manifest.environmentDrivers?.[0]?.configSchema as {
properties?: Record<string, { format?: string; default?: unknown }>;
}
);
const properties = configSchema.properties ?? {};
it("pre-fills VM sizing for the environment form", () => {
expect(properties.cpu?.default).toBe(4);
expect(properties.memory?.default).toBe("4GB");
expect(properties.disk?.default).toBe("20GB");
});
it("declares no default on secret-ref fields, which would be persisted as a company secret", () => {
for (const prop of Object.values(properties)) {
if (prop.format === "secret-ref") {
expect(prop.default).toBeUndefined();
}
}
});
});
@@ -1,6 +1,6 @@
{
"name": "@paperclipai/plugin-modal",
"version": "0.1.0",
"version": "0.1.1",
"description": "Modal sandbox provider plugin for Paperclip environments",
"license": "MIT",
"homepage": "https://github.com/paperclipai/paperclip",
@@ -1,7 +1,7 @@
import type { PaperclipPluginManifestV1 } from "@paperclipai/plugin-sdk";
const PLUGIN_ID = "paperclip.modal-sandbox-provider";
const PLUGIN_VERSION = "0.1.0";
const PLUGIN_VERSION = "0.1.1";
const manifest: PaperclipPluginManifestV1 = {
id: PLUGIN_ID,
@@ -31,11 +31,13 @@ const manifest: PaperclipPluginManifestV1 = {
type: "string",
description:
"Modal App name used as the parent for sandboxes. The plugin calls `modal.apps.fromName(appName, { createIfMissing: true })`, so the App is created on first acquire if it does not already exist.",
default: "paperclip",
},
image: {
type: "string",
description:
"Container image reference passed to `modal.images.fromRegistry()`, e.g. `python:3.13` or `node:20`.",
"Container image reference passed to `modal.images.fromRegistry()`, e.g. `python:3.13` or `node:22`. The default `node:22` satisfies the sandbox runtime contract (node, sh, and tar on PATH).",
default: "node:22",
},
tokenId: {
type: "string",
@@ -1,5 +1,7 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
import manifest from "./manifest.js";
const { MockNotFoundError, MockTimeoutError, MockSandboxTimeoutError } = vi.hoisted(() => {
class MockNotFoundError extends Error {}
class MockTimeoutError extends Error {}
@@ -704,3 +706,25 @@ describe("Modal sandbox provider plugin", () => {
});
});
});
describe("modal manifest form defaults", () => {
const configSchema = (
manifest.environmentDrivers?.[0]?.configSchema as {
properties?: Record<string, { format?: string; default?: unknown }>;
}
);
const properties = configSchema.properties ?? {};
it("pre-fills the required app name and image so the form works out of the box", () => {
expect(properties.appName?.default).toBe("paperclip");
expect(properties.image?.default).toBe("node:22");
});
it("declares no default on secret-ref fields, which would be persisted as a company secret", () => {
for (const prop of Object.values(properties)) {
if (prop.format === "secret-ref") {
expect(prop.default).toBeUndefined();
}
}
});
});