Files
PaperClipAI/server/src/__tests__/agent-runtime-settings.test.ts
T
DottaandPaperclip 9bf7dc0c8f feat(agents): bulk edit connections and default models (#17215)
Add harness-scoped bulk connection and default-model edits to the agent roster, with compatible choices, change previews, per-agent save results, and retries.

Use an icon-based harness filter, keep agent rows readable, remove the status selector and selection hint, and redirect legacy status URLs to the full roster.

Preserve authorization, audit history, unrelated settings, and optimistic concurrency checks through the existing agent update route.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-22 18:47:06 -05:00

28 lines
2.4 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { agentRuntimeSettingsPatchSchema, type AgentRuntimeSettingsPatch } from "@paperclipai/shared";
import { prepareRuntimeSettingsPatch } from "../services/agent-runtime-settings.js";
const connection = { provider: "openai", method: "api_key", mode: "responsible_user" } as const;
const existing = { adapterType: "paperclip_runner", adapterConfig: { provider: "codex", model: "old", cwd: "/workspace", env: { PRESERVE: "value" } }, runtimeConfig: { heartbeat: { intervalSec: 900 }, aiConnection: connection }, status: "paused" };
const settings: AgentRuntimeSettingsPatch = { harness: "codex_local", model: "new", expected: { model: "old", aiConnection: connection } };
describe("roster runtime settings patches", () => {
it("changes only the requested fields and retains unrelated runtime settings", () => {
expect(prepareRuntimeSettingsPatch(existing, { runtimeSettings: settings })).toEqual({ adapterConfig: { model: "new" } });
const next = { ...connection, method: "subscription" } as const;
expect(prepareRuntimeSettingsPatch(existing, { runtimeSettings: { ...settings, model: undefined, aiConnection: next } })).toEqual({ runtimeConfig: { heartbeat: { intervalSec: 900 }, aiConnection: next } });
expect(existing.adapterConfig.model).toBe("old");
});
it("rejects stale previews, harness switches, and mixed broad patches", () => {
expect(() => prepareRuntimeSettingsPatch(existing, { runtimeSettings: { ...settings, harness: "claude_local" } })).toThrow("harness changed");
expect(() => prepareRuntimeSettingsPatch(existing, { runtimeSettings: { ...settings, expected: { ...settings.expected, model: "stale" } } })).toThrow("connection or model changed");
expect(() => prepareRuntimeSettingsPatch(existing, { runtimeSettings: settings, name: "Unexpected rename" })).toThrow("cannot be combined");
expect(() => prepareRuntimeSettingsPatch({ ...existing, status: "terminated" }, { runtimeSettings: settings })).toThrow("cannot be updated");
});
it("requires an explicit edit and rejects extra fields inside the intent", () => {
expect(agentRuntimeSettingsPatchSchema.safeParse({ harness: "codex_local", expected: settings.expected }).success).toBe(false);
expect(agentRuntimeSettingsPatchSchema.safeParse({ ...settings, model: " " }).success).toBe(false);
expect(agentRuntimeSettingsPatchSchema.safeParse({ ...settings, status: "idle" }).success).toBe(false);
});
});