| |
|
|
| import { describe, expect, it } from "vitest"; |
| import type { Agent } from "@penclipai/shared"; |
| import { buildAgentUpdatePatch, type AgentConfigOverlay } from "./agent-config-patch"; |
|
|
| function makeAgent(): Agent { |
| return { |
| id: "agent-1", |
| companyId: "company-1", |
| name: "Agent", |
| role: "engineer", |
| title: "Engineer", |
| icon: null, |
| status: "active", |
| reportsTo: null, |
| capabilities: null, |
| adapterType: "claude_local", |
| adapterConfig: { |
| model: "claude-sonnet-4-6", |
| env: { |
| OPENAI_API_KEY: { |
| type: "plain", |
| value: "secret", |
| }, |
| }, |
| promptTemplate: "Work the issue.", |
| }, |
| runtimeConfig: { |
| heartbeat: { |
| enabled: true, |
| intervalSec: 300, |
| }, |
| }, |
| budgetMonthlyCents: 0, |
| spentMonthlyCents: 0, |
| pauseReason: null, |
| pausedAt: null, |
| lastHeartbeatAt: null, |
| createdAt: new Date("2026-01-01T00:00:00.000Z"), |
| updatedAt: new Date("2026-01-01T00:00:00.000Z"), |
| urlKey: "agent", |
| permissions: { |
| canCreateAgents: false, |
| }, |
| metadata: null, |
| }; |
| } |
|
|
| function makeOverlay(patch?: Partial<AgentConfigOverlay>): AgentConfigOverlay { |
| return { |
| identity: {}, |
| adapterConfig: {}, |
| heartbeat: {}, |
| runtime: {}, |
| ...patch, |
| }; |
| } |
|
|
| describe("buildAgentUpdatePatch", () => { |
| it("replaces adapter config and drops env when the last env binding is cleared", () => { |
| const patch = buildAgentUpdatePatch( |
| makeAgent(), |
| makeOverlay({ |
| adapterConfig: { |
| env: undefined, |
| }, |
| }), |
| ); |
|
|
| expect(patch).toEqual({ |
| adapterConfig: { |
| model: "claude-sonnet-4-6", |
| promptTemplate: "Work the issue.", |
| }, |
| replaceAdapterConfig: true, |
| }); |
| }); |
|
|
| it("preserves adapter-agnostic keys when changing adapter types", () => { |
| const patch = buildAgentUpdatePatch( |
| makeAgent(), |
| makeOverlay({ |
| adapterType: "codex_local", |
| adapterConfig: { |
| model: "gpt-5.4", |
| dangerouslyBypassApprovalsAndSandbox: true, |
| }, |
| }), |
| ); |
|
|
| expect(patch).toEqual({ |
| adapterType: "codex_local", |
| adapterConfig: { |
| env: { |
| OPENAI_API_KEY: { |
| type: "plain", |
| value: "secret", |
| }, |
| }, |
| promptTemplate: "Work the issue.", |
| model: "gpt-5.4", |
| dangerouslyBypassApprovalsAndSandbox: true, |
| }, |
| replaceAdapterConfig: true, |
| }); |
| }); |
| }); |
|
|