mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-19 14:57:42 +02:00
feat(website): M5 — AI tools + starter templates
Two things:
1. AI tools (9) in the website module — writes go through the standard
proposal flow, reads run auto during planning.
- shared-ai/src/tools/schemas.ts: AI_TOOL_CATALOG entries with
defaultPolicy propose/auto.
- webapp modules/website/tools.ts: execute functions wired to the
existing stores. ModuleTool[] registered in data/tools/init.ts.
- Propose: create_website, apply_website_template, create_website_page,
add_website_block, update_website_block, publish_website
- Auto: list_websites, list_website_pages, list_website_blocks
Server-side mana-tool-registry integration (mana-mcp, mana-ai) is
a M5.x follow-up — webapp flow unblocks the missions-based use case.
2. Starter templates — clone into a fresh site with new UUIDs.
- templates/types.ts: SiteTemplate shape with localId / parentLocalId
so container→child references survive the clone.
- 4 templates: portfolio (4 pages), personal-linktree (1 page, 6 CTAs),
event (3 pages incl. RSVP form), blank (1 empty page). Deferred:
smb-corporate + product-landing (need team/pricing/testimonials
blocks, M6+).
- sitesStore.applyTemplate: walks template, bulk-inserts new rows,
remaps parent refs. Sets navConfig items from template pages.
- TemplatePicker component + /website/new route. Replaces the old
quick-create modal; ListView now links to /new. AppRegistry
context-menu action points there too.
AiProposalInbox integration deferred — the component doesn't exist in
the webapp yet (the plan mentions it aspirationally). defaultPolicy
'propose' is already set so writes stage correctly once the UI catches
up.
Validation:
- pnpm run validate:all: 6/6 gates green
- pnpm run check (web): 0 errors, 0 warnings
- apps/api + packages/shared-ai type-check: green
Plan: docs/plans/website-builder.md (M5 shipped)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
3edf680ea0
commit
13efae8cd2
14 changed files with 1486 additions and 235 deletions
|
|
@ -1518,6 +1518,159 @@ export const AI_TOOL_CATALOG: readonly ToolSchema[] = [
|
|||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ── Website ───────────────────────────────────────────────
|
||||
{
|
||||
name: 'create_website',
|
||||
module: 'website',
|
||||
description:
|
||||
'Erstellt eine neue Website im aktiven Space mit einer Startseite. Gibt siteId und homePageId zurueck.',
|
||||
defaultPolicy: 'propose',
|
||||
parameters: [
|
||||
{
|
||||
name: 'name',
|
||||
type: 'string',
|
||||
description: 'Anzeigename der Website',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'slug',
|
||||
type: 'string',
|
||||
description: '2-40 Kleinbuchstaben/Zahlen/Bindestrich — wird Teil der URL (/s/{slug})',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'apply_website_template',
|
||||
module: 'website',
|
||||
description:
|
||||
'Erstellt eine neue Website aus einem Template (portfolio, personal-linktree, event, blank). Kopiert alle Seiten und Bloecke mit neuen IDs.',
|
||||
defaultPolicy: 'propose',
|
||||
parameters: [
|
||||
{
|
||||
name: 'templateId',
|
||||
type: 'string',
|
||||
description: 'Template-Kennung',
|
||||
required: true,
|
||||
enum: ['portfolio', 'personal-linktree', 'event', 'blank'],
|
||||
},
|
||||
{ name: 'name', type: 'string', description: 'Website-Name', required: true },
|
||||
{ name: 'slug', type: 'string', description: 'URL-Slug', required: true },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'create_website_page',
|
||||
module: 'website',
|
||||
description:
|
||||
'Fuegt einer existierenden Website eine neue Seite hinzu (z.B. /ueber-uns, /kontakt).',
|
||||
defaultPolicy: 'propose',
|
||||
parameters: [
|
||||
{ name: 'siteId', type: 'string', description: 'ID der Website', required: true },
|
||||
{
|
||||
name: 'path',
|
||||
type: 'string',
|
||||
description: 'URL-Pfad mit fuehrendem Slash (z.B. /ueber-uns)',
|
||||
required: true,
|
||||
},
|
||||
{ name: 'title', type: 'string', description: 'Seitentitel', required: true },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'add_website_block',
|
||||
module: 'website',
|
||||
description:
|
||||
'Fuegt einer Seite einen neuen Block hinzu. Block-Typen: hero, richText, cta, image, gallery, faq, form, moduleEmbed, columns, spacer. `props` ist ein JSON-Objekt mit den typ-spezifischen Feldern.',
|
||||
defaultPolicy: 'propose',
|
||||
parameters: [
|
||||
{ name: 'pageId', type: 'string', description: 'ID der Zielseite', required: true },
|
||||
{
|
||||
name: 'type',
|
||||
type: 'string',
|
||||
description: 'Block-Typ',
|
||||
required: true,
|
||||
enum: [
|
||||
'hero',
|
||||
'richText',
|
||||
'cta',
|
||||
'image',
|
||||
'gallery',
|
||||
'faq',
|
||||
'form',
|
||||
'moduleEmbed',
|
||||
'columns',
|
||||
'spacer',
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'props',
|
||||
type: 'object',
|
||||
description:
|
||||
'Typ-spezifische Eigenschaften. Leer = verwendet die Defaults. Beispiel fuer hero: { title, subtitle, ctaLabel, ctaHref }.',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'parentBlockId',
|
||||
type: 'string',
|
||||
description:
|
||||
'Falls der Block in einem Container liegt (z.B. columns), die ID des Containers.',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'slotKey',
|
||||
type: 'string',
|
||||
description: 'Slot-Key innerhalb des Containers, z.B. col-0 / col-1.',
|
||||
required: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'update_website_block',
|
||||
module: 'website',
|
||||
description:
|
||||
'Aktualisiert die props eines Blocks. `patch` ist ein JSON-Objekt mit nur den zu aendernden Feldern — alles andere bleibt unveraendert.',
|
||||
defaultPolicy: 'propose',
|
||||
parameters: [
|
||||
{ name: 'blockId', type: 'string', description: 'ID des Blocks', required: true },
|
||||
{
|
||||
name: 'patch',
|
||||
type: 'object',
|
||||
description: 'Die zu aendernden props-Felder',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'publish_website',
|
||||
module: 'website',
|
||||
description:
|
||||
'Veroeffentlicht die aktuelle Draft-Version der Website unter /s/{slug}. Vorher sollte der Inhalt vom Nutzer geprueft werden.',
|
||||
defaultPolicy: 'propose',
|
||||
parameters: [{ name: 'siteId', type: 'string', description: 'ID der Website', required: true }],
|
||||
},
|
||||
{
|
||||
name: 'list_websites',
|
||||
module: 'website',
|
||||
description:
|
||||
'Listet alle Websites im aktiven Space (id, slug, name, published-Status). Auto-Policy: laeuft waehrend Planning.',
|
||||
defaultPolicy: 'auto',
|
||||
parameters: [],
|
||||
},
|
||||
{
|
||||
name: 'list_website_pages',
|
||||
module: 'website',
|
||||
description: 'Listet die Seiten einer Website (id, path, title, order). Auto-Policy.',
|
||||
defaultPolicy: 'auto',
|
||||
parameters: [{ name: 'siteId', type: 'string', description: 'ID der Website', required: true }],
|
||||
},
|
||||
{
|
||||
name: 'list_website_blocks',
|
||||
module: 'website',
|
||||
description:
|
||||
'Listet die Bloecke einer Seite (id, type, parentBlockId, order, props-Snapshot). Auto-Policy.',
|
||||
defaultPolicy: 'auto',
|
||||
parameters: [{ name: 'pageId', type: 'string', description: 'ID der Seite', required: true }],
|
||||
},
|
||||
];
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue