mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-26 18:31:34 +01:00
merge: refresh config safety branch
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
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();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user