feat(tickets): Kurz-Verweise (Shortlinks) im Ticket-Text auflösen

Die KI kann im Text `tier:<8hex>` / `kontakt:` / `wurf:` / `gehege:` schreiben;
Frontend löst per POST /refs/resolve (Präfix-Match, DB-agnostisch) zu Name +
internem Link auf. Reine KI-Schreibhilfe — kein Nutzer-Button.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-23 07:23:03 +02:00
parent c7b054e909
commit 00dba91a5c
7 changed files with 407 additions and 7 deletions

View File

@@ -795,6 +795,34 @@ export async function installMockApi(page: Page): Promise<MockDb> {
return json(route, 405)
}
// REFS: getippte Kurz-Verweise (Shortlinks) auflösen. Spiegelt das Backend:
// Präfix-Match (>=6 Hex, bindestrich-tolerant) auf der bindestrich-losen Id;
// mehrdeutig/unbekannt => id/name null.
if (path === '/refs/resolve' && method === 'POST') {
const body = request.postDataJSON() as { refs?: { type?: string; code?: string }[] }
const tableFor: Record<string, Row[]> = {
tier: db.gerbils as unknown as Row[],
kontakt: db.contacts as unknown as Row[],
wurf: db.litters as unknown as Row[],
gehege: db.enclosures as unknown as Row[],
}
const normCode = (code: string) => (code ?? '').toLowerCase().replace(/[^0-9a-f]/g, '')
const results = (body.refs ?? []).map((r) => {
const type = (r.type ?? '').toLowerCase()
const prefix = normCode(r.code ?? '')
const rows = tableFor[type]
if (!rows || prefix.length < 6) return { type: r.type, code: r.code, id: null, name: null }
const matches = rows.filter((row) =>
String(row.id ?? '').toLowerCase().replace(/-/g, '').startsWith(prefix),
)
if (matches.length === 1) {
return { type: r.type, code: r.code, id: String(matches[0].id), name: String(matches[0].name ?? '') }
}
return { type: r.type, code: r.code, id: null, name: null }
})
return json(route, 200, results)
}
// Generische Kollektionen: /<resource> und /<resource>/<id>
m = path.match(/^\/([a-z-]+)(?:\/([^/]+))?$/)
const col = m ? collections[m[1]] : undefined