{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "agent-persona-editor", "title": "Agent Persona Editor", "description": "Controlled canonical Persona authoring editor with bounded lore entries and asset manifests, prompts, governance, sources, and rights", "dependencies": ["@wener/ai@^0.1.21", "daisyui", "lucide-react"], "registryDependencies": ["https://ui-components.wener.me/r/ai-config-editor.json"], "files": [ { "path": "registry/default/blocks/agent-persona-editor/agent-persona-editor-types.ts", "content": "import type { Persona } from '@wener/ai/agent/persona';\nimport type { ComponentPropsWithRef } from 'react';\nimport type {\n\tAiConfigEditorSlots,\n\tAiConfigSchema,\n\tAiConfigValidationMode,\n\tAiResourceEditorMessageOverrides,\n\tAiResourceEditorMessages,\n} from '../../ui/ai-config-editor';\n\nexport type AgentPersonaEditorField =\n\t| 'id'\n\t| 'name'\n\t| 'version'\n\t| 'title'\n\t| 'nickname'\n\t| 'description'\n\t| 'author'\n\t| 'creatorNotes'\n\t| 'tags'\n\t| 'language'\n\t| 'authoring'\n\t| 'prompts'\n\t| 'greetings'\n\t| 'groupGreetings'\n\t| 'lorebook'\n\t| 'assets'\n\t| 'governance'\n\t| 'rights'\n\t| 'metadata'\n\t| 'extensions';\nexport type AgentPersonaEditorSection =\n\t| 'identity'\n\t| 'authoring'\n\t| 'prompts'\n\t| 'author'\n\t| 'lorebook'\n\t| 'assets'\n\t| 'governance'\n\t| 'extensions';\nexport type AgentPersonaEditorMessages = AiResourceEditorMessages;\nexport type AgentPersonaEditorMessageOverrides = AiResourceEditorMessageOverrides<\n\tAgentPersonaEditorField,\n\tAgentPersonaEditorSection\n>;\nexport type AgentPersonaEditorProps = Omit, 'onChange' | 'title'> & {\n\tvalue: Persona;\n\tonChange: (value: Persona) => void;\n\tonSubmit?: (value: Persona) => void;\n\tschema?: AiConfigSchema;\n\tvalidationMode?: AiConfigValidationMode;\n\tdisabled?: boolean;\n\treadOnly?: boolean;\n\tmessages?: AgentPersonaEditorMessageOverrides;\n\tslots?: AiConfigEditorSlots;\n\tmaxLoreEntries?: number;\n\tmaxAssets?: number;\n};\n", "type": "registry:lib", "target": "@components/blocks/agent-persona-editor/agent-persona-editor-types.ts" }, { "path": "registry/default/blocks/agent-persona-editor/persona-lorebook-editor.tsx", "content": "'use client';\n\nimport type { LorebookEntry, PersonaLorebook } from '@wener/ai/agent/persona';\nimport { Plus, Trash2 } from 'lucide-react';\nimport type { ComponentPropsWithRef } from 'react';\nimport {\n\tAiConfigFieldGrid,\n\tAiConfigNumberField,\n\tAiConfigStringListField,\n\tAiConfigTextareaField,\n\tAiConfigTextField,\n\tAiConfigToggleField,\n\tJsonValueEditor,\n\tuseStableListEntries,\n} from '../../ui/ai-config-editor';\n\nexport type PersonaLorebookEditorProps = Omit, 'onChange'> & {\n\tvalue?: PersonaLorebook;\n\tonChange: (value: PersonaLorebook) => void;\n\tdisabled?: boolean;\n\treadOnly?: boolean;\n\tmaxEntries?: number;\n};\n\nexport function PersonaLorebookEditor({\n\tvalue,\n\tonChange,\n\tdisabled = false,\n\treadOnly = false,\n\tmaxEntries = 64,\n\tclassName,\n\t...props\n}: PersonaLorebookEditorProps) {\n\tconst lorebook: PersonaLorebook = value ?? { entries: [], bindings: [] };\n\tconst boundedMax = Number.isInteger(maxEntries) ? Math.max(1, Math.min(maxEntries, 256)) : 64;\n\tconst loreEntries = useStableListEntries(lorebook.entries, 'lore-entry');\n\tconst updateEntry = (index: number, entry: LorebookEntry) =>\n\t\tonChange({\n\t\t\t...lorebook,\n\t\t\tentries: lorebook.entries.map((current, itemIndex) => (itemIndex === index ? entry : current)),\n\t\t});\n\tconst removeEntry = (index: number) =>\n\t\tonChange({ ...lorebook, entries: lorebook.entries.filter((_, itemIndex) => itemIndex !== index) });\n\treturn (\n\t\t
\n\t\t\t\n\t\t\t\t onChange({ ...lorebook, name: optional(name) })}\n\t\t\t\t/>\n\t\t\t\t onChange({ ...lorebook, scanDepth })}\n\t\t\t\t/>\n\t\t\t\t onChange({ ...lorebook, tokenBudget })}\n\t\t\t\t/>\n\t\t\t\t onChange({ ...lorebook, recursive })}\n\t\t\t\t/>\n\t\t\t\n\t\t\t onChange({ ...lorebook, description: optional(description) })}\n\t\t\t/>\n\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t

Lore 条目

\n\t\t\t\t\t

\n\t\t\t\t\t\t{lorebook.entries.length} / {boundedMax}\n\t\t\t\t\t

\n\t\t\t\t
\n\t\t\t\t{!readOnly ? (\n\t\t\t\t\t= boundedMax}\n\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\tonChange({ ...lorebook, entries: [...lorebook.entries, createLorebookEntry(lorebook.entries)] })\n\t\t\t\t\t\t}\n\t\t\t\t\t>\n\t\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t{lorebook.entries.length ? (\n\t\t\t\t\tloreEntries.map(({ item: entry, key }, index) => (\n\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{entry.name || entry.id}\n\t\t\t\t\t\t\t\t{entry.enabled === false ? '停用' : '启用'}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t updateEntry(index, { ...entry, id })}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t updateEntry(index, { ...entry, name: optional(name) })}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t updateEntry(index, { ...entry, priority })}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t updateEntry(index, { ...entry, insertionOrder })}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t updateEntry(index, { ...entry, keys })}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t updateEntry(index, { ...entry, secondaryKeys })}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t updateEntry(index, { ...entry, content })}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t updateEntry(index, { ...entry, enabled })}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t updateEntry(index, { ...entry, constant })}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t updateEntry(index, { ...entry, caseSensitive })}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t updateEntry(index, { ...entry, useRegex })}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{!readOnly ? (\n\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t removeEntry(index)}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t))\n\t\t\t\t) : (\n\t\t\t\t\t
暂无 Lore 条目
\n\t\t\t\t)}\n\t\t\t
\n\t\t\t onChange({ ...lorebook, bindings: bindings as PersonaLorebook['bindings'] })}\n\t\t\t/>\n\t\t\t onChange({ ...lorebook, extensions: extensions as PersonaLorebook['extensions'] })}\n\t\t\t/>\n\t\t
\n\t);\n}\n\nexport function createLorebookEntry(entries: readonly LorebookEntry[]): LorebookEntry {\n\tlet suffix = entries.length + 1;\n\twhile (entries.some((entry) => entry.id === `lore-${suffix}`)) suffix++;\n\treturn { id: `lore-${suffix}`, keys: [], content: '', enabled: true };\n}\n\nfunction optional(value: string): string | undefined {\n\treturn value.trim() ? value : undefined;\n}\n", "type": "registry:component", "target": "@components/blocks/agent-persona-editor/persona-lorebook-editor.tsx" }, { "path": "registry/default/blocks/agent-persona-editor/persona-assets-editor.tsx", "content": "'use client';\n\nimport type { PersonaAsset } from '@wener/ai/agent/persona';\nimport { Plus, Trash2 } from 'lucide-react';\nimport type { ComponentPropsWithRef } from 'react';\nimport {\n\tAiConfigFieldGrid,\n\tAiConfigNumberField,\n\tAiConfigSelectField,\n\tAiConfigStringListField,\n\tAiConfigTextareaField,\n\tAiConfigTextField,\n\tAiConfigToggleField,\n\tuseStableListEntries,\n} from '../../ui/ai-config-editor';\n\nconst assetTypes = ['avatar', 'icon', 'background', 'emotion', 'voice', 'model', 'document', 'other'].map((value) => ({\n\tvalue,\n\tlabel: value,\n}));\nexport type PersonaAssetsEditorProps = Omit, 'onChange'> & {\n\tvalue: readonly PersonaAsset[];\n\tonChange: (value: PersonaAsset[]) => void;\n\tdisabled?: boolean;\n\treadOnly?: boolean;\n\tmaxAssets?: number;\n};\n\nexport function PersonaAssetsEditor({\n\tvalue,\n\tonChange,\n\tdisabled = false,\n\treadOnly = false,\n\tmaxAssets = 64,\n\tclassName,\n\t...props\n}: PersonaAssetsEditorProps) {\n\tconst boundedMax = Number.isInteger(maxAssets) ? Math.max(1, Math.min(maxAssets, 256)) : 64;\n\tconst assetEntries = useStableListEntries(value, 'persona-asset');\n\tconst update = (index: number, asset: PersonaAsset) =>\n\t\tonChange(value.map((current, itemIndex) => (itemIndex === index ? asset : current)));\n\treturn (\n\t\t
\n\t\t\t
\n\t\t\t\t

\n\t\t\t\t\t{value.length} / {boundedMax} 个 manifest;仅保存 URI 和元数据。\n\t\t\t\t

\n\t\t\t\t{!readOnly ? (\n\t\t\t\t\t= boundedMax}\n\t\t\t\t\t\tonClick={() => onChange([...value, createPersonaAsset(value)])}\n\t\t\t\t\t>\n\t\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t{value.length ? (\n\t\t\t\t\tassetEntries.map(({ item: asset, key }, index) => (\n\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{asset.name || asset.id}\n\t\t\t\t\t\t\t\t{asset.type}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t update(index, { ...asset, id })}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t update(index, { ...asset, type: type as PersonaAsset['type'] })}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t update(index, { ...asset, uri })}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t update(index, { ...asset, name: optional(name) })}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t update(index, { ...asset, mediaType: optional(mediaType) })}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t update(index, { ...asset, checksum: optional(checksum) })}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t update(index, { ...asset, size })}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t update(index, { ...asset, description: optional(description) })}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t update(index, { ...asset, tags })}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\tupdate(index, { ...asset, rights: { ...asset.rights, license: optional(license) } })\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\tupdate(index, { ...asset, rights: { ...asset.rights, rightsHolder: optional(rightsHolder) } })\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\tupdate(index, { ...asset, rights: { ...asset.rights, redistributable } })\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{!readOnly ? (\n\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t onChange(value.filter((_, itemIndex) => itemIndex !== index))}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t))\n\t\t\t\t) : (\n\t\t\t\t\t
暂无资源 manifest
\n\t\t\t\t)}\n\t\t\t
\n\t\t
\n\t);\n}\n\nexport function createPersonaAsset(assets: readonly PersonaAsset[]): PersonaAsset {\n\tlet suffix = assets.length + 1;\n\twhile (assets.some((asset) => asset.id === `asset-${suffix}`)) suffix++;\n\treturn { id: `asset-${suffix}`, type: 'other', uri: 'https://cdn.example.com/persona/asset' };\n}\n\nfunction optional(value: string): string | undefined {\n\treturn value.trim() ? value : undefined;\n}\n", "type": "registry:component", "target": "@components/blocks/agent-persona-editor/persona-assets-editor.tsx" }, { "path": "registry/default/blocks/agent-persona-editor/persona-authoring-fields.tsx", "content": "import type { Persona } from '@wener/ai/agent/persona';\nimport { AiConfigFieldGrid, AiConfigStringListField, AiConfigTextareaField } from '../../ui/ai-config-editor';\n\nexport type PersonaSectionFieldsProps = {\n\tvalue: Persona;\n\tonChange: (value: Persona) => void;\n\tdisabled?: boolean;\n\treadOnly?: boolean;\n};\n\nexport function PersonaAuthoringFields({\n\tvalue,\n\tonChange,\n\tdisabled = false,\n\treadOnly = false,\n}: PersonaSectionFieldsProps) {\n\tconst patch = (next: Partial>) =>\n\t\tonChange({ ...value, authoring: { ...value.authoring, ...next } });\n\treturn (\n\t\t\n\t\t\t patch({ background: optional(background) })}\n\t\t\t/>\n\t\t\t patch({ personality: optional(personality) })}\n\t\t\t/>\n\t\t\t patch({ behaviorPolicy: optional(behaviorPolicy) })}\n\t\t\t/>\n\t\t\t patch({ speechStyle: optional(speechStyle) })}\n\t\t\t/>\n\t\t\t patch({ values })}\n\t\t\t/>\n\t\t\t patch({ goals })}\n\t\t\t/>\n\t\t\t patch({ flaws })}\n\t\t\t/>\n\t\t\t patch({ exampleDialogue })}\n\t\t\t/>\n\t\t\n\t);\n}\n\nexport function PersonaPromptFields({\n\tvalue,\n\tonChange,\n\tdisabled = false,\n\treadOnly = false,\n}: PersonaSectionFieldsProps) {\n\tconst patch = (next: Partial>) =>\n\t\tonChange({ ...value, prompts: { ...value.prompts, ...next } });\n\treturn (\n\t\t
\n\t\t\t patch({ system: optional(system) })}\n\t\t\t/>\n\t\t\t patch({ persona: optional(persona) })}\n\t\t\t/>\n\t\t\t patch({ scenario: optional(scenario) })}\n\t\t\t/>\n\t\t\t\n\t\t\t\t\tpatch({ postHistoryInstructions: optional(postHistoryInstructions) })\n\t\t\t\t}\n\t\t\t/>\n\t\t
\n\t);\n}\n\nfunction optional(value: string): string | undefined {\n\treturn value.trim() ? value : undefined;\n}\n", "type": "registry:component", "target": "@components/blocks/agent-persona-editor/persona-authoring-fields.tsx" }, { "path": "registry/default/blocks/agent-persona-editor/persona-governance-fields.tsx", "content": "import type { Persona } from '@wener/ai/agent/persona';\nimport {\n\tAiConfigFieldGrid,\n\tAiConfigSelectField,\n\tAiConfigTextField,\n\tAiConfigToggleField,\n} from '../../ui/ai-config-editor';\n\nconst visibility = ['private', 'unlisted', 'public'].map((value) => ({ value, label: value }));\nconst ratings = ['unknown', 'general', 'teen', 'mature', 'restricted'].map((value) => ({ value, label: value }));\nconst reviewStatuses = ['draft', 'pending', 'approved', 'rejected', 'withdrawn'].map((value) => ({\n\tvalue,\n\tlabel: value,\n}));\n\nexport type PersonaGovernanceFieldsProps = {\n\tvalue: Persona;\n\tonChange: (value: Persona) => void;\n\tdisabled?: boolean;\n\treadOnly?: boolean;\n};\n\nexport function PersonaGovernanceFields({\n\tvalue,\n\tonChange,\n\tdisabled = false,\n\treadOnly = false,\n}: PersonaGovernanceFieldsProps) {\n\tconst locked = disabled || readOnly;\n\tconst patchGovernance = (next: Partial>) =>\n\t\tonChange({ ...value, governance: { ...value.governance, ...next } });\n\tconst patchRights = (next: Partial>) =>\n\t\tonChange({ ...value, rights: { ...value.rights, ...next } });\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\tpatchGovernance({ visibility: next ? (next as NonNullable['visibility']) : undefined })\n\t\t\t\t}\n\t\t\t/>\n\t\t\t\n\t\t\t\t\tpatchGovernance({\n\t\t\t\t\t\tcontentRating: next ? (next as NonNullable['contentRating']) : undefined,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t/>\n\t\t\t\n\t\t\t\t\tpatchGovernance({\n\t\t\t\t\t\treviewStatus: next ? (next as NonNullable['reviewStatus']) : undefined,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t/>\n\t\t\t patchGovernance({ provenance: optional(provenance) })}\n\t\t\t/>\n\t\t\t patchGovernance({ sourceUrl: optional(sourceUrl) })}\n\t\t\t/>\n\t\t\t patchRights({ license: optional(license) })}\n\t\t\t/>\n\t\t\t patchRights({ rightsHolder: optional(rightsHolder) })}\n\t\t\t/>\n\t\t\t patchRights({ source: optional(source) })}\n\t\t\t/>\n\t\t\t patchRights({ redistributable })}\n\t\t\t/>\n\t\t\t patchRights({ commercialUse })}\n\t\t\t/>\n\t\t\n\t);\n}\n\nfunction optional(value: string): string | undefined {\n\treturn value.trim() ? value : undefined;\n}\n", "type": "registry:component", "target": "@components/blocks/agent-persona-editor/persona-governance-fields.tsx" }, { "path": "registry/default/blocks/agent-persona-editor/agent-persona-editor.tsx", "content": "'use client';\n\nimport { type Persona, PersonaSchema } from '@wener/ai/agent/persona';\nimport type { ReactNode } from 'react';\nimport {\n\tAiConfigEditor,\n\tAiConfigFieldGrid,\n\tAiConfigFieldSlot,\n\tAiConfigFormSection,\n\tAiConfigStringListField,\n\tAiConfigTextareaField,\n\tAiConfigTextField,\n\taiConfigFieldError,\n\tJsonValueEditor,\n\tmergeResourceEditorMessages,\n\tuseAiConfigDraft,\n} from '../../ui/ai-config-editor';\nimport type {\n\tAgentPersonaEditorField,\n\tAgentPersonaEditorMessages,\n\tAgentPersonaEditorProps,\n} from './agent-persona-editor-types';\nimport { PersonaAssetsEditor } from './persona-assets-editor';\nimport { PersonaAuthoringFields, PersonaPromptFields } from './persona-authoring-fields';\nimport { PersonaGovernanceFields } from './persona-governance-fields';\nimport { PersonaLorebookEditor } from './persona-lorebook-editor';\n\nexport const defaultAgentPersona: Persona = PersonaSchema.parse({\n\tid: 'persona-new',\n\tname: '新角色',\n\tversion: '1.0.0',\n});\nconst defaultMessages: AgentPersonaEditorMessages = {\n\ttitle: 'Agent Persona 配置',\n\tdescription: '编辑角色 authoring、prompts、Lorebook、资源 manifest 与治理信息。',\n\tsections: {\n\t\tidentity: '身份',\n\t\tauthoring: '性格与行为',\n\t\tprompts: 'Prompts 与问候语',\n\t\tauthor: '作者',\n\t\tlorebook: 'Lorebook',\n\t\tassets: '资源 Manifest',\n\t\tgovernance: '来源、治理与权利',\n\t\textensions: 'Metadata 与 Extensions',\n\t},\n\tfields: {\n\t\tid: 'ID',\n\t\tname: '名称',\n\t\tversion: '版本',\n\t\ttitle: '显示名称',\n\t\tnickname: '昵称',\n\t\tdescription: '描述',\n\t\tauthor: '作者',\n\t\tcreatorNotes: '创作者备注',\n\t\ttags: '标签',\n\t\tlanguage: '语言',\n\t\tauthoring: 'Authoring',\n\t\tprompts: 'Prompts',\n\t\tgreetings: '问候语',\n\t\tgroupGreetings: '群组问候语',\n\t\tlorebook: 'Lorebook',\n\t\tassets: '资源',\n\t\tgovernance: '治理',\n\t\trights: 'Rights',\n\t\tmetadata: 'Metadata',\n\t\textensions: 'Extensions',\n\t},\n};\n\nexport function AgentPersonaEditor({\n\tvalue,\n\tonChange,\n\tonSubmit,\n\tschema = PersonaSchema,\n\tvalidationMode,\n\tdisabled = false,\n\treadOnly = false,\n\tmessages: overrides,\n\tslots,\n\tmaxLoreEntries = 64,\n\tmaxAssets = 64,\n\t...props\n}: AgentPersonaEditorProps) {\n\tconst messages = mergeResourceEditorMessages(defaultMessages, overrides);\n\tconst controller = useAiConfigDraft({\n\t\tvalue,\n\t\tfallbackValue: defaultAgentPersona,\n\t\tschema,\n\t\tonChange,\n\t\tonSubmit,\n\t\tvalidationMode,\n\t});\n\tconst draft = controller.draft;\n\tconst patch = (next: Partial) => controller.setDraft({ ...draft, ...next });\n\tconst field = (name: AgentPersonaEditorField, defaultField: ReactNode) => (\n\t\t\n\t);\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{field(\n\t\t\t\t\t\t'id',\n\t\t\t\t\t\t patch({ id })}\n\t\t\t\t\t\t/>,\n\t\t\t\t\t)}\n\t\t\t\t\t{field(\n\t\t\t\t\t\t'name',\n\t\t\t\t\t\t patch({ name })}\n\t\t\t\t\t\t/>,\n\t\t\t\t\t)}\n\t\t\t\t\t{field(\n\t\t\t\t\t\t'version',\n\t\t\t\t\t\t patch({ version })}\n\t\t\t\t\t\t/>,\n\t\t\t\t\t)}\n\t\t\t\t\t{field(\n\t\t\t\t\t\t'title',\n\t\t\t\t\t\t patch({ title: optional(title) })}\n\t\t\t\t\t\t/>,\n\t\t\t\t\t)}\n\t\t\t\t\t{field(\n\t\t\t\t\t\t'nickname',\n\t\t\t\t\t\t patch({ nickname: optional(nickname) })}\n\t\t\t\t\t\t/>,\n\t\t\t\t\t)}\n\t\t\t\t\t{field(\n\t\t\t\t\t\t'language',\n\t\t\t\t\t\t patch({ language: optional(language) })}\n\t\t\t\t\t\t/>,\n\t\t\t\t\t)}\n\t\t\t\t\n\t\t\t\t{field(\n\t\t\t\t\t'description',\n\t\t\t\t\t patch({ description: optional(description) })}\n\t\t\t\t\t/>,\n\t\t\t\t)}\n\t\t\t\t{field(\n\t\t\t\t\t'tags',\n\t\t\t\t\t patch({ tags })}\n\t\t\t\t\t/>,\n\t\t\t\t)}\n\t\t\t\n\t\t\t\n\t\t\t\t{field(\n\t\t\t\t\t'authoring',\n\t\t\t\t\t,\n\t\t\t\t)}\n\t\t\t\n\t\t\t\n\t\t\t\t{field(\n\t\t\t\t\t'prompts',\n\t\t\t\t\t,\n\t\t\t\t)}\n\t\t\t\t
\n\t\t\t\t\t{field(\n\t\t\t\t\t\t'greetings',\n\t\t\t\t\t\t patch({ greetings })}\n\t\t\t\t\t\t/>,\n\t\t\t\t\t)}\n\t\t\t\t\t{field(\n\t\t\t\t\t\t'groupGreetings',\n\t\t\t\t\t\t patch({ groupGreetings })}\n\t\t\t\t\t\t/>,\n\t\t\t\t\t)}\n\t\t\t\t
\n\t\t\t
\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t patch({ author: name.trim() ? { ...draft.author, name } : undefined })}\n\t\t\t\t\t/>\n\t\t\t\t\t draft.author && patch({ author: { ...draft.author, id: optional(id) } })}\n\t\t\t\t\t/>\n\t\t\t\t\t draft.author && patch({ author: { ...draft.author, url: optional(url) } })}\n\t\t\t\t\t/>\n\t\t\t\t\t\n\t\t\t\t\t\t\tdraft.author && patch({ author: { ...draft.author, contact: optional(contact) } })\n\t\t\t\t\t\t}\n\t\t\t\t\t/>\n\t\t\t\t\n\t\t\t\t{field(\n\t\t\t\t\t'creatorNotes',\n\t\t\t\t\t patch({ creatorNotes: optional(creatorNotes) })}\n\t\t\t\t\t/>,\n\t\t\t\t)}\n\t\t\t\n\t\t\t\n\t\t\t\t{field(\n\t\t\t\t\t'lorebook',\n\t\t\t\t\t patch({ lorebook })}\n\t\t\t\t\t/>,\n\t\t\t\t)}\n\t\t\t\n\t\t\t\n\t\t\t\t{field(\n\t\t\t\t\t'assets',\n\t\t\t\t\t patch({ assets })}\n\t\t\t\t\t/>,\n\t\t\t\t)}\n\t\t\t\n\t\t\t\n\t\t\t\t{field(\n\t\t\t\t\t'governance',\n\t\t\t\t\t,\n\t\t\t\t)}\n\t\t\t\n\t\t\t\n\t\t\t\t
\n\t\t\t\t\t{field(\n\t\t\t\t\t\t'metadata',\n\t\t\t\t\t\t patch({ metadata: metadata as Persona['metadata'] })}\n\t\t\t\t\t\t/>,\n\t\t\t\t\t)}\n\t\t\t\t\t{field(\n\t\t\t\t\t\t'extensions',\n\t\t\t\t\t\t patch({ extensions: extensions as Persona['extensions'] })}\n\t\t\t\t\t\t/>,\n\t\t\t\t\t)}\n\t\t\t\t
\n\t\t\t
\n\t\t\n\t);\n}\n\nfunction optional(value: string): string | undefined {\n\treturn value.trim() ? value : undefined;\n}\n", "type": "registry:component", "target": "@components/blocks/agent-persona-editor/agent-persona-editor.tsx" }, { "path": "registry/default/blocks/agent-persona-editor/index.ts", "content": "export * from './agent-persona-editor';\nexport * from './agent-persona-editor-types';\nexport * from './persona-assets-editor';\nexport * from './persona-authoring-fields';\nexport * from './persona-governance-fields';\nexport * from './persona-lorebook-editor';\n", "type": "registry:component", "target": "@components/blocks/agent-persona-editor/index.ts" } ], "type": "registry:block" }