feat(writing): agent.defaultWritingStyleId — M8 persona-linkage follow-up

Agents can now pin a default writing style. When an AI-actor runs
`create_draft` without an explicit styleId, the tool resolves to the
agent's `defaultWritingStyleId` so e.g. a "Marketing-Agent" always
drafts in the Corporate-Tone style and a "Memoir-Agent" in Memoir.

- @mana/shared-ai: optional `defaultWritingStyleId?: string` added to
  the Agent interface (plaintext FK, format `preset:<id>` or a custom
  WritingStyle uuid). No migration — existing rows stay undefined and
  the fallback path no-ops for them.
- ai-agents store: field threaded through CreateAgentInput + AgentPatch
  + the create function's copy-list. `updateAgent` already deep-clones
  the patch so nothing else to change there.
- ai-agents ListView: new "Writing" section in the agent detail panel
  with a StylePicker (reuses the writing module's component — Vorlagen
  + Meine Stile optgroups). Empty = kein Default.
- writing/tools.ts: `resolveAgentDefaultStyle()` reads the current
  actor, guards `isAiActor`, loads the agent row, and returns its
  defaultWritingStyleId. Wired into `create_draft` as a fallback when
  `params.styleId` is missing. User-invoked calls skip the lookup — a
  human omitting styleId means "ad-hoc, no style", not "my default".
  `generate_draft_content` needs no change because the draft's styleId
  is already set at create time.

107 shared-ai tests still pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-04-24 16:36:20 +02:00
parent e7398b2dee
commit 6545498dc2
4 changed files with 55 additions and 2 deletions

View file

@ -54,6 +54,14 @@ export interface Agent {
* (tag IDs are not sensitive). */
scopeTagIds?: string[];
/** Fallback writing-style id for the Writing module (M8 follow-up).
* When this agent runs create_draft / generate_draft_content without
* an explicit styleId, the tool resolves to this value so e.g. a
* "Marketing-Agent" always drafts in the Corporate-Tone style.
* Format: `preset:<id>` for a built-in preset or the uuid of a
* custom LocalWritingStyle row. Plaintext FK. */
defaultWritingStyleId?: string;
/** Per-tool allowlist/propose/deny. Replaces the user-level AiPolicy
* in Phase 4; pre-populated with the default policy at create time
* so the runner can start reading it even while still consulting