@humaan/payload-plugin-ai-assistant 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +277 -2
- package/dist/admin/AiAssistantControl.d.ts +11 -0
- package/dist/admin/AiAssistantControl.js +31 -0
- package/dist/admin/AiAssistantControl.js.map +1 -0
- package/dist/admin/AiAssistantPanel.d.ts +10 -0
- package/dist/admin/AiAssistantPanel.js +208 -0
- package/dist/admin/AiAssistantPanel.js.map +1 -0
- package/dist/admin/AiAssistantPanel.module.scss +689 -0
- package/dist/admin/AiSourceSwitch.d.ts +13 -0
- package/dist/admin/AiSourceSwitch.js +14 -0
- package/dist/admin/AiSourceSwitch.js.map +1 -0
- package/dist/admin/BudgetField.d.ts +8 -0
- package/dist/admin/BudgetField.js +145 -0
- package/dist/admin/BudgetField.js.map +1 -0
- package/dist/admin/BudgetField.module.scss +47 -0
- package/dist/admin/Conversation.d.ts +12 -0
- package/dist/admin/Conversation.js +469 -0
- package/dist/admin/Conversation.js.map +1 -0
- package/dist/admin/Markdown.d.ts +9 -0
- package/dist/admin/Markdown.js +63 -0
- package/dist/admin/Markdown.js.map +1 -0
- package/dist/admin/PageContextBridge.d.ts +5 -0
- package/dist/admin/PageContextBridge.js +72 -0
- package/dist/admin/PageContextBridge.js.map +1 -0
- package/dist/admin/Pill.d.ts +11 -0
- package/dist/admin/Pill.js +27 -0
- package/dist/admin/Pill.js.map +1 -0
- package/dist/admin/PlanCard.d.ts +14 -0
- package/dist/admin/PlanCard.js +465 -0
- package/dist/admin/PlanCard.js.map +1 -0
- package/dist/admin/SettingsAlerts.d.ts +7 -0
- package/dist/admin/SettingsAlerts.js +37 -0
- package/dist/admin/SettingsAlerts.js.map +1 -0
- package/dist/admin/UsageSummary.d.ts +11 -0
- package/dist/admin/UsageSummary.js +129 -0
- package/dist/admin/UsageSummary.js.map +1 -0
- package/dist/admin/attachmentUpload.d.ts +25 -0
- package/dist/admin/attachmentUpload.js +76 -0
- package/dist/admin/attachmentUpload.js.map +1 -0
- package/dist/admin/openDocument.d.ts +13 -0
- package/dist/admin/openDocument.js +34 -0
- package/dist/admin/openDocument.js.map +1 -0
- package/dist/admin/percent.d.ts +10 -0
- package/dist/admin/percent.js +21 -0
- package/dist/admin/percent.js.map +1 -0
- package/dist/admin/threads.d.ts +21 -0
- package/dist/admin/threads.js +92 -0
- package/dist/admin/threads.js.map +1 -0
- package/dist/admin/toolSteps.d.ts +12 -0
- package/dist/admin/toolSteps.js +57 -0
- package/dist/admin/toolSteps.js.map +1 -0
- package/dist/admin/transport.d.ts +24 -0
- package/dist/admin/transport.js +75 -0
- package/dist/admin/transport.js.map +1 -0
- package/dist/admin/useAttachments.d.ts +32 -0
- package/dist/admin/useAttachments.js +91 -0
- package/dist/admin/useAttachments.js.map +1 -0
- package/dist/admin/useEntityLabel.d.ts +3 -0
- package/dist/admin/useEntityLabel.js +23 -0
- package/dist/admin/useEntityLabel.js.map +1 -0
- package/dist/attachments/collection.d.ts +15 -0
- package/dist/attachments/collection.js +90 -0
- package/dist/attachments/collection.js.map +1 -0
- package/dist/attachments/conversation.d.ts +25 -0
- package/dist/attachments/conversation.js +105 -0
- package/dist/attachments/conversation.js.map +1 -0
- package/dist/attachments/rules.d.ts +9 -0
- package/dist/attachments/rules.js +17 -0
- package/dist/attachments/rules.js.map +1 -0
- package/dist/attachments/store.d.ts +27 -0
- package/dist/attachments/store.js +187 -0
- package/dist/attachments/store.js.map +1 -0
- package/dist/billing.d.ts +60 -0
- package/dist/billing.js +116 -0
- package/dist/billing.js.map +1 -0
- package/dist/chat/history.d.ts +37 -0
- package/dist/chat/history.js +165 -0
- package/dist/chat/history.js.map +1 -0
- package/dist/chat/messages.d.ts +5 -0
- package/dist/chat/messages.js +3 -0
- package/dist/chat/messages.js.map +1 -0
- package/dist/chat/threads.d.ts +33 -0
- package/dist/chat/threads.js +77 -0
- package/dist/chat/threads.js.map +1 -0
- package/dist/chat/tools.d.ts +76 -0
- package/dist/chat/tools.js +596 -0
- package/dist/chat/tools.js.map +1 -0
- package/dist/chat/usage.d.ts +66 -0
- package/dist/chat/usage.js +219 -0
- package/dist/chat/usage.js.map +1 -0
- package/dist/collectionAccess.d.ts +6 -0
- package/dist/collectionAccess.js +32 -0
- package/dist/collectionAccess.js.map +1 -0
- package/dist/constants.d.ts +64 -0
- package/dist/constants.js +51 -0
- package/dist/constants.js.map +1 -0
- package/dist/endpoints/access.d.ts +4 -0
- package/dist/endpoints/access.js +28 -0
- package/dist/endpoints/access.js.map +1 -0
- package/dist/endpoints/allowance.d.ts +22 -0
- package/dist/endpoints/allowance.js +37 -0
- package/dist/endpoints/allowance.js.map +1 -0
- package/dist/endpoints/applyEndpoint.d.ts +12 -0
- package/dist/endpoints/applyEndpoint.js +170 -0
- package/dist/endpoints/applyEndpoint.js.map +1 -0
- package/dist/endpoints/budget.d.ts +30 -0
- package/dist/endpoints/budget.js +153 -0
- package/dist/endpoints/budget.js.map +1 -0
- package/dist/endpoints/chatEndpoint.d.ts +12 -0
- package/dist/endpoints/chatEndpoint.js +295 -0
- package/dist/endpoints/chatEndpoint.js.map +1 -0
- package/dist/endpoints/form.d.ts +23 -0
- package/dist/endpoints/form.js +95 -0
- package/dist/endpoints/form.js.map +1 -0
- package/dist/endpoints/usageEndpoint.d.ts +13 -0
- package/dist/endpoints/usageEndpoint.js +70 -0
- package/dist/endpoints/usageEndpoint.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/lexical/editorConfig.d.ts +4 -0
- package/dist/lexical/editorConfig.js +19 -0
- package/dist/lexical/editorConfig.js.map +1 -0
- package/dist/lexical/lexicalToMarkdown.d.ts +10 -0
- package/dist/lexical/lexicalToMarkdown.js +10 -0
- package/dist/lexical/lexicalToMarkdown.js.map +1 -0
- package/dist/lexical/markdownToLexical.d.ts +7 -0
- package/dist/lexical/markdownToLexical.js +10 -0
- package/dist/lexical/markdownToLexical.js.map +1 -0
- package/dist/plan/allowed.d.ts +7 -0
- package/dist/plan/allowed.js +19 -0
- package/dist/plan/allowed.js.map +1 -0
- package/dist/plan/applyPlan.d.ts +16 -0
- package/dist/plan/applyPlan.js +353 -0
- package/dist/plan/applyPlan.js.map +1 -0
- package/dist/plan/catalogue.d.ts +37 -0
- package/dist/plan/catalogue.js +157 -0
- package/dist/plan/catalogue.js.map +1 -0
- package/dist/plan/diff.d.ts +13 -0
- package/dist/plan/diff.js +87 -0
- package/dist/plan/diff.js.map +1 -0
- package/dist/plan/parsePlan.d.ts +27 -0
- package/dist/plan/parsePlan.js +322 -0
- package/dist/plan/parsePlan.js.map +1 -0
- package/dist/plan/prompt.d.ts +1 -0
- package/dist/plan/prompt.js +45 -0
- package/dist/plan/prompt.js.map +1 -0
- package/dist/plan/stored.d.ts +53 -0
- package/dist/plan/stored.js +3 -0
- package/dist/plan/stored.js.map +1 -0
- package/dist/plan/tokens.d.ts +8 -0
- package/dist/plan/tokens.js +79 -0
- package/dist/plan/tokens.js.map +1 -0
- package/dist/plan/view.d.ts +4 -0
- package/dist/plan/view.js +43 -0
- package/dist/plan/view.js.map +1 -0
- package/dist/plugin.d.ts +3 -0
- package/dist/plugin.js +464 -0
- package/dist/plugin.js.map +1 -0
- package/dist/read/outline.d.ts +7 -0
- package/dist/read/outline.js +70 -0
- package/dist/read/outline.js.map +1 -0
- package/dist/read/readTarget.d.ts +4 -0
- package/dist/read/readTarget.js +13 -0
- package/dist/read/readTarget.js.map +1 -0
- package/dist/read/readable.d.ts +8 -0
- package/dist/read/readable.js +131 -0
- package/dist/read/readable.js.map +1 -0
- package/dist/runtime.d.ts +15 -0
- package/dist/runtime.js +14 -0
- package/dist/runtime.js.map +1 -0
- package/dist/schema/fields.d.ts +113 -0
- package/dist/schema/fields.js +1036 -0
- package/dist/schema/fields.js.map +1 -0
- package/dist/schema/listingFields.d.ts +9 -0
- package/dist/schema/listingFields.js +95 -0
- package/dist/schema/listingFields.js.map +1 -0
- package/dist/schema/slugify.d.ts +2 -0
- package/dist/schema/slugify.js +5 -0
- package/dist/schema/slugify.js.map +1 -0
- package/dist/settings.d.ts +10 -0
- package/dist/settings.js +54 -0
- package/dist/settings.js.map +1 -0
- package/dist/types.d.ts +198 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/dist/uploads/routeAsset.d.ts +27 -0
- package/dist/uploads/routeAsset.js +127 -0
- package/dist/uploads/routeAsset.js.map +1 -0
- package/package.json +122 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/schema/fields.ts"],"sourcesContent":["import type { Block, Field, RichTextField, Tab } from 'payload'\n\nimport { slugify } from './slugify.js'\n\n/** Whether a field is shown, from its `admin.condition`, given the values beside it. */\ntype FieldCondition = (siblingData: Record<string, unknown>) => boolean\n\ntype GuideMeta = {\n /** Present when the field is shown only for some sibling values, such as a link's doc or url. */\n condition?: FieldCondition\n description?: string\n label?: string\n name: string\n /** Guidance for the assistant only, from `custom.aiAssistant` on the field. */\n note?: string\n required: boolean\n}\n\nexport type CompiledField =\n | ({ blocks: CompiledBlock[]; kind: 'blocks'; maxRows?: number; minRows?: number } & GuideMeta)\n | { condition?: FieldCondition; fields: CompiledField[]; kind: 'flatten' }\n | ({ field: RichTextField; kind: 'richText' } & GuideMeta)\n | ({ fields: CompiledField[]; kind: 'array'; maxRows?: number; minRows?: number } & GuideMeta)\n | ({ fields: CompiledField[]; kind: 'group' } & GuideMeta)\n | ({ hasMany: boolean; kind: 'date' | 'email' | 'text' | 'textarea' } & GuideMeta)\n | ({ hasMany: boolean; kind: 'number' } & GuideMeta)\n | ({ hasMany: boolean; kind: 'relationship' | 'upload'; relationTo: string[] } & GuideMeta)\n | ({ hasMany: boolean; kind: 'select'; options: string[] } & GuideMeta)\n | ({ kind: 'checkbox' } & GuideMeta)\n\ntype CompiledBlock = {\n fields: CompiledField[]\n label?: string\n /** Guidance for the assistant only, from `custom.aiAssistant` on the block. */\n note?: string\n slug: string\n}\n\nexport type FieldError = { message: string; path: string }\n\nexport type ApplyContext = {\n /** An update may omit fields. Missing required fields stay as they are. */\n partial?: boolean\n toLexical: (field: RichTextField, markdown: string) => Promise<unknown>\n}\n\n/** Set by the site or by the editor, never by the assistant. Publishing is always the editor's decision. */\nconst derivedNames = new Set([\n '_status',\n 'collectionSlug',\n 'isNavigableCollection',\n 'path',\n 'slug',\n 'slugToggle',\n 'wordCount',\n])\n\nconst unsupportedTypes = new Set(['code', 'json', 'point'])\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction fieldAdmin(\n field: Field | Tab,\n):\n { condition?: unknown; description?: unknown; hidden?: unknown; readOnly?: unknown } | undefined {\n if (!field.admin) {\n return undefined\n }\n return field.admin as {\n condition?: unknown\n description?: unknown\n hidden?: unknown\n readOnly?: unknown\n }\n}\n\n/**\n * The field's `admin.condition`, run the way the admin runs it, against the values beside it.\n * A condition that throws counts as shown, so a field is never wrongly treated as optional.\n */\nfunction conditionOf(field: Field | Tab): FieldCondition | undefined {\n const condition = fieldAdmin(field)?.condition\n if (typeof condition !== 'function') {\n return undefined\n }\n return (siblingData) => {\n try {\n return Boolean(\n condition({}, siblingData, {\n blockData: siblingData,\n operation: 'create',\n path: [],\n user: null,\n }),\n )\n } catch {\n return true\n }\n }\n}\n\nfunction isSkipped(field: Field): boolean {\n const admin = fieldAdmin(field)\n if (admin?.hidden === true || admin?.readOnly === true) {\n return true\n }\n if ('virtual' in field && field.virtual === true) {\n return true\n }\n if ('name' in field && typeof field.name === 'string' && derivedNames.has(field.name)) {\n return true\n }\n return false\n}\n\nfunction labelOf(field: Field): string | undefined {\n if (!('label' in field) || typeof field.label !== 'string') {\n return undefined\n }\n return field.label\n}\n\nfunction descriptionOf(field: Field): string | undefined {\n const description = fieldAdmin(field)?.description\n if (typeof description !== 'string') {\n return undefined\n }\n const trimmed = description.replace(/\\s+/g, ' ').trim()\n return trimmed.length > 240 ? `${trimmed.slice(0, 237)}...` : trimmed\n}\n\n/**\n * Guidance for the assistant that editors do not need to see: a string at `custom.aiAssistant` on a field,\n * block, collection, or global. Guidance that helps editors too belongs in `admin.description`, which the\n * guide also includes.\n */\nexport function assistantNote(config: { custom?: unknown }): string | undefined {\n const custom = config.custom\n if (!custom || typeof custom !== 'object' || !('aiAssistant' in custom)) {\n return undefined\n }\n const note = custom.aiAssistant\n return typeof note === 'string' && note.trim() ? note.replace(/\\s+/g, ' ').trim() : undefined\n}\n\nfunction requiredOf(field: Field): boolean {\n return 'required' in field && field.required === true\n}\n\nfunction hasManyOf(field: Field): boolean {\n return 'hasMany' in field && field.hasMany === true\n}\n\nfunction relationToOf(field: Field): string[] {\n if (!('relationTo' in field)) {\n return []\n }\n const relationTo = field.relationTo\n if (typeof relationTo === 'string') {\n return [relationTo]\n }\n if (Array.isArray(relationTo)) {\n return relationTo.map((item) => String(item))\n }\n return []\n}\n\nfunction optionValues(field: Field): string[] {\n if (!('options' in field) || !Array.isArray(field.options)) {\n return []\n }\n return field.options.flatMap((option) => {\n if (typeof option === 'string') {\n return [option]\n }\n if (option && typeof option === 'object' && 'value' in option) {\n return typeof option.value === 'string' ? [option.value] : []\n }\n return []\n })\n}\n\nfunction childFields(field: Field): Field[] {\n if ('fields' in field && Array.isArray(field.fields)) {\n return field.fields\n }\n return []\n}\n\nfunction containsUnsupported(fields: Field[]): boolean {\n return fields.some((field) => {\n if (isSkipped(field)) {\n return false\n }\n if (unsupportedTypes.has(field.type)) {\n return true\n }\n if (field.type === 'tabs') {\n return field.tabs.some((tab) => containsUnsupported(tabFields(tab)))\n }\n const nested = childFields(field)\n return nested.length > 0 && containsUnsupported(nested)\n })\n}\n\nfunction tabFields(tab: Tab): Field[] {\n return 'fields' in tab && Array.isArray(tab.fields) ? tab.fields : []\n}\n\nfunction named(field: Field): string | undefined {\n return 'name' in field && typeof field.name === 'string' ? field.name : undefined\n}\n\nfunction meta(field: Field, name: string): GuideMeta {\n return {\n name,\n label: labelOf(field),\n description: descriptionOf(field),\n note: assistantNote(field),\n condition: conditionOf(field),\n required: requiredOf(field),\n }\n}\n\n/** Fields the model is allowed to fill. JSON, code, and point fields are left out. Every block in the schema is included. */\nexport function compileFields(fields: Field[]): CompiledField[] {\n const compiled: CompiledField[] = []\n for (const field of fields) {\n const next = compileField(field)\n if (Array.isArray(next)) {\n compiled.push(...next)\n } else if (next) {\n compiled.push(next)\n }\n }\n return compiled\n}\n\nfunction blockLabelOf(block: Block): string | undefined {\n const labels = block.labels\n if (!labels || typeof labels !== 'object' || !('singular' in labels)) {\n return undefined\n }\n return typeof labels.singular === 'string' ? labels.singular : undefined\n}\n\nfunction compileBlocks(field: Extract<Field, { type: 'blocks' }>): CompiledField | null {\n const name = named(field)\n if (!name) {\n return null\n }\n const blocks = field.blocks.flatMap((block) => {\n const nested = compileFields(block.fields)\n if (nested.length === 0) {\n return []\n }\n return [\n { slug: block.slug, label: blockLabelOf(block), note: assistantNote(block), fields: nested },\n ]\n })\n if (blocks.length === 0) {\n return null\n }\n return {\n ...meta(field, name),\n kind: 'blocks',\n blocks,\n maxRows: typeof field.maxRows === 'number' ? field.maxRows : undefined,\n minRows: typeof field.minRows === 'number' ? field.minRows : undefined,\n }\n}\n\nfunction compileField(field: Field): CompiledField | CompiledField[] | null {\n if (isSkipped(field)) {\n return null\n }\n if (field.type === 'blocks') {\n return compileBlocks(field)\n }\n if (unsupportedTypes.has(field.type)) {\n return null\n }\n\n switch (field.type) {\n case 'array': {\n if (containsUnsupported(childFields(field))) {\n return null\n }\n const name = named(field)\n const nested = compileFields(childFields(field))\n if (!name || nested.length === 0) {\n return null\n }\n return {\n ...meta(field, name),\n kind: 'array',\n fields: nested,\n maxRows: typeof field.maxRows === 'number' ? field.maxRows : undefined,\n minRows: typeof field.minRows === 'number' ? field.minRows : undefined,\n }\n }\n case 'checkbox': {\n const name = named(field)\n if (!name) {\n return null\n }\n return { ...meta(field, name), kind: 'checkbox' }\n }\n case 'collapsible':\n case 'row': {\n const nested = compileFields(childFields(field))\n if (nested.length === 0) {\n return null\n }\n return { kind: 'flatten', fields: nested, condition: conditionOf(field) }\n }\n case 'date':\n case 'email':\n case 'text':\n case 'textarea': {\n const name = named(field)\n if (!name) {\n return null\n }\n return { ...meta(field, name), kind: field.type, hasMany: hasManyOf(field) }\n }\n case 'group': {\n const nested = compileFields(childFields(field))\n if (nested.length === 0) {\n return null\n }\n const name = named(field)\n if (!name) {\n return { kind: 'flatten', fields: nested, condition: conditionOf(field) }\n }\n return { ...meta(field, name), kind: 'group', fields: nested }\n }\n case 'number': {\n const name = named(field)\n if (!name) {\n return null\n }\n return { ...meta(field, name), kind: 'number', hasMany: hasManyOf(field) }\n }\n case 'radio':\n case 'select': {\n const name = named(field)\n if (!name) {\n return null\n }\n return {\n ...meta(field, name),\n kind: 'select',\n options: optionValues(field),\n hasMany: field.type === 'select' && hasManyOf(field),\n }\n }\n case 'relationship':\n case 'upload': {\n const name = named(field)\n if (!name) {\n return null\n }\n return {\n ...meta(field, name),\n kind: field.type,\n relationTo: relationToOf(field),\n hasMany: hasManyOf(field),\n }\n }\n case 'richText': {\n const name = named(field)\n if (!name) {\n return null\n }\n return { ...meta(field, name), kind: 'richText', field }\n }\n case 'tabs': {\n const compiled: CompiledField[] = []\n for (const tab of field.tabs) {\n const nested = compileFields(tabFields(tab))\n if (nested.length === 0) {\n continue\n }\n if ('name' in tab && typeof tab.name === 'string' && tab.name) {\n compiled.push({\n kind: 'group',\n name: tab.name,\n label: typeof tab.label === 'string' ? tab.label : undefined,\n description: typeof tab.description === 'string' ? tab.description : undefined,\n required: false,\n fields: nested,\n })\n } else {\n compiled.push({ kind: 'flatten', fields: nested, condition: conditionOf(tab) })\n }\n }\n return compiled\n }\n default:\n return null\n }\n}\n\nfunction heading(field: CompiledField): string {\n if (field.kind === 'flatten') {\n return ''\n }\n const bits = [field.label ? `${field.name} (${field.label})` : field.name]\n return bits[0]\n}\n\nfunction listingHint(field: CompiledField): string {\n if (field.kind === 'flatten') {\n return ''\n }\n if (field.name === 'cardImage' || field.name === 'cardDescription') {\n return '. Fill this when creating a document'\n }\n if (field.name === 'seo' && field.kind === 'group') {\n return '. Fill title, description, and image when creating a document'\n }\n return ''\n}\n\nfunction kindLabel(field: CompiledField): string {\n switch (field.kind) {\n case 'array':\n return `array${field.maxRows ? `, max ${field.maxRows}` : ''}${field.minRows ? `, min ${field.minRows}` : ''}`\n case 'blocks':\n return `blocks${field.maxRows ? `, max ${field.maxRows}` : ''}${field.minRows ? `, min ${field.minRows}` : ''}. Each item is an object with blockType`\n case 'checkbox':\n return 'boolean'\n case 'flatten':\n return ''\n case 'group':\n return 'group'\n case 'relationship':\n case 'upload': {\n const target = field.relationTo.join(' | ') || 'unknown'\n const many = field.hasMany ? ', many' : ''\n const shape =\n field.relationTo.length > 1\n ? field.hasMany\n ? 'array of { relationTo, value }'\n : '{ relationTo, value }'\n : field.hasMany\n ? 'ids'\n : 'id'\n return `${field.kind} to ${target}${many}; ${shape}`\n }\n case 'richText':\n return 'markdown'\n case 'select':\n return `one of: ${field.options.join(', ')}${field.hasMany ? ' (many)' : ''}`\n default:\n return field.hasMany ? `${field.kind}, many` : field.kind\n }\n}\n\nexport interface FieldGuideOptions {\n /** Blocks to describe in full, by slug. Every other block is listed by name only. */\n blocks?: readonly string[]\n}\n\n/**\n * Compact field guide the model fills. Names match the collection schema.\n * Block definitions are most of a page's schema, so only the blocks asked for are expanded.\n */\nexport function formatFieldGuide(fields: Field[], options: FieldGuideOptions = {}): string {\n return formatCompiled(compileFields(fields), 0, new Set(options.blocks ?? [])).trim()\n}\n\n/** The field a dotted path points at, through groups, tabs, and rows. Lists and blocks end the walk. */\nexport function compiledFieldAtPath(fields: Field[], path: string): CompiledField | undefined {\n let level = compileFields(fields)\n let found: CompiledField | undefined\n for (const name of path.split('.')) {\n found = findCompiled(level, name)\n if (!found) {\n return undefined\n }\n level = found.kind === 'group' ? found.fields : []\n }\n return found\n}\n\nfunction findCompiled(fields: CompiledField[], name: string): CompiledField | undefined {\n for (const field of fields) {\n if (field.kind === 'flatten') {\n const nested = findCompiled(field.fields, name)\n if (nested) {\n return nested\n }\n } else if (field.name === name) {\n return field\n }\n }\n return undefined\n}\n\n/**\n * Keys in a set that match no field. Writes drop unknown keys, so these must be rejected\n * before the editor sees a plan that would quietly skip them.\n */\nexport function unknownFieldPaths(fields: Field[], set: Record<string, unknown>): string[] {\n const walk = (\n level: CompiledField[],\n values: Record<string, unknown>,\n prefix: string,\n ): string[] =>\n Object.entries(values).flatMap(([key, item]) => {\n const path = prefix ? `${prefix}.${key}` : key\n const field = findCompiled(level, key)\n if (!field) {\n return [path]\n }\n if (field.kind === 'group' && isRecord(item)) {\n return walk(field.fields, item, path)\n }\n return []\n })\n return walk(compileFields(fields), set, '')\n}\n\n/** Every block slug in the guide, so the model can be told which ones it can ask about. */\nexport function blockSlugs(fields: Field[]): string[] {\n const slugs = new Set<string>()\n const visit = (compiled: CompiledField[]) => {\n for (const field of compiled) {\n if (field.kind === 'flatten' || field.kind === 'group' || field.kind === 'array') {\n visit(field.fields)\n }\n if (field.kind === 'blocks') {\n for (const block of field.blocks) {\n slugs.add(block.slug)\n visit(block.fields)\n }\n }\n }\n }\n visit(compileFields(fields))\n return [...slugs]\n}\n\nfunction formatCompiled(\n fields: CompiledField[],\n depth: number,\n expand: ReadonlySet<string>,\n): string {\n const pad = ' '.repeat(depth)\n return fields\n .map((field) => {\n if (field.kind === 'flatten') {\n return formatCompiled(field.fields, depth, expand)\n }\n const required =\n 'required' in field && field.required\n ? field.condition\n ? ', required when shown'\n : ', required'\n : ''\n const listing = listingHint(field)\n const description =\n 'description' in field && field.description ? `. ${field.description}` : ''\n const base = `${pad}- ${heading(field)}: ${kindLabel(field)}${required}${listing}${description}`\n const note =\n 'note' in field && field.note ? `${/[.!?]$/.test(base) ? '' : '.'} Note: ${field.note}` : ''\n const line = `${base}${note}`\n if (field.kind === 'group' || field.kind === 'array') {\n const nested = formatCompiled(field.fields, depth + 1, expand)\n return nested ? `${line}\\n${nested}` : line\n }\n if (field.kind === 'blocks') {\n const nested = field.blocks\n .map((block) => {\n const name = block.label ? `${block.slug} (${block.label})` : block.slug\n // The note shows even when the block is only listed, so it can help choose between blocks.\n const title = block.note ? `${name}: ${block.note}` : name\n if (!expand.has(block.slug)) {\n return `${pad} - ${title}`\n }\n const body = formatCompiled(block.fields, depth + 2, expand)\n return body ? `${pad} - ${title}\\n${body}` : `${pad} - ${title}`\n })\n .join('\\n')\n return nested ? `${line}\\n${nested}` : line\n }\n return line\n })\n .filter(Boolean)\n .join('\\n')\n}\n\nexport function exampleValues(fields: Field[]): Record<string, unknown> {\n return exampleCompiled(compileFields(fields))\n}\n\nfunction exampleCompiled(fields: CompiledField[]): Record<string, unknown> {\n const example: Record<string, unknown> = {}\n for (const field of fields) {\n if (field.kind === 'flatten') {\n Object.assign(example, exampleCompiled(field.fields))\n continue\n }\n example[field.name] = exampleValue(field)\n }\n return example\n}\n\nfunction exampleValue(field: CompiledField): unknown {\n switch (field.kind) {\n case 'array':\n return [exampleCompiled(field.fields)]\n case 'blocks': {\n const block = field.blocks[0]\n if (!block) {\n return []\n }\n return [{ blockType: block.slug, ...exampleCompiled(block.fields) }]\n }\n case 'checkbox':\n return false\n case 'flatten':\n return undefined\n case 'group':\n return exampleCompiled(field.fields)\n case 'number':\n return field.hasMany ? [0] : 0\n case 'relationship':\n case 'upload':\n if (field.relationTo.length > 1) {\n const value = { relationTo: field.relationTo[0] ?? '', value: 'id' }\n return field.hasMany ? [value] : value\n }\n return field.hasMany ? ['id'] : 'id'\n case 'richText':\n return 'Markdown. Headings start at h2.'\n case 'select':\n return field.hasMany ? field.options.slice(0, 1) : (field.options[0] ?? '')\n default:\n return field.hasMany ? [''] : ''\n }\n}\n\nexport async function applyFields(\n fields: Field[],\n values: unknown,\n context: ApplyContext,\n): Promise<{ data: Record<string, unknown>; ok: true } | { errors: FieldError[]; ok: false }> {\n if (!isRecord(values)) {\n return { ok: false, errors: [{ path: '', message: 'Values must be an object.' }] }\n }\n\n const errors: FieldError[] = []\n const data = await applyCompiled(compileFields(fields), values, '', context, errors)\n if (errors.length > 0) {\n return { ok: false, errors }\n }\n return { ok: true, data }\n}\n\n/**\n * `hidden` is true inside a row or tab whose condition hides it. A hidden field is not required,\n * as in the admin, but a value sent for it is still kept.\n */\nasync function applyCompiled(\n fields: CompiledField[],\n source: Record<string, unknown>,\n prefix: string,\n context: ApplyContext,\n errors: FieldError[],\n hidden = false,\n): Promise<Record<string, unknown>> {\n const data: Record<string, unknown> = {}\n\n for (const field of fields) {\n const fieldHidden = hidden || (field.condition ? !field.condition(source) : false)\n if (field.kind === 'flatten') {\n Object.assign(\n data,\n await applyCompiled(field.fields, source, prefix, context, errors, fieldHidden),\n )\n continue\n }\n\n const path = prefix ? `${prefix}.${field.name}` : field.name\n const raw = source[field.name]\n if (raw === undefined || raw === null) {\n if (!context.partial && !fieldHidden && 'required' in field && field.required) {\n errors.push({ path, message: 'This field is required.' })\n }\n continue\n }\n\n const value = await readValue(field, raw, path, context, errors)\n if (value !== undefined) {\n data[field.name] = value\n }\n }\n\n return data\n}\n\nasync function readValue(\n field: Exclude<CompiledField, { kind: 'flatten' }>,\n raw: unknown,\n path: string,\n context: ApplyContext,\n errors: FieldError[],\n): Promise<unknown> {\n switch (field.kind) {\n case 'array':\n return readArray(field, raw, path, context, errors)\n case 'blocks':\n return readBlocks(field, raw, path, context, errors)\n case 'checkbox':\n if (typeof raw !== 'boolean') {\n errors.push({ path, message: 'Expected true or false.' })\n return undefined\n }\n return raw\n case 'date':\n case 'email':\n case 'text':\n case 'textarea':\n return readStrings(raw, path, field.hasMany, field.required, errors)\n case 'group': {\n if (!isRecord(raw)) {\n errors.push({ path, message: 'Expected an object.' })\n return undefined\n }\n return applyCompiled(field.fields, raw, path, context, errors)\n }\n case 'number':\n return readNumbers(raw, path, field.hasMany, field.required, errors)\n case 'relationship':\n case 'upload':\n return readRelation(raw, path, field.relationTo, field.hasMany, field.required, errors)\n case 'richText':\n return readRichText(field.field, raw, path, field.required, context, errors)\n case 'select':\n return readSelect(raw, path, field.options, field.hasMany, field.required, errors)\n default:\n return undefined\n }\n}\n\nfunction readStrings(\n raw: unknown,\n path: string,\n hasMany: boolean,\n required: boolean,\n errors: FieldError[],\n): string | string[] | undefined {\n if (hasMany) {\n if (!Array.isArray(raw) || raw.some((item) => typeof item !== 'string')) {\n errors.push({ path, message: 'Expected a list of strings.' })\n return undefined\n }\n const values = raw.map((item) => item.trim()).filter(Boolean)\n if (required && values.length === 0) {\n errors.push({ path, message: 'This field is required.' })\n }\n return values\n }\n if (typeof raw !== 'string') {\n errors.push({ path, message: 'Expected a string.' })\n return undefined\n }\n const value = raw.trim()\n if (required && !value) {\n errors.push({ path, message: 'This field is required.' })\n }\n return value\n}\n\nfunction readNumbers(\n raw: unknown,\n path: string,\n hasMany: boolean,\n required: boolean,\n errors: FieldError[],\n): number | number[] | undefined {\n const valid = (value: unknown): value is number =>\n typeof value === 'number' && Number.isFinite(value)\n if (hasMany) {\n if (!Array.isArray(raw) || !raw.every(valid)) {\n errors.push({ path, message: 'Expected a list of numbers.' })\n return undefined\n }\n if (required && raw.length === 0) {\n errors.push({ path, message: 'This field is required.' })\n }\n return raw\n }\n if (!valid(raw)) {\n errors.push({ path, message: 'Expected a number.' })\n return undefined\n }\n return raw\n}\n\nfunction readSelect(\n raw: unknown,\n path: string,\n options: string[],\n hasMany: boolean,\n required: boolean,\n errors: FieldError[],\n): string | string[] | undefined {\n const known = new Set(options)\n const accept = (value: unknown): value is string =>\n typeof value === 'string' && (known.size === 0 || known.has(value))\n if (hasMany) {\n if (!Array.isArray(raw) || !raw.every(accept)) {\n errors.push({ path, message: `Expected values from: ${options.join(', ')}.` })\n return undefined\n }\n if (required && raw.length === 0) {\n errors.push({ path, message: 'This field is required.' })\n }\n return raw\n }\n if (!accept(raw)) {\n errors.push({ path, message: `Expected one of: ${options.join(', ')}.` })\n return undefined\n }\n return raw\n}\n\nasync function readRichText(\n field: RichTextField,\n raw: unknown,\n path: string,\n required: boolean,\n context: ApplyContext,\n errors: FieldError[],\n): Promise<unknown> {\n if (typeof raw !== 'string') {\n errors.push({ path, message: 'Expected markdown.' })\n return undefined\n }\n const markdown = stripFence(raw)\n if (!markdown) {\n if (required) {\n errors.push({ path, message: 'This field is required.' })\n }\n return undefined\n }\n return context.toLexical(field, markdown)\n}\n\nfunction readRelation(\n raw: unknown,\n path: string,\n relationTo: string[],\n hasMany: boolean,\n required: boolean,\n errors: FieldError[],\n): unknown {\n const readOne = (value: unknown, itemPath: string): unknown => {\n if (relationTo.length > 1) {\n if (!isRecord(value) || typeof value.relationTo !== 'string' || !isId(value.value)) {\n errors.push({ path: itemPath, message: 'Expected { relationTo, value }.' })\n return undefined\n }\n if (!relationTo.includes(value.relationTo)) {\n errors.push({\n path: itemPath,\n message: `relationTo must be one of: ${relationTo.join(', ')}.`,\n })\n return undefined\n }\n return { relationTo: value.relationTo, value: normaliseId(value.value) }\n }\n if (!isId(value)) {\n errors.push({ path: itemPath, message: 'Expected an id.' })\n return undefined\n }\n return normaliseId(value)\n }\n\n if (hasMany) {\n if (!Array.isArray(raw)) {\n errors.push({ path, message: 'Expected a list of ids.' })\n return undefined\n }\n const values = raw\n .map((item, index) => readOne(item, `${path}.${index}`))\n .filter((item) => item !== undefined)\n if (required && values.length === 0) {\n errors.push({ path, message: 'This field is required.' })\n }\n return values\n }\n\n return readOne(raw, path)\n}\n\nasync function readArray(\n field: Extract<CompiledField, { kind: 'array' }>,\n raw: unknown,\n path: string,\n context: ApplyContext,\n errors: FieldError[],\n): Promise<Record<string, unknown>[] | undefined> {\n if (!Array.isArray(raw)) {\n errors.push({ path, message: 'Expected a list.' })\n return undefined\n }\n if (field.maxRows !== undefined && raw.length > field.maxRows) {\n errors.push({ path, message: `Use at most ${field.maxRows}.` })\n return undefined\n }\n if (field.minRows !== undefined && raw.length < field.minRows) {\n errors.push({ path, message: `Use at least ${field.minRows}.` })\n }\n\n const rows: Record<string, unknown>[] = []\n for (const [index, row] of raw.entries()) {\n if (!isRecord(row)) {\n errors.push({ path: `${path}.${index}`, message: 'Expected an object.' })\n continue\n }\n rows.push(await applyCompiled(field.fields, row, `${path}.${index}`, context, errors))\n }\n return rows\n}\n\nasync function readBlocks(\n field: Extract<CompiledField, { kind: 'blocks' }>,\n raw: unknown,\n path: string,\n context: ApplyContext,\n errors: FieldError[],\n): Promise<Record<string, unknown>[] | undefined> {\n if (!Array.isArray(raw)) {\n errors.push({ path, message: 'Expected a list of blocks.' })\n return undefined\n }\n if (field.maxRows !== undefined && raw.length > field.maxRows) {\n errors.push({ path, message: `Use at most ${field.maxRows} blocks.` })\n return undefined\n }\n if (field.minRows !== undefined && raw.length < field.minRows) {\n errors.push({ path, message: `Use at least ${field.minRows} blocks.` })\n }\n\n const known = new Map(field.blocks.map((block) => [block.slug, block]))\n const rows: Record<string, unknown>[] = []\n for (const [index, row] of raw.entries()) {\n const rowPath = `${path}.${index}`\n if (!isRecord(row) || typeof row.blockType !== 'string') {\n errors.push({ path: rowPath, message: 'Expected an object with blockType.' })\n continue\n }\n const block = known.get(row.blockType)\n if (!block) {\n errors.push({\n path: rowPath,\n message: `blockType must be one of: ${[...known.keys()].join(', ')}.`,\n })\n continue\n }\n const values = await applyCompiled(block.fields, row, rowPath, context, errors)\n rows.push({ ...values, blockType: block.slug })\n }\n return rows\n}\n\nfunction isId(value: unknown): value is number | string {\n if (typeof value === 'number') {\n return Number.isFinite(value)\n }\n return typeof value === 'string' && value.trim().length > 0\n}\n\nfunction normaliseId(value: number | string): number | string {\n return typeof value === 'string' ? value.trim() : value\n}\n\nfunction stripFence(value: string): string {\n const trimmed = value.trim()\n const fenced = trimmed.match(/^```(?:markdown|md)?([\\s\\S]*?)```$/i)\n return (fenced?.[1] ?? trimmed).trim()\n}\n\n/** Fills slug, path, and hidden defaults the editor never types, so create validation can pass. */\n/**\n * The slug a renamed document gets when its \"Use title\" toggle is on, matching the slug field in the editor,\n * which rebuilds the slug from the title as it changes. Undefined when the slug stays as it is.\n * The path field's own hook then rebuilds the URL from the slug and adds a redirect if the page was published.\n */\nexport function followedSlug(\n fields: Field[],\n current: unknown,\n nextTitle: unknown,\n): string | undefined {\n if (!findNamed(fields, 'slug') || !findNamed(fields, 'slugToggle')) {\n return undefined\n }\n if (!isRecord(current) || current.slugToggle !== 'title') {\n return undefined\n }\n if (typeof nextTitle !== 'string' || nextTitle === current.title) {\n return undefined\n }\n const slug = slugify(nextTitle)\n return slug && slug !== current.slug ? slug : undefined\n}\n\nexport function withDerivedValues(\n fields: Field[],\n data: Record<string, unknown>,\n options?: { prependPath?: string },\n): Record<string, unknown> {\n const next = { ...data }\n const slugField = findNamed(fields, 'slug')\n if (slugField && (typeof next.slug !== 'string' || next.slug.trim() === '')) {\n const title = typeof next.title === 'string' ? next.title : ''\n const slug = slugify(title)\n if (slug) {\n next.slug = slug\n // Keep the generated slug. The \"use title\" toggle would rewrite it in the editor.\n if (findNamed(fields, 'slugToggle')) {\n next.slugToggle = 'manual'\n }\n }\n }\n\n const pathField = findNamed(fields, 'path')\n if (\n pathField &&\n (typeof next.path !== 'string' || next.path.trim() === '') &&\n typeof next.slug === 'string'\n ) {\n const path = documentPath(options?.prependPath, next.slug)\n if (path) {\n next.path = path\n }\n }\n\n const collectionSlug = findNamed(fields, 'collectionSlug')\n if (\n collectionSlug &&\n next.collectionSlug === undefined &&\n 'defaultValue' in collectionSlug &&\n typeof collectionSlug.defaultValue === 'string'\n ) {\n next.collectionSlug = collectionSlug.defaultValue\n }\n\n return next\n}\n\nfunction documentPath(prepend: string | undefined, slug: string): string {\n const trimmed = slug.trim()\n if (!trimmed) {\n return ''\n }\n const prefix = prepend?.trim() ?? ''\n const joined = `${prefix}/${trimmed}`.replace(/\\/+/g, '/')\n return joined.length > 1 ? joined.replace(/\\/+$/, '') : '/'\n}\n\nfunction findNamed(fields: Field[], name: string): Field | undefined {\n for (const field of fields) {\n if ('name' in field && field.name === name) {\n return field\n }\n if (field.type === 'tabs') {\n for (const tab of field.tabs) {\n const found = findNamed(tabFields(tab), name)\n if (found) {\n return found\n }\n }\n }\n const nested = childFields(field)\n if (nested.length > 0) {\n const found = findNamed(nested, name)\n if (found) {\n return found\n }\n }\n }\n return undefined\n}\n"],"names":["slugify","derivedNames","Set","unsupportedTypes","isRecord","value","Boolean","Array","isArray","fieldAdmin","field","admin","undefined","conditionOf","condition","siblingData","blockData","operation","path","user","isSkipped","hidden","readOnly","virtual","name","has","labelOf","label","descriptionOf","description","trimmed","replace","trim","length","slice","assistantNote","config","custom","note","aiAssistant","requiredOf","required","hasManyOf","hasMany","relationToOf","relationTo","map","item","String","optionValues","options","flatMap","option","childFields","fields","containsUnsupported","some","type","tabs","tab","tabFields","nested","named","meta","compileFields","compiled","next","compileField","push","blockLabelOf","block","labels","singular","compileBlocks","blocks","slug","kind","maxRows","minRows","heading","bits","listingHint","kindLabel","target","join","many","shape","formatFieldGuide","formatCompiled","compiledFieldAtPath","level","found","split","findCompiled","unknownFieldPaths","set","walk","values","prefix","Object","entries","key","blockSlugs","slugs","visit","add","depth","expand","pad","repeat","listing","base","test","line","title","body","filter","exampleValues","exampleCompiled","example","assign","exampleValue","blockType","applyFields","context","ok","errors","message","data","applyCompiled","source","fieldHidden","raw","partial","readValue","readArray","readBlocks","readStrings","readNumbers","readRelation","readRichText","readSelect","valid","Number","isFinite","every","known","accept","size","markdown","stripFence","toLexical","readOne","itemPath","isId","includes","normaliseId","index","rows","row","Map","rowPath","get","keys","fenced","match","followedSlug","current","nextTitle","findNamed","slugToggle","withDerivedValues","slugField","pathField","documentPath","prependPath","collectionSlug","defaultValue","prepend","joined"],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Field } from 'payload';
|
|
2
|
+
/**
|
|
3
|
+
* Paths the assistant must fill when creating a document that has listing or SEO fields.
|
|
4
|
+
* Schema-optional, but required for cards, menus, and search previews.
|
|
5
|
+
*/
|
|
6
|
+
export declare function listingCreatePaths(fields: Field[]): string[];
|
|
7
|
+
/** Listing or SEO paths that are missing or empty in a create set. */
|
|
8
|
+
export declare function missingListingCreatePaths(fields: Field[], set: unknown): string[];
|
|
9
|
+
export declare function topLevelSetPaths(set: unknown): string[];
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { compileFields } from './fields.js';
|
|
2
|
+
const listingNames = new Set([
|
|
3
|
+
'cardDescription',
|
|
4
|
+
'cardImage'
|
|
5
|
+
]);
|
|
6
|
+
const seoChildNames = [
|
|
7
|
+
'title',
|
|
8
|
+
'description',
|
|
9
|
+
'image'
|
|
10
|
+
];
|
|
11
|
+
function isRecord(value) {
|
|
12
|
+
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Paths the assistant must fill when creating a document that has listing or SEO fields.
|
|
16
|
+
* Schema-optional, but required for cards, menus, and search previews.
|
|
17
|
+
*/ export function listingCreatePaths(fields) {
|
|
18
|
+
return listingPathsFromCompiled(compileFields(fields));
|
|
19
|
+
}
|
|
20
|
+
function listingPathsFromCompiled(fields, prefix = '') {
|
|
21
|
+
const paths = [];
|
|
22
|
+
for (const field of fields){
|
|
23
|
+
if (field.kind === 'flatten') {
|
|
24
|
+
paths.push(...listingPathsFromCompiled(field.fields, prefix));
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
const path = prefix ? `${prefix}.${field.name}` : field.name;
|
|
28
|
+
if (listingNames.has(field.name)) {
|
|
29
|
+
paths.push(path);
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
if (field.name === 'seo' && field.kind === 'group') {
|
|
33
|
+
for (const child of field.fields){
|
|
34
|
+
if (child.kind === 'flatten') {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
if (seoChildNames.includes(child.name)) {
|
|
38
|
+
paths.push(`${path}.${child.name}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (field.kind === 'group') {
|
|
44
|
+
paths.push(...listingPathsFromCompiled(field.fields, path));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return paths;
|
|
48
|
+
}
|
|
49
|
+
/** Listing or SEO paths that are missing or empty in a create set. */ export function missingListingCreatePaths(fields, set) {
|
|
50
|
+
const expected = listingCreatePaths(fields);
|
|
51
|
+
if (expected.length === 0 || !isRecord(set)) {
|
|
52
|
+
return expected;
|
|
53
|
+
}
|
|
54
|
+
return expected.filter((path)=>!hasValueAtPath(set, path));
|
|
55
|
+
}
|
|
56
|
+
export function topLevelSetPaths(set) {
|
|
57
|
+
if (!isRecord(set)) {
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
return Object.keys(set).filter((key)=>set[key] !== undefined && set[key] !== null);
|
|
61
|
+
}
|
|
62
|
+
function hasValueAtPath(source, path) {
|
|
63
|
+
const parts = path.split('.');
|
|
64
|
+
let current = source;
|
|
65
|
+
for (const part of parts){
|
|
66
|
+
if (!isRecord(current) || !(part in current)) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
current = current[part];
|
|
70
|
+
}
|
|
71
|
+
if (current === undefined || current === null) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
if (typeof current === 'string') {
|
|
75
|
+
return current.trim().length > 0;
|
|
76
|
+
}
|
|
77
|
+
if (typeof current === 'number' || typeof current === 'boolean') {
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
if (Array.isArray(current)) {
|
|
81
|
+
return current.length > 0;
|
|
82
|
+
}
|
|
83
|
+
if (isRecord(current)) {
|
|
84
|
+
if ('$file' in current || '$op' in current) {
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
if ('relationTo' in current && 'value' in current) {
|
|
88
|
+
return current.value !== undefined && current.value !== null;
|
|
89
|
+
}
|
|
90
|
+
return Object.keys(current).length > 0;
|
|
91
|
+
}
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
//# sourceMappingURL=listingFields.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/schema/listingFields.ts"],"sourcesContent":["import type { Field } from 'payload'\n\nimport type { CompiledField } from './fields.js'\n\nimport { compileFields } from './fields.js'\n\nconst listingNames = new Set(['cardDescription', 'cardImage'])\nconst seoChildNames = ['title', 'description', 'image'] as const\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === 'object' && !Array.isArray(value)\n}\n\n/**\n * Paths the assistant must fill when creating a document that has listing or SEO fields.\n * Schema-optional, but required for cards, menus, and search previews.\n */\nexport function listingCreatePaths(fields: Field[]): string[] {\n return listingPathsFromCompiled(compileFields(fields))\n}\n\nfunction listingPathsFromCompiled(fields: CompiledField[], prefix = ''): string[] {\n const paths: string[] = []\n for (const field of fields) {\n if (field.kind === 'flatten') {\n paths.push(...listingPathsFromCompiled(field.fields, prefix))\n continue\n }\n const path = prefix ? `${prefix}.${field.name}` : field.name\n if (listingNames.has(field.name)) {\n paths.push(path)\n continue\n }\n if (field.name === 'seo' && field.kind === 'group') {\n for (const child of field.fields) {\n if (child.kind === 'flatten') {\n continue\n }\n if ((seoChildNames as readonly string[]).includes(child.name)) {\n paths.push(`${path}.${child.name}`)\n }\n }\n continue\n }\n if (field.kind === 'group') {\n paths.push(...listingPathsFromCompiled(field.fields, path))\n }\n }\n return paths\n}\n\n/** Listing or SEO paths that are missing or empty in a create set. */\nexport function missingListingCreatePaths(fields: Field[], set: unknown): string[] {\n const expected = listingCreatePaths(fields)\n if (expected.length === 0 || !isRecord(set)) {\n return expected\n }\n return expected.filter((path) => !hasValueAtPath(set, path))\n}\n\nexport function topLevelSetPaths(set: unknown): string[] {\n if (!isRecord(set)) {\n return []\n }\n return Object.keys(set).filter((key) => set[key] !== undefined && set[key] !== null)\n}\n\nfunction hasValueAtPath(source: Record<string, unknown>, path: string): boolean {\n const parts = path.split('.')\n let current: unknown = source\n for (const part of parts) {\n if (!isRecord(current) || !(part in current)) {\n return false\n }\n current = current[part]\n }\n if (current === undefined || current === null) {\n return false\n }\n if (typeof current === 'string') {\n return current.trim().length > 0\n }\n if (typeof current === 'number' || typeof current === 'boolean') {\n return true\n }\n if (Array.isArray(current)) {\n return current.length > 0\n }\n if (isRecord(current)) {\n if ('$file' in current || '$op' in current) {\n return true\n }\n if ('relationTo' in current && 'value' in current) {\n return current.value !== undefined && current.value !== null\n }\n return Object.keys(current).length > 0\n }\n return false\n}\n"],"names":["compileFields","listingNames","Set","seoChildNames","isRecord","value","Boolean","Array","isArray","listingCreatePaths","fields","listingPathsFromCompiled","prefix","paths","field","kind","push","path","name","has","child","includes","missingListingCreatePaths","set","expected","length","filter","hasValueAtPath","topLevelSetPaths","Object","keys","key","undefined","source","parts","split","current","part","trim"],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** URL slug from a title. Matches the site's slug rules closely enough for a draft. */ export function slugify(value) {
|
|
2
|
+
return value.trim().normalize('NFC').toLowerCase().replace(/[\s._&/]+/g, '-').replace(/[^\p{L}\p{N}-]+/gu, '').replace(/-+/g, '-').replace(/^-+|-+$/g, '');
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
//# sourceMappingURL=slugify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/schema/slugify.ts"],"sourcesContent":["/** URL slug from a title. Matches the site's slug rules closely enough for a draft. */\nexport function slugify(value: string): string {\n return value\n .trim()\n .normalize('NFC')\n .toLowerCase()\n .replace(/[\\s._&/]+/g, '-')\n .replace(/[^\\p{L}\\p{N}-]+/gu, '')\n .replace(/-+/g, '-')\n .replace(/^-+|-+$/g, '')\n}\n"],"names":["slugify","value","trim","normalize","toLowerCase","replace"],"mappings":"AAAA,qFAAqF,GACrF,OAAO,SAASA,QAAQC,KAAa;IACnC,OAAOA,MACJC,IAAI,GACJC,SAAS,CAAC,OACVC,WAAW,GACXC,OAAO,CAAC,cAAc,KACtBA,OAAO,CAAC,qBAAqB,IAC7BA,OAAO,CAAC,OAAO,KACfA,OAAO,CAAC,YAAY;AACzB"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AssistantSettings } from './types.js';
|
|
2
|
+
export declare function roleOf(user: unknown): string | undefined;
|
|
3
|
+
export declare function isAdminRole(user: unknown): boolean;
|
|
4
|
+
export declare function userIdOf(user: unknown): string | undefined;
|
|
5
|
+
/**
|
|
6
|
+
* Missing fields fall back to the plugin defaults. An array that was saved empty is respected,
|
|
7
|
+
* so an admin can turn every role off.
|
|
8
|
+
*/
|
|
9
|
+
export declare function parseSettings(value: unknown, fallback: AssistantSettings): AssistantSettings;
|
|
10
|
+
export declare function canUseAssistant(user: unknown, settings: AssistantSettings): boolean;
|
package/dist/settings.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export function roleOf(user) {
|
|
2
|
+
if (!user || typeof user !== 'object' || !('role' in user)) {
|
|
3
|
+
return undefined;
|
|
4
|
+
}
|
|
5
|
+
return typeof user.role === 'string' ? user.role : undefined;
|
|
6
|
+
}
|
|
7
|
+
export function isAdminRole(user) {
|
|
8
|
+
return roleOf(user) === 'admin';
|
|
9
|
+
}
|
|
10
|
+
export function userIdOf(user) {
|
|
11
|
+
if (!user || typeof user !== 'object' || !('id' in user)) {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
const id = user.id;
|
|
15
|
+
if (typeof id === 'string' && id) {
|
|
16
|
+
return id;
|
|
17
|
+
}
|
|
18
|
+
if (typeof id === 'number') {
|
|
19
|
+
return String(id);
|
|
20
|
+
}
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
function isRecord(value) {
|
|
24
|
+
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
25
|
+
}
|
|
26
|
+
function stringList(value, fallback) {
|
|
27
|
+
if (!Array.isArray(value)) {
|
|
28
|
+
return fallback;
|
|
29
|
+
}
|
|
30
|
+
return value.filter((item)=>typeof item === 'string');
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Missing fields fall back to the plugin defaults. An array that was saved empty is respected,
|
|
34
|
+
* so an admin can turn every role off.
|
|
35
|
+
*/ export function parseSettings(value, fallback) {
|
|
36
|
+
const doc = isRecord(value) ? value : {};
|
|
37
|
+
return {
|
|
38
|
+
billing: doc.billing === 'own-key' ? 'own-key' : fallback.billing,
|
|
39
|
+
allowedRoles: stringList(doc.allowedRoles, fallback.allowedRoles),
|
|
40
|
+
dailySpendCapPercent: percent(doc.dailySpendCapPercent, fallback.dailySpendCapPercent)
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function percent(value, fallback) {
|
|
44
|
+
return typeof value === 'number' && Number.isFinite(value) && value >= 0 && value <= 100 ? value : fallback;
|
|
45
|
+
}
|
|
46
|
+
export function canUseAssistant(user, settings) {
|
|
47
|
+
const role = roleOf(user);
|
|
48
|
+
if (!role || !settings.allowedRoles.includes(role)) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
//# sourceMappingURL=settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/settings.ts"],"sourcesContent":["import type { AssistantSettings } from './types.js'\n\nexport function roleOf(user: unknown): string | undefined {\n if (!user || typeof user !== 'object' || !('role' in user)) {\n return undefined\n }\n return typeof user.role === 'string' ? user.role : undefined\n}\n\nexport function isAdminRole(user: unknown): boolean {\n return roleOf(user) === 'admin'\n}\n\nexport function userIdOf(user: unknown): string | undefined {\n if (!user || typeof user !== 'object' || !('id' in user)) {\n return undefined\n }\n const id = user.id\n if (typeof id === 'string' && id) {\n return id\n }\n if (typeof id === 'number') {\n return String(id)\n }\n return undefined\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction stringList(value: unknown, fallback: string[]): string[] {\n if (!Array.isArray(value)) {\n return fallback\n }\n return value.filter((item): item is string => typeof item === 'string')\n}\n\n/**\n * Missing fields fall back to the plugin defaults. An array that was saved empty is respected,\n * so an admin can turn every role off.\n */\nexport function parseSettings(value: unknown, fallback: AssistantSettings): AssistantSettings {\n const doc = isRecord(value) ? value : {}\n\n return {\n billing: doc.billing === 'own-key' ? 'own-key' : fallback.billing,\n allowedRoles: stringList(doc.allowedRoles, fallback.allowedRoles),\n dailySpendCapPercent: percent(doc.dailySpendCapPercent, fallback.dailySpendCapPercent),\n }\n}\n\nfunction percent(value: unknown, fallback: number): number {\n return typeof value === 'number' && Number.isFinite(value) && value >= 0 && value <= 100\n ? value\n : fallback\n}\n\nexport function canUseAssistant(user: unknown, settings: AssistantSettings): boolean {\n const role = roleOf(user)\n if (!role || !settings.allowedRoles.includes(role)) {\n return false\n }\n return true\n}\n"],"names":["roleOf","user","undefined","role","isAdminRole","userIdOf","id","String","isRecord","value","Boolean","Array","isArray","stringList","fallback","filter","item","parseSettings","doc","billing","allowedRoles","dailySpendCapPercent","percent","Number","isFinite","canUseAssistant","settings","includes"],"mappings":"AAEA,OAAO,SAASA,OAAOC,IAAa;IAClC,IAAI,CAACA,QAAQ,OAAOA,SAAS,YAAY,CAAE,CAAA,UAAUA,IAAG,GAAI;QAC1D,OAAOC;IACT;IACA,OAAO,OAAOD,KAAKE,IAAI,KAAK,WAAWF,KAAKE,IAAI,GAAGD;AACrD;AAEA,OAAO,SAASE,YAAYH,IAAa;IACvC,OAAOD,OAAOC,UAAU;AAC1B;AAEA,OAAO,SAASI,SAASJ,IAAa;IACpC,IAAI,CAACA,QAAQ,OAAOA,SAAS,YAAY,CAAE,CAAA,QAAQA,IAAG,GAAI;QACxD,OAAOC;IACT;IACA,MAAMI,KAAKL,KAAKK,EAAE;IAClB,IAAI,OAAOA,OAAO,YAAYA,IAAI;QAChC,OAAOA;IACT;IACA,IAAI,OAAOA,OAAO,UAAU;QAC1B,OAAOC,OAAOD;IAChB;IACA,OAAOJ;AACT;AAEA,SAASM,SAASC,KAAc;IAC9B,OAAOC,QAAQD,UAAU,OAAOA,UAAU,YAAY,CAACE,MAAMC,OAAO,CAACH;AACvE;AAEA,SAASI,WAAWJ,KAAc,EAAEK,QAAkB;IACpD,IAAI,CAACH,MAAMC,OAAO,CAACH,QAAQ;QACzB,OAAOK;IACT;IACA,OAAOL,MAAMM,MAAM,CAAC,CAACC,OAAyB,OAAOA,SAAS;AAChE;AAEA;;;CAGC,GACD,OAAO,SAASC,cAAcR,KAAc,EAAEK,QAA2B;IACvE,MAAMI,MAAMV,SAASC,SAASA,QAAQ,CAAC;IAEvC,OAAO;QACLU,SAASD,IAAIC,OAAO,KAAK,YAAY,YAAYL,SAASK,OAAO;QACjEC,cAAcP,WAAWK,IAAIE,YAAY,EAAEN,SAASM,YAAY;QAChEC,sBAAsBC,QAAQJ,IAAIG,oBAAoB,EAAEP,SAASO,oBAAoB;IACvF;AACF;AAEA,SAASC,QAAQb,KAAc,EAAEK,QAAgB;IAC/C,OAAO,OAAOL,UAAU,YAAYc,OAAOC,QAAQ,CAACf,UAAUA,SAAS,KAAKA,SAAS,MACjFA,QACAK;AACN;AAEA,OAAO,SAASW,gBAAgBxB,IAAa,EAAEyB,QAA2B;IACxE,MAAMvB,OAAOH,OAAOC;IACpB,IAAI,CAACE,QAAQ,CAACuB,SAASN,YAAY,CAACO,QAAQ,CAACxB,OAAO;QAClD,OAAO;IACT;IACA,OAAO;AACT"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import type { CollectionSlug, GlobalSlug } from 'payload';
|
|
2
|
+
import type { Billing, ByokOption } from './billing.js';
|
|
3
|
+
export interface AiAssistantRole {
|
|
4
|
+
label: string;
|
|
5
|
+
value: string;
|
|
6
|
+
}
|
|
7
|
+
export interface AiAssistantPluginOptions {
|
|
8
|
+
/** Admin nav group for the settings global. */
|
|
9
|
+
adminGroup?: string;
|
|
10
|
+
/**
|
|
11
|
+
* Query parameters sent when the assistant reads an attachment through its storage adapter, for adapters that
|
|
12
|
+
* transform files on delivery. With ImageKit, `{ tr: "orig-true" }` returns the original file rather than an
|
|
13
|
+
* optimised copy, so Proceed saves what the editor uploaded. Most adapters need none.
|
|
14
|
+
*/
|
|
15
|
+
attachmentReadParams?: Record<string, string>;
|
|
16
|
+
/**
|
|
17
|
+
* The site's own provider credentials, so the provider bills the client's account instead of the Vercel project.
|
|
18
|
+
* In the gateway's request-scoped BYOK shape: provider slugs mapped to a credential object, or a list to try in
|
|
19
|
+
* order, such as `{ anthropic: { apiKey: process.env.ANTHROPIC_API_KEY } }`. Read values from environment
|
|
20
|
+
* variables. A credential with any value unset is left out, so admins can only choose the own key once the
|
|
21
|
+
* variables are populated. Credentials stay on the server.
|
|
22
|
+
*/
|
|
23
|
+
byok?: ByokOption;
|
|
24
|
+
/**
|
|
25
|
+
* Optional instructions for a collection or global, included when that target is described.
|
|
26
|
+
* Prefer `admin.description` or `custom.aiAssistant` on the fields themselves; this is for intent with no field to live on.
|
|
27
|
+
*/
|
|
28
|
+
collectionRules?: Partial<Record<CollectionSlug, string>>;
|
|
29
|
+
/**
|
|
30
|
+
* Collections the assistant cannot change. It can still read them, with the editor's own access.
|
|
31
|
+
* Auth collections such as users, Payload's own `payload-*` collections, and the plugin's collections are never changed.
|
|
32
|
+
*/
|
|
33
|
+
deniedCollections?: CollectionSlug[];
|
|
34
|
+
/** Globals the assistant cannot change. It can still read them. Its own settings global is never changed. */
|
|
35
|
+
deniedGlobals?: GlobalSlug[];
|
|
36
|
+
/**
|
|
37
|
+
* Turns the assistant on or off without uninstalling it. When off, its collections and settings global
|
|
38
|
+
* stay so the database schema does not change, but the panel and endpoints are not added.
|
|
39
|
+
* @default true
|
|
40
|
+
*/
|
|
41
|
+
enabled?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* AI Gateway model id, such as `anthropic/claude-sonnet-5.5`. It needs vision and tool use.
|
|
44
|
+
* @default defaultModelId
|
|
45
|
+
*/
|
|
46
|
+
model?: string;
|
|
47
|
+
/** Roles an admin can allow to run the assistant. */
|
|
48
|
+
roles: AiAssistantRole[];
|
|
49
|
+
/** Fixed editorial rules. The prompt may change the task, not these rules. */
|
|
50
|
+
siteRules: string;
|
|
51
|
+
/** IANA time zone for the daily spend cap, so it resets at local midnight. Defaults to UTC. */
|
|
52
|
+
timeZone?: string;
|
|
53
|
+
}
|
|
54
|
+
/** What admins set in the settings global. */
|
|
55
|
+
export interface AssistantSettings {
|
|
56
|
+
allowedRoles: string[];
|
|
57
|
+
/** What was chosen. The billing that applies also needs the key to be set; see `activeBilling`. */
|
|
58
|
+
billing: Billing;
|
|
59
|
+
/** Percentage of the project's budget each editor can spend per day. 0 means no cap. Vercel billing only. */
|
|
60
|
+
dailySpendCapPercent: number;
|
|
61
|
+
}
|
|
62
|
+
export type PlanTargetKind = 'collection' | 'global';
|
|
63
|
+
/** A document the plan will create or change. Field values stay on the server. */
|
|
64
|
+
export interface PlanOperationView {
|
|
65
|
+
action: 'create' | 'update';
|
|
66
|
+
/** Each value it will write, beside the current one. Shown to the editor, not sent back to the model. */
|
|
67
|
+
fieldChanges?: FieldChangeView[];
|
|
68
|
+
/** Top-level fields this operation will write. */
|
|
69
|
+
fields: string[];
|
|
70
|
+
href?: string;
|
|
71
|
+
id?: string;
|
|
72
|
+
kind: PlanTargetKind;
|
|
73
|
+
label: string;
|
|
74
|
+
savesImmediately: boolean;
|
|
75
|
+
slug: string;
|
|
76
|
+
summary: string;
|
|
77
|
+
}
|
|
78
|
+
export interface FieldChangeView {
|
|
79
|
+
/** Blocks added to the end of a blocks field. */
|
|
80
|
+
added?: boolean;
|
|
81
|
+
after: string;
|
|
82
|
+
/** The current value. Missing when the field is empty or the document is new. */
|
|
83
|
+
before?: string;
|
|
84
|
+
/** For an upload field, the files on each side, so the card can show them instead of ids. */
|
|
85
|
+
media?: {
|
|
86
|
+
after?: MediaView;
|
|
87
|
+
before?: MediaView;
|
|
88
|
+
};
|
|
89
|
+
/** Dotted path, such as `seo.title`. */
|
|
90
|
+
path: string;
|
|
91
|
+
}
|
|
92
|
+
export interface MediaView {
|
|
93
|
+
label: string;
|
|
94
|
+
/** Attached in this conversation and not saved yet. */
|
|
95
|
+
pending?: boolean;
|
|
96
|
+
/** A small image, when the file is an image the editor can read. */
|
|
97
|
+
thumbnail?: string;
|
|
98
|
+
}
|
|
99
|
+
export interface PlanCandidateView {
|
|
100
|
+
href?: string;
|
|
101
|
+
id?: string;
|
|
102
|
+
kind: PlanTargetKind;
|
|
103
|
+
label: string;
|
|
104
|
+
slug: string;
|
|
105
|
+
}
|
|
106
|
+
export interface PlanFileView {
|
|
107
|
+
collection: string;
|
|
108
|
+
/** Position in the conversation's attachments. */
|
|
109
|
+
index: number;
|
|
110
|
+
name: string;
|
|
111
|
+
note: string;
|
|
112
|
+
savesImmediately: boolean;
|
|
113
|
+
}
|
|
114
|
+
/** What the drawer shows before anything is written. */
|
|
115
|
+
export interface AssistantPlanView {
|
|
116
|
+
blocked: boolean;
|
|
117
|
+
candidates: PlanCandidateView[];
|
|
118
|
+
files: PlanFileView[];
|
|
119
|
+
id: string;
|
|
120
|
+
operations: PlanOperationView[];
|
|
121
|
+
questions: string[];
|
|
122
|
+
summary: string;
|
|
123
|
+
}
|
|
124
|
+
export interface AssistantChange {
|
|
125
|
+
action: 'created' | 'updated' | 'uploaded';
|
|
126
|
+
/** Collection or global slug. With the id, lets a later plan point at a document this one saved. */
|
|
127
|
+
collection: string;
|
|
128
|
+
detail?: string;
|
|
129
|
+
href: string;
|
|
130
|
+
id: string;
|
|
131
|
+
label: string;
|
|
132
|
+
}
|
|
133
|
+
/** The document open in the admin when the editor sends a message. */
|
|
134
|
+
export interface PageContext {
|
|
135
|
+
id?: string;
|
|
136
|
+
kind: PlanTargetKind;
|
|
137
|
+
label: string;
|
|
138
|
+
slug: string;
|
|
139
|
+
}
|
|
140
|
+
/** A file attached to a conversation. The index is its position across the whole conversation. */
|
|
141
|
+
export interface AttachmentView {
|
|
142
|
+
index: number;
|
|
143
|
+
name: string;
|
|
144
|
+
type: string;
|
|
145
|
+
}
|
|
146
|
+
export interface AssistantMessageMetadata {
|
|
147
|
+
/** Files first attached with this user message. Set by the server. */
|
|
148
|
+
attachments?: AttachmentView[];
|
|
149
|
+
/** The document open when this user message was sent. */
|
|
150
|
+
context?: PageContext;
|
|
151
|
+
/** Token use for an assistant reply. */
|
|
152
|
+
usage?: {
|
|
153
|
+
cachedInputTokens?: number;
|
|
154
|
+
inputTokens?: number;
|
|
155
|
+
outputTokens?: number;
|
|
156
|
+
totalTokens?: number;
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
export type PlanStatus = 'applied' | 'blocked' | 'cancelled' | 'proposed';
|
|
160
|
+
/** What submitPlan returns. The drawer renders it as a plan card. The status changes when the editor acts on it. */
|
|
161
|
+
export type SubmitPlanOutput = {
|
|
162
|
+
changes?: AssistantChange[];
|
|
163
|
+
ok: true;
|
|
164
|
+
plan: AssistantPlanView;
|
|
165
|
+
status: PlanStatus;
|
|
166
|
+
} | {
|
|
167
|
+
error: string;
|
|
168
|
+
ok: false;
|
|
169
|
+
};
|
|
170
|
+
/** The project's AI Gateway budget, as shares only. Dollar amounts stay on the server. */
|
|
171
|
+
export interface BudgetView {
|
|
172
|
+
/** At or past `lowBudgetUsedShare` of the budget used. */
|
|
173
|
+
low: boolean;
|
|
174
|
+
/** What is left as a share of the budget for this period, from 0 to 1. */
|
|
175
|
+
remainingShare: number;
|
|
176
|
+
}
|
|
177
|
+
/** Replies billed to the site's own provider key. US dollars are the site's own spend, so admins see them. */
|
|
178
|
+
export interface OwnKeyView {
|
|
179
|
+
/** Admins only: model calls today that fell back to Vercel's credit because the key failed. */
|
|
180
|
+
fallbackSteps?: number;
|
|
181
|
+
/** The provider's name, such as `Anthropic`. */
|
|
182
|
+
provider: string;
|
|
183
|
+
/** Admins only: everyone's spend on the key today, in US dollars, as the gateway prices it. */
|
|
184
|
+
todayUsd?: number;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* What the panel header shows. On Vercel billing: the editor's share of today's cap and, for admins, the project's
|
|
188
|
+
* budget, as shares only. On the own key: which provider pays and, for admins, today's spend on it.
|
|
189
|
+
*/
|
|
190
|
+
export interface UsageView {
|
|
191
|
+
budget?: BudgetView;
|
|
192
|
+
ownKey?: OwnKeyView;
|
|
193
|
+
/** Missing when there is no daily cap. */
|
|
194
|
+
today?: {
|
|
195
|
+
/** Share of today's allowance used, from 0. */
|
|
196
|
+
usedShare: number;
|
|
197
|
+
};
|
|
198
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the panel header shows. On Vercel billing: the editor's share of today's cap and, for admins, the project's
|
|
3
|
+
* budget, as shares only. On the own key: which provider pays and, for admins, today's spend on it.
|
|
4
|
+
*/ export { };
|
|
5
|
+
|
|
6
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type { CollectionSlug, GlobalSlug } from 'payload'\n\nimport type { Billing, ByokOption } from './billing.js'\n\nexport interface AiAssistantRole {\n label: string\n value: string\n}\n\nexport interface AiAssistantPluginOptions {\n /** Admin nav group for the settings global. */\n adminGroup?: string\n /**\n * Query parameters sent when the assistant reads an attachment through its storage adapter, for adapters that\n * transform files on delivery. With ImageKit, `{ tr: \"orig-true\" }` returns the original file rather than an\n * optimised copy, so Proceed saves what the editor uploaded. Most adapters need none.\n */\n attachmentReadParams?: Record<string, string>\n /**\n * The site's own provider credentials, so the provider bills the client's account instead of the Vercel project.\n * In the gateway's request-scoped BYOK shape: provider slugs mapped to a credential object, or a list to try in\n * order, such as `{ anthropic: { apiKey: process.env.ANTHROPIC_API_KEY } }`. Read values from environment\n * variables. A credential with any value unset is left out, so admins can only choose the own key once the\n * variables are populated. Credentials stay on the server.\n */\n byok?: ByokOption\n /**\n * Optional instructions for a collection or global, included when that target is described.\n * Prefer `admin.description` or `custom.aiAssistant` on the fields themselves; this is for intent with no field to live on.\n */\n collectionRules?: Partial<Record<CollectionSlug, string>>\n /**\n * Collections the assistant cannot change. It can still read them, with the editor's own access.\n * Auth collections such as users, Payload's own `payload-*` collections, and the plugin's collections are never changed.\n */\n deniedCollections?: CollectionSlug[]\n /** Globals the assistant cannot change. It can still read them. Its own settings global is never changed. */\n deniedGlobals?: GlobalSlug[]\n /**\n * Turns the assistant on or off without uninstalling it. When off, its collections and settings global\n * stay so the database schema does not change, but the panel and endpoints are not added.\n * @default true\n */\n enabled?: boolean\n /**\n * AI Gateway model id, such as `anthropic/claude-sonnet-5.5`. It needs vision and tool use.\n * @default defaultModelId\n */\n model?: string\n /** Roles an admin can allow to run the assistant. */\n roles: AiAssistantRole[]\n /** Fixed editorial rules. The prompt may change the task, not these rules. */\n siteRules: string\n /** IANA time zone for the daily spend cap, so it resets at local midnight. Defaults to UTC. */\n timeZone?: string\n}\n\n/** What admins set in the settings global. */\nexport interface AssistantSettings {\n allowedRoles: string[]\n /** What was chosen. The billing that applies also needs the key to be set; see `activeBilling`. */\n billing: Billing\n /** Percentage of the project's budget each editor can spend per day. 0 means no cap. Vercel billing only. */\n dailySpendCapPercent: number\n}\n\nexport type PlanTargetKind = 'collection' | 'global'\n\n/** A document the plan will create or change. Field values stay on the server. */\nexport interface PlanOperationView {\n action: 'create' | 'update'\n /** Each value it will write, beside the current one. Shown to the editor, not sent back to the model. */\n fieldChanges?: FieldChangeView[]\n /** Top-level fields this operation will write. */\n fields: string[]\n href?: string\n id?: string\n kind: PlanTargetKind\n label: string\n savesImmediately: boolean\n slug: string\n summary: string\n}\n\nexport interface FieldChangeView {\n /** Blocks added to the end of a blocks field. */\n added?: boolean\n after: string\n /** The current value. Missing when the field is empty or the document is new. */\n before?: string\n /** For an upload field, the files on each side, so the card can show them instead of ids. */\n media?: { after?: MediaView; before?: MediaView }\n /** Dotted path, such as `seo.title`. */\n path: string\n}\n\nexport interface MediaView {\n label: string\n /** Attached in this conversation and not saved yet. */\n pending?: boolean\n /** A small image, when the file is an image the editor can read. */\n thumbnail?: string\n}\n\nexport interface PlanCandidateView {\n href?: string\n id?: string\n kind: PlanTargetKind\n label: string\n slug: string\n}\n\nexport interface PlanFileView {\n collection: string\n /** Position in the conversation's attachments. */\n index: number\n name: string\n note: string\n savesImmediately: boolean\n}\n\n/** What the drawer shows before anything is written. */\nexport interface AssistantPlanView {\n blocked: boolean\n candidates: PlanCandidateView[]\n files: PlanFileView[]\n id: string\n operations: PlanOperationView[]\n questions: string[]\n summary: string\n}\n\nexport interface AssistantChange {\n action: 'created' | 'updated' | 'uploaded'\n /** Collection or global slug. With the id, lets a later plan point at a document this one saved. */\n collection: string\n detail?: string\n href: string\n id: string\n label: string\n}\n\n/** The document open in the admin when the editor sends a message. */\nexport interface PageContext {\n id?: string\n kind: PlanTargetKind\n label: string\n slug: string\n}\n\n/** A file attached to a conversation. The index is its position across the whole conversation. */\nexport interface AttachmentView {\n index: number\n name: string\n type: string\n}\n\nexport interface AssistantMessageMetadata {\n /** Files first attached with this user message. Set by the server. */\n attachments?: AttachmentView[]\n /** The document open when this user message was sent. */\n context?: PageContext\n /** Token use for an assistant reply. */\n usage?: {\n cachedInputTokens?: number\n inputTokens?: number\n outputTokens?: number\n totalTokens?: number\n }\n}\n\nexport type PlanStatus = 'applied' | 'blocked' | 'cancelled' | 'proposed'\n\n/** What submitPlan returns. The drawer renders it as a plan card. The status changes when the editor acts on it. */\nexport type SubmitPlanOutput =\n | { changes?: AssistantChange[]; ok: true; plan: AssistantPlanView; status: PlanStatus }\n | { error: string; ok: false }\n\n/** The project's AI Gateway budget, as shares only. Dollar amounts stay on the server. */\nexport interface BudgetView {\n /** At or past `lowBudgetUsedShare` of the budget used. */\n low: boolean\n /** What is left as a share of the budget for this period, from 0 to 1. */\n remainingShare: number\n}\n\n/** Replies billed to the site's own provider key. US dollars are the site's own spend, so admins see them. */\nexport interface OwnKeyView {\n /** Admins only: model calls today that fell back to Vercel's credit because the key failed. */\n fallbackSteps?: number\n /** The provider's name, such as `Anthropic`. */\n provider: string\n /** Admins only: everyone's spend on the key today, in US dollars, as the gateway prices it. */\n todayUsd?: number\n}\n\n/**\n * What the panel header shows. On Vercel billing: the editor's share of today's cap and, for admins, the project's\n * budget, as shares only. On the own key: which provider pays and, for admins, today's spend on it.\n */\nexport interface UsageView {\n budget?: BudgetView\n ownKey?: OwnKeyView\n /** Missing when there is no daily cap. */\n today?: {\n /** Share of today's allowance used, from 0. */\n usedShare: number\n }\n}\n"],"names":[],"mappings":"AAoMA;;;CAGC,GACD,WAQC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type AssetKind = 'caption' | 'document' | 'image' | 'video';
|
|
2
|
+
/** Programs and scripts are never accepted, whatever collection they would go to. */
|
|
3
|
+
export declare function isBlockedFilename(name: string): boolean;
|
|
4
|
+
export interface UploadTarget {
|
|
5
|
+
/** Empty means this collection accepts files that no other collection claims, such as PDFs. */
|
|
6
|
+
mimeTypes: string[];
|
|
7
|
+
slug: string;
|
|
8
|
+
}
|
|
9
|
+
export type UploadChoice = {
|
|
10
|
+
error: string;
|
|
11
|
+
} | {
|
|
12
|
+
kind: AssetKind;
|
|
13
|
+
mime: string;
|
|
14
|
+
slug: string;
|
|
15
|
+
};
|
|
16
|
+
export declare function mimeTypesFromUpload(upload: unknown): string[];
|
|
17
|
+
export declare function titleFromFilename(filename: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* Files an upload into the collection whose mime types match.
|
|
20
|
+
* Images, video, and captions stay in their own collections. Other files use the
|
|
21
|
+
* collection that has no mime filter, which is Documents.
|
|
22
|
+
*/
|
|
23
|
+
export declare function chooseUploadCollection(file: {
|
|
24
|
+
name: string;
|
|
25
|
+
type: string;
|
|
26
|
+
}, targets: UploadTarget[]): UploadChoice;
|
|
27
|
+
export declare function kindFromMime(mime: string): AssetKind;
|