Phase 7a: cards.create-Tool für Cloze + Image-Occlusion + content_hash
Some checks are pending
CI / validate (push) Waiting to run
Some checks are pending
CI / validate (push) Waiting to run
Tool-Pfad in /api/v1/tools/cards.create war nicht konvergent zum
REST-Pfad in /api/v1/cards POST:
- subIndexCount(type) crashte bei type='cloze' und 'image-occlusion'
(beide werfen seit Sprint 8a/9l, weil Sub-Index-Anzahl text-abhängig)
- content_hash wurde nicht geschrieben (war seit Sprint 9j auf REST-Pfad)
Fix: identische Branching-Logik wie cards.ts POST. Cloze ohne {{cN::…}}
und image-occlusion ohne valides mask_regions-JSON liefern 422.
content_hash wird mit cardContentHash beim Insert geschrieben.
Damit ist der Tool-Pfad voll-konvergent — mana-mcp und Persona-Runner
können jeden Card-Type via cards.create anlegen, sobald die Plattform-
Services (mana-share + mana-mcp) deployed sind.
Phase-7-Plumbing:
✓ Cards-Tools (cards.create + cards.search) sind konvergent zum
REST-Pfad und end-to-end via Bearer-JWT verifiziert
✓ App-Manifest deklariert beide Tools (input_schema + output_schema)
✓ Service-Key in mana-auth registriert (Phase 2)
✗ mana-mcp + mana-share Container sind auf Mac Mini NICHT deployed
→ Tool-Discovery + Routing aus Claude Desktop / Persona-Runner
bleiben offen, bis die Plattform-Services hochgezogen werden.
Das ist Plattform-Scope, nicht Cards-Scope.
56 API-Tests grün, type-check sauber.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
5b6d096f56
commit
d7c7c9772e
1 changed files with 36 additions and 4 deletions
|
|
@ -4,8 +4,11 @@ import { Hono } from 'hono';
|
|||
import {
|
||||
CardsCreateInputSchema,
|
||||
CardsSearchInputSchema,
|
||||
cardContentHash,
|
||||
maskRegionCount,
|
||||
newReview,
|
||||
subIndexCount,
|
||||
subIndexCountForCloze,
|
||||
} from '@cards/domain';
|
||||
|
||||
import { getDb, type CardsDb } from '../db/connection.ts';
|
||||
|
|
@ -55,8 +58,39 @@ export function toolsRouter(deps: ToolsDeps = {}): Hono<{ Variables: AuthVars }>
|
|||
if (!deck) return c.json({ error: 'deck_not_found' }, 404);
|
||||
if (deck.userId !== userId) return c.json({ error: 'deck_not_owned' }, 403);
|
||||
|
||||
// Text-abhängige Sub-Index-Counts identisch zum REST-Pfad
|
||||
// (cards.ts POST). Cloze ohne Cluster + Image-Occlusion
|
||||
// ohne Mask-Regions werden 422.
|
||||
let count: number;
|
||||
if (parsed.data.type === 'cloze') {
|
||||
count = subIndexCountForCloze(parsed.data.fields.text ?? '');
|
||||
if (count === 0) {
|
||||
return c.json(
|
||||
{ error: 'invalid_input', issues: ['cloze.text contains no {{cN::…}} clusters'] },
|
||||
422
|
||||
);
|
||||
}
|
||||
} else if (parsed.data.type === 'image-occlusion') {
|
||||
count = maskRegionCount(parsed.data.fields.mask_regions ?? '');
|
||||
if (count === 0) {
|
||||
return c.json(
|
||||
{
|
||||
error: 'invalid_input',
|
||||
issues: ['image-occlusion.mask_regions must be JSON array with >=1 region'],
|
||||
},
|
||||
422
|
||||
);
|
||||
}
|
||||
} else {
|
||||
count = subIndexCount(parsed.data.type);
|
||||
}
|
||||
|
||||
const cardId = ulid();
|
||||
const now = new Date();
|
||||
const contentHash = await cardContentHash({
|
||||
type: parsed.data.type,
|
||||
fields: parsed.data.fields,
|
||||
});
|
||||
const [row] = await dbOf().transaction(async (tx) => {
|
||||
const [card] = await tx
|
||||
.insert(cards)
|
||||
|
|
@ -67,14 +101,12 @@ export function toolsRouter(deps: ToolsDeps = {}): Hono<{ Variables: AuthVars }>
|
|||
type: parsed.data.type,
|
||||
fields: parsed.data.fields,
|
||||
mediaRefs: parsed.data.media_refs ?? [],
|
||||
contentHash,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
})
|
||||
.returning();
|
||||
const initial = Array.from(
|
||||
{ length: subIndexCount(parsed.data.type) },
|
||||
(_, i) => i
|
||||
).map((subIndex) => {
|
||||
const initial = Array.from({ length: count }, (_, i) => i).map((subIndex) => {
|
||||
const r = newReview({ userId, cardId, subIndex, now });
|
||||
return {
|
||||
cardId: r.card_id,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue