mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 19:01:08 +02:00
feat(writing): M8 — AI tools exposed through the shared catalog
Writing is now programmatically accessible from the foreground mission
runner, personas, and Claude Desktop / MCP. Eight tools land:
Auto (read-only):
- list_drafts — filtered by kind/status + word-count summary
- get_draft — briefing + current version body, ready for reading
- list_writing_styles — 9 presets + user customs, ids usable in create_draft
Propose (human approval per agent policy):
- create_draft — briefing only, no generation yet
- generate_draft_content — wraps generationsStore.startDraftGeneration;
writes a new LocalDraftVersion + pointer flip
- refine_draft_selection — wraps refineSelection + applyRefinement in
one call; operations: shorten/expand/tone/
rewrite/translate with op-specific params
- set_draft_status — draft/refining/complete/published
- save_draft_as_article — hand-off to articlesStore.saveFromExtracted
with internal://writing/<id> as originalUrl,
records publishedTo + emits WritingDraftPublished
Schemas live in @mana/shared-ai/src/tools/schemas.ts (the SSOT that the
web-app policy layer + mana-ai planner derive from). Executors live in
modules/writing/tools.ts and delegate to the existing stores so the
encryption + event pipeline runs once regardless of who called the tool.
Registration added to data/tools/init.ts.
107 shared-ai tests still pass. CLAUDE.md tool-coverage table bumped:
67→75 tools, 21→22 modules.
Not in M8 (deferred): agent.defaultWritingStyleId linkage (needs a
Persona schema change + runner wiring), mana-tool-registry Zod specs
(add when a non-web MCP client needs richer validation).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
cc51f0b4b9
commit
d49ad239d9
4 changed files with 704 additions and 1 deletions
|
|
@ -1671,6 +1671,213 @@ export const AI_TOOL_CATALOG: readonly ToolSchema[] = [
|
|||
defaultPolicy: 'auto',
|
||||
parameters: [{ name: 'pageId', type: 'string', description: 'ID der Seite', required: true }],
|
||||
},
|
||||
|
||||
// ── Writing (Ghostwriter) ─────────────────────────────────
|
||||
{
|
||||
name: 'list_drafts',
|
||||
module: 'writing',
|
||||
description:
|
||||
'Listet Writing-Drafts (id, kind, title, status, wordCount). Optional nach kind oder status filterbar.',
|
||||
defaultPolicy: 'auto',
|
||||
parameters: [
|
||||
{
|
||||
name: 'kind',
|
||||
type: 'string',
|
||||
description: 'Nur eine Textart zeigen',
|
||||
required: false,
|
||||
enum: [
|
||||
'blog',
|
||||
'essay',
|
||||
'email',
|
||||
'social',
|
||||
'story',
|
||||
'letter',
|
||||
'speech',
|
||||
'cover-letter',
|
||||
'product-description',
|
||||
'press-release',
|
||||
'bio',
|
||||
'other',
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'status',
|
||||
type: 'string',
|
||||
description: 'Nur einen Status zeigen',
|
||||
required: false,
|
||||
enum: ['draft', 'refining', 'complete', 'published'],
|
||||
},
|
||||
{
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
description: 'Maximale Anzahl (Standard 30)',
|
||||
required: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'get_draft',
|
||||
module: 'writing',
|
||||
description:
|
||||
'Liefert einen vollstaendigen Draft inklusive Briefing, aktueller Version, Stil und Quellen.',
|
||||
defaultPolicy: 'auto',
|
||||
parameters: [{ name: 'draftId', type: 'string', description: 'ID des Drafts', required: true }],
|
||||
},
|
||||
{
|
||||
name: 'list_writing_styles',
|
||||
module: 'writing',
|
||||
description:
|
||||
'Listet verfuegbare Schreibstile (9 eingebaute Presets + vom Nutzer angelegte). Jeder mit id (preset:<id> oder uuid), name und Kurzbeschreibung.',
|
||||
defaultPolicy: 'auto',
|
||||
parameters: [],
|
||||
},
|
||||
{
|
||||
name: 'create_draft',
|
||||
module: 'writing',
|
||||
description:
|
||||
'Legt einen neuen Writing-Draft mit Briefing an — noch ohne Generation. Optional mit Stil und Quellen. Danach via generate_draft_content die erste Version erzeugen.',
|
||||
defaultPolicy: 'propose',
|
||||
parameters: [
|
||||
{
|
||||
name: 'kind',
|
||||
type: 'string',
|
||||
description: 'Textart',
|
||||
required: true,
|
||||
enum: [
|
||||
'blog',
|
||||
'essay',
|
||||
'email',
|
||||
'social',
|
||||
'story',
|
||||
'letter',
|
||||
'speech',
|
||||
'cover-letter',
|
||||
'product-description',
|
||||
'press-release',
|
||||
'bio',
|
||||
'other',
|
||||
],
|
||||
},
|
||||
{ name: 'title', type: 'string', description: 'Titel / Arbeitstitel', required: true },
|
||||
{
|
||||
name: 'topic',
|
||||
type: 'string',
|
||||
description: 'Kern-Briefing (worum geht es?)',
|
||||
required: true,
|
||||
},
|
||||
{ name: 'audience', type: 'string', description: 'Zielgruppe', required: false },
|
||||
{
|
||||
name: 'tone',
|
||||
type: 'string',
|
||||
description: 'Ton (z.B. "neutral", "warm")',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'language',
|
||||
type: 'string',
|
||||
description: 'ISO-Sprachcode, Standard "de"',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'targetWords',
|
||||
type: 'number',
|
||||
description: 'Ziel-Laenge in Woertern',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'styleId',
|
||||
type: 'string',
|
||||
description: 'Stil-ID (preset:<id> oder uuid einer Custom-Style-Row)',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'extraInstructions',
|
||||
type: 'string',
|
||||
description: 'Zusatzhinweise fuer die Generation',
|
||||
required: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'generate_draft_content',
|
||||
module: 'writing',
|
||||
description:
|
||||
'Erzeugt Text fuer einen existierenden Draft. Schreibt eine neue LocalDraftVersion und flippt den currentVersionId-Pointer auf die neue Version. Nutzt Briefing + Stil + Quellen des Drafts.',
|
||||
defaultPolicy: 'propose',
|
||||
parameters: [{ name: 'draftId', type: 'string', description: 'ID des Drafts', required: true }],
|
||||
},
|
||||
{
|
||||
name: 'refine_draft_selection',
|
||||
module: 'writing',
|
||||
description:
|
||||
'Verfeinert einen markierten Ausschnitt der aktuellen Version in-place. Operationen: shorten, expand, tone (target), rewrite (instruction), translate (targetLanguage). Wird direkt auf die aktuelle Version angewandt — keine neue Version.',
|
||||
defaultPolicy: 'propose',
|
||||
parameters: [
|
||||
{ name: 'draftId', type: 'string', description: 'ID des Drafts', required: true },
|
||||
{
|
||||
name: 'operation',
|
||||
type: 'string',
|
||||
description: 'Art der Verfeinerung',
|
||||
required: true,
|
||||
enum: ['shorten', 'expand', 'tone', 'rewrite', 'translate'],
|
||||
},
|
||||
{
|
||||
name: 'selectionStart',
|
||||
type: 'number',
|
||||
description: 'Zeichen-Start der Auswahl (0-basiert)',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'selectionEnd',
|
||||
type: 'number',
|
||||
description: 'Zeichen-Ende der Auswahl (exklusiv)',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'targetTone',
|
||||
type: 'string',
|
||||
description: 'Nur fuer operation=tone: der Zielton',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'instruction',
|
||||
type: 'string',
|
||||
description: 'Nur fuer operation=rewrite: die Anweisung',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'targetLanguage',
|
||||
type: 'string',
|
||||
description: 'Nur fuer operation=translate: ISO-Code der Zielsprache',
|
||||
required: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'set_draft_status',
|
||||
module: 'writing',
|
||||
description:
|
||||
'Setzt den Status eines Drafts (draft/refining/complete/published). Emittiert WritingDraftStatusChanged fuer die Timeline.',
|
||||
defaultPolicy: 'propose',
|
||||
parameters: [
|
||||
{ name: 'draftId', type: 'string', description: 'ID des Drafts', required: true },
|
||||
{
|
||||
name: 'status',
|
||||
type: 'string',
|
||||
description: 'Neuer Status',
|
||||
required: true,
|
||||
enum: ['draft', 'refining', 'complete', 'published'],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'save_draft_as_article',
|
||||
module: 'writing',
|
||||
description:
|
||||
'Veroeffentlicht die aktuelle Version des Drafts als Read-Later-Artikel im articles-Modul. Traegt das Ziel in draft.publishedTo ein und emittiert WritingDraftPublished.',
|
||||
defaultPolicy: 'propose',
|
||||
parameters: [{ name: 'draftId', type: 'string', description: 'ID des Drafts', required: true }],
|
||||
},
|
||||
];
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue