Files
paperclip/packages/shared/src/validators/agent.ts
T
Forgotten cf237d2e7f feat: add agent icons with picker and collapsible sidebar section
- Add `icon` text column to agents DB schema with migration
- Add icon field to shared Agent type and validators
- Create AgentIconPicker component with 40+ curated lucide icons and search
- Show clickable icon next to agent name on detail page header
- Replace static Agents nav item with collapsible AGENTS section in sidebar
- Each agent shows its icon (defaulting to Bot) with truncated name

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 12:25:13 -06:00

94 lines
3.1 KiB
TypeScript

import { z } from "zod";
import {
AGENT_ADAPTER_TYPES,
AGENT_ROLES,
AGENT_STATUSES,
} from "../constants.js";
import { envConfigSchema } from "./secret.js";
export const agentPermissionsSchema = z.object({
canCreateAgents: z.boolean().optional().default(false),
});
const adapterConfigSchema = z.record(z.unknown()).superRefine((value, ctx) => {
const envValue = value.env;
if (envValue === undefined) return;
const parsed = envConfigSchema.safeParse(envValue);
if (!parsed.success) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: "adapterConfig.env must be a map of valid env bindings",
path: ["env"],
});
}
});
export const createAgentSchema = z.object({
name: z.string().min(1),
role: z.enum(AGENT_ROLES).optional().default("general"),
title: z.string().optional().nullable(),
icon: z.string().optional().nullable(),
reportsTo: z.string().uuid().optional().nullable(),
capabilities: z.string().optional().nullable(),
adapterType: z.enum(AGENT_ADAPTER_TYPES).optional().default("process"),
adapterConfig: adapterConfigSchema.optional().default({}),
runtimeConfig: z.record(z.unknown()).optional().default({}),
budgetMonthlyCents: z.number().int().nonnegative().optional().default(0),
permissions: agentPermissionsSchema.optional(),
metadata: z.record(z.unknown()).optional().nullable(),
});
export type CreateAgent = z.infer<typeof createAgentSchema>;
export const createAgentHireSchema = createAgentSchema.extend({
sourceIssueId: z.string().uuid().optional().nullable(),
sourceIssueIds: z.array(z.string().uuid()).optional(),
});
export type CreateAgentHire = z.infer<typeof createAgentHireSchema>;
export const updateAgentSchema = createAgentSchema
.omit({ permissions: true })
.partial()
.extend({
permissions: z.never().optional(),
status: z.enum(AGENT_STATUSES).optional(),
spentMonthlyCents: z.number().int().nonnegative().optional(),
});
export type UpdateAgent = z.infer<typeof updateAgentSchema>;
export const createAgentKeySchema = z.object({
name: z.string().min(1).default("default"),
});
export type CreateAgentKey = z.infer<typeof createAgentKeySchema>;
export const wakeAgentSchema = z.object({
source: z.enum(["timer", "assignment", "on_demand", "automation"]).optional().default("on_demand"),
triggerDetail: z.enum(["manual", "ping", "callback", "system"]).optional(),
reason: z.string().optional().nullable(),
payload: z.record(z.unknown()).optional().nullable(),
idempotencyKey: z.string().optional().nullable(),
});
export type WakeAgent = z.infer<typeof wakeAgentSchema>;
export const resetAgentSessionSchema = z.object({
taskKey: z.string().min(1).optional().nullable(),
});
export type ResetAgentSession = z.infer<typeof resetAgentSessionSchema>;
export const testAdapterEnvironmentSchema = z.object({
adapterConfig: adapterConfigSchema.optional().default({}),
});
export type TestAdapterEnvironment = z.infer<typeof testAdapterEnvironmentSchema>;
export const updateAgentPermissionsSchema = z.object({
canCreateAgents: z.boolean(),
});
export type UpdateAgentPermissions = z.infer<typeof updateAgentPermissionsSchema>;