mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-12 06:10:44 +01:00
Introduce company-scoped computer attachments, bounded runner and viewer ownership, persistent files and worktrees, Boat ingress, and native and legacy runtime integration behind the experimental Boat flag. Keep desktop UI and extended acceptance cases in the stacked feature branch. Co-Authored-By: Paperclip <noreply@paperclip.ing>
121 lines
4.6 KiB
TypeScript
121 lines
4.6 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
adapterSupportsRemoteManagedEnvironments,
|
|
getEnvironmentCapabilities,
|
|
isSandboxProviderSupportedForAdapter,
|
|
supportedEnvironmentDriversForAdapter,
|
|
} from "./environment-support.js";
|
|
|
|
describe("isSandboxProviderSupportedForAdapter", () => {
|
|
it("treats Paperclip Runner as a remote-managed adapter", () => {
|
|
expect(adapterSupportsRemoteManagedEnvironments("paperclip_runner")).toBe(true);
|
|
expect(supportedEnvironmentDriversForAdapter("paperclip_runner")).toEqual([
|
|
"local",
|
|
"ssh",
|
|
"sandbox",
|
|
"computer",
|
|
]);
|
|
});
|
|
|
|
it.each(["claude_local", "codex_local", "paperclip_runner"] as const)(
|
|
"exposes computer environments for %s",
|
|
(adapterType) => {
|
|
const capabilities = getEnvironmentCapabilities([adapterType]);
|
|
expect(supportedEnvironmentDriversForAdapter(adapterType)).toContain("computer");
|
|
expect(capabilities.adapters[0].drivers.computer).toBe("supported");
|
|
},
|
|
);
|
|
|
|
it.each(["cursor", "gemini_local", "grok_local", "kimi_local", "openclaw"] as const)(
|
|
"does not advertise unqualified computer support for %s",
|
|
(adapterType) => {
|
|
const capabilities = getEnvironmentCapabilities([adapterType]);
|
|
expect(supportedEnvironmentDriversForAdapter(adapterType)).not.toContain("computer");
|
|
expect(capabilities.adapters[0].drivers.computer).toBe("unsupported");
|
|
},
|
|
);
|
|
|
|
it("accepts additional sandbox providers for remote-managed adapters", () => {
|
|
expect(
|
|
isSandboxProviderSupportedForAdapter("codex_local", "fake-plugin", ["fake-plugin"]),
|
|
).toBe(true);
|
|
});
|
|
|
|
it("rejects providers for adapters without remote-managed environment support", () => {
|
|
expect(
|
|
isSandboxProviderSupportedForAdapter("openclaw", "fake-plugin", ["fake-plugin"]),
|
|
).toBe(false);
|
|
});
|
|
|
|
it("treats grok_local as a remote-managed local adapter", () => {
|
|
expect(adapterSupportsRemoteManagedEnvironments("grok_local")).toBe(true);
|
|
expect(supportedEnvironmentDriversForAdapter("grok_local")).toEqual(["local", "ssh", "sandbox"]);
|
|
expect(
|
|
isSandboxProviderSupportedForAdapter("grok_local", "fake-plugin", ["fake-plugin"]),
|
|
).toBe(true);
|
|
});
|
|
|
|
it("includes grok_local sandbox support in environment capabilities", () => {
|
|
const capabilities = getEnvironmentCapabilities(["grok_local"], {
|
|
sandboxProviders: {
|
|
"fake-plugin": { displayName: "Fake Plugin" },
|
|
},
|
|
});
|
|
|
|
expect(capabilities.adapters).toEqual([
|
|
expect.objectContaining({
|
|
adapterType: "grok_local",
|
|
drivers: expect.objectContaining({ sandbox: "supported", ssh: "supported" }),
|
|
sandboxProviders: expect.objectContaining({ "fake-plugin": "supported" }),
|
|
}),
|
|
]);
|
|
});
|
|
|
|
it("treats kimi_local as a remote-managed local adapter", () => {
|
|
expect(adapterSupportsRemoteManagedEnvironments("kimi_local")).toBe(true);
|
|
expect(supportedEnvironmentDriversForAdapter("kimi_local")).toEqual(["local", "ssh", "sandbox"]);
|
|
expect(
|
|
isSandboxProviderSupportedForAdapter("kimi_local", "fake-plugin", ["fake-plugin"]),
|
|
).toBe(true);
|
|
});
|
|
|
|
it("includes kimi_local sandbox support in environment capabilities", () => {
|
|
const capabilities = getEnvironmentCapabilities(["kimi_local"], {
|
|
sandboxProviders: {
|
|
"fake-plugin": { displayName: "Fake Plugin" },
|
|
},
|
|
});
|
|
|
|
expect(capabilities.adapters).toEqual([
|
|
expect.objectContaining({
|
|
adapterType: "kimi_local",
|
|
drivers: expect.objectContaining({ sandbox: "supported", ssh: "supported" }),
|
|
sandboxProviders: expect.objectContaining({ "fake-plugin": "supported" }),
|
|
}),
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe("getEnvironmentCapabilities reusable leases default", () => {
|
|
it("test_absent_reusable_leases_presents_as_false", () => {
|
|
const capabilities = getEnvironmentCapabilities(["codex_local"], {
|
|
sandboxProviders: {
|
|
// The manifest does not declare supportsReusableLeases.
|
|
"fake-plugin": { displayName: "Fake Plugin" },
|
|
},
|
|
});
|
|
expect(capabilities.sandboxProviders["fake-plugin"].supportsReusableLeases).toBe(false);
|
|
|
|
// A manifest that declares true still presents as true.
|
|
const declared = getEnvironmentCapabilities(["codex_local"], {
|
|
sandboxProviders: {
|
|
"reuse-plugin": { displayName: "Reuse Plugin", supportsReusableLeases: true },
|
|
},
|
|
});
|
|
expect(declared.sandboxProviders["reuse-plugin"].supportsReusableLeases).toBe(true);
|
|
|
|
// The built-in fake provider presents as false.
|
|
expect(capabilities.sandboxProviders.fake.supportsReusableLeases).toBe(false);
|
|
});
|
|
});
|