15 KiB
lib/ — Utilities & Shared Logic
Geteilte Hilfsfunktionen, Typ-Definitionen und Konfiguration. Keine React-Komponenten — nur reines TypeScript.
Dateien im Überblick
| Datei | Zweck |
|---|---|
canvas-utils.ts |
Convex↔React Flow Adapter, Edge-Glow, Node-Defaults, Bridge-Edges |
canvas-node-catalog.ts |
Vollständige Node-Taxonomie (alle Phasen, Kategorien, Phase-Flags) |
canvas-node-types.ts |
TypeScript-Typen und Union-Typen für Canvas-Nodes |
canvas-node-templates.ts |
Default-Daten für neue Nodes (beim Einfügen aus Palette) |
canvas-connection-policy.ts |
Validierungsregeln für Edge-Verbindungen zwischen Nodes |
agent-definitions.ts |
Runtime-Registry fuer Agent-Definitionen (Struktur, Regeln, Blueprints, Docs-Pfad) |
agent-templates.ts |
UI-Projektion auf Agent-Metadaten aus agent-definitions.ts |
agent-prompting.ts |
Pure Prompt-Builder (summarizeIncomingContext, buildAnalyzeMessages, buildExecuteMessages) |
agent-run-contract.ts |
Normalisierung fuer Clarifications, Execution Plan und strukturierte Agent-Outputs |
generated/agent-doc-segments.ts |
Generierte Prompt-Segmente aus components/agents/*.md (nicht manuell editieren) |
ai-models.ts |
Client-seitige Bild-Modell-Definitionen (muss mit convex/openrouter.ts in sync bleiben) |
ai-video-models.ts |
Video-Modell-Registry: 5 MVP-Modelle mit Endpunkten, Credit-Kosten, Tier-Zugang |
video-poll-logging.ts |
Log-Volumen-Steuerung für Video-Polling (vermeidet excessive Konsolenausgabe) |
tier-credits.ts |
Tier-Normalisierung (normalizePublicTier) für Video-Modell-Tier-Checks |
image-formats.ts |
Aspect-Ratio-Strings, Node-Chrome-Höhen (AI_IMAGE_NODE_HEADER_PX etc.) |
auth.ts |
Better Auth Server-Instanz |
auth-server.ts |
Server-Helper: getAuthUser(), getToken() |
auth-client.ts |
Client-Helper: authClient |
canvas-local-persistence.ts |
localStorage-Cache für Canvas-Snapshots und Op-Queue |
canvas-op-queue.ts |
IndexedDB-basierte Canvas-Sync-Queue (Retry, TTL, Remap/Pruning) |
toast.ts |
Toast-Utility-Wrapper |
toast-messages.ts |
Typisierte Toast-Message-Definitionen (msg, CanvasNodeDeleteBlockReason) |
ai-errors.ts |
Error-Kategorisierung und User-facing Fehlermeldungen |
pexels-types.ts |
TypeScript-Typen für Pexels-API-Responses |
polar-products.ts |
Polar.sh Produkt-IDs und Tier-Mapping |
rate-limit.ts |
Rate-Limiting-Utilities (Redis-backed) |
redis.ts |
Redis-Client-Initialisierung |
topup-calculator.ts |
Bonus-Staffel-Berechnung für Credit-Top-Ups |
format-time.ts |
Zeitformatierung (relative Zeitangaben) |
utils.ts |
cn() (clsx + tailwind-merge), allgemeine Utilities |
credits-activity.ts |
Credits-Aktivitäts-Analytics: Transaktions-Priorisierung, Activity-Series, Usage-Domain-Berechnung |
dashboard-snapshot-cache.ts |
localStorage-Cache für Dashboard-Snapshots (12h TTL, versioniert) |
Agent Runtime: Dual Model
Die Agent-Runtime folgt einem dualen Modell:
- TS-Vertraege als Struktur-Single-Source:
lib/agent-definitions.ts+lib/agent-run-contract.tsdefinieren IDs, Regeln, Blueprints und Normalisierung. - Markdown-Segmente als kuratierter Prompt-Input: markierte Segmente in
components/agents/*.mdwerden viascripts/compile-agent-docs.tsinlib/generated/agent-doc-segments.tskompiliert.
Wichtig:
convex/agents.tsliest nur die generierte TS-Datei, nicht Raw-Markdown.- Nur markierte
AGENT_PROMPT_SEGMENT-Bloecke beeinflussen Analyze/Execute-Prompts. agent-templates.tsist bewusst nur eine UI-Projektion ausagent-definitions.ts.
canvas-utils.ts — Wichtigste Datei
Alle Adapter-Funktionen zwischen Convex-Datenmodell und React Flow. Details in components/canvas/CLAUDE.md.
Kritische Exports:
convexNodeToRF,convexEdgeToRF,convexEdgeToRFWithSourceGlowconvexNodeDocWithMergedStorageUrl— URL-Injection für Storage-Bilder aus serverseitig aufgelöster URL-Map oder gecachtem VorgängerzustandNODE_DEFAULTS— Default-Größen und Daten per Node-Typ (inkl.video-promptundai-video)NODE_HANDLE_MAP— Handle-IDs pro Node-Typ (inkl.video-prompt-out/inundvideo-out/in)SOURCE_NODE_GLOW_RGB— Edge-Glow-Farben pro Source-Node-Typ (inkl.video-promptundai-video)agentist als input-only Node enthalten (NODE_HANDLE_MAP.agent = { target: "agent-in" })computeBridgeCreatesForDeletedNodes— Kanten-Reconnect nach Node-LöschungcomputeMediaNodeSize— Dynamische Node-Größe basierend auf Bild-Dimensionen
Wichtig: canvas-utils.ts erzeugt keine Storage-Fallback-URLs mehr selbst. Die URL-Auflösung kommt aus dem Canvas-Layer (storage.batchGetUrlsForCanvas) und wird hier nur noch gemerged/cached.
canvas-node-types.ts — TypeScript-Typen
Einzige Quelle für Node-Typ-Union-Typen und Schema-Validatoren.
PHASE1_CANVAS_NODE_TYPES // Phase 1 Nodes (aktiv)
CANVAS_NODE_TYPES // Phase 1 + Phase 2 + Phase 3 (alle)
ADJUSTMENT_NODE_TYPES // Adjustment-Preset-Nodes (curves, color-adjust, etc.)
ADJUSTMENT_PRESET_NODE_TYPES // Spezifische Adjustment-Presets
Wichtig: Dieser Datei und convex/node_type_validator.ts müssen immer synchron gehalten werden. Neue Nodes → Validator anpassen.
Video-Typen: video-prompt ist in PHASE1_CANVAS_NODE_TYPES und CANVAS_NODE_TYPES enthalten. ai-video ist in CANVAS_NODE_TYPES (Phase 2).
canvas-node-catalog.ts — Node-Taxonomie
Einzige Wahrheitsquelle für alle Node-Typen auf Client-Seite.
NODE_CATALOG // Alle Nodes aller Phasen
NODE_CATEGORY_META // Label + Sortierung pro Kategorie
NODE_CATEGORIES_ORDERED // Sortierte Kategorien-Liste
catalogEntriesByCategory() // Gruppiert für Sidebar-Rendering
isNodePaletteEnabled // true wenn: implementiert + kein systemOutput + Template vorhanden
Kategorien:
source— Quelle (image, text, video, asset, color)ai-output— KI-Ausgabe (prompt, video-prompt, ai-text, ai-video, agent-output)transform— Transformation (crop, bg-remove, upscale)image-edit— Bildbearbeitung (adjustments)control— Steuerung & Flowlayout— Canvas & Layout (group, frame, note, compare)
Node-Eigenschaften:
type— Node-Typ (als String)label— Anzeigetextcategory— Kategorisierungphase— 1, 2 oder 3 (für zukünftige Feature-Phasen)implemented— true wenn React-Flow-Komponente vorhandensystemOutput— true wenn KI-System diese Nodes erzeugt (nicht aus Palette nutzbar)disabledHint— Kurzer Hinweis für deaktivierte Nodes
Phase-2/3-Nodes: Haben implemented: false und disabledHint. UI filtert nach Phase, niemals ohne zugehörige React-Flow-Komponente implemented: true setzen.
canvas-node-templates.ts — Default-Daten
Default-Initial-Daten für neue Nodes beim Einfügen aus Palette.
- Erstellt durch die Node-Katalog-Einträge
- Enthält default-Werte für
data-Felder video-prompthat Default-Daten:{ modelId: "wan-2-2-720p", durationSeconds: 5 }agenthat aktuell ein statisches Template-Default:{ templateId: "campaign-distributor" }- Wird von
canvas.tsxverwendet beim Node-Create
canvas-connection-policy.ts — Validierungsregeln
Regeln für erlaubte Verbindungen zwischen Node-Typen.
Validierungs-Funktionen:
validateCanvasConnectionPolicy()— Prüft, ob Verbindung erlaubt istgetCanvasConnectionValidationMessage()— Gibt lesbare Fehlermeldung zurückassertConnectionPolicy()— Wirft Fehler bei ungültiger Verbindung
Regeln:
- Source-Typ muss Output-Ports haben, Target-Typ muss Input-Ports haben
- Keine self-loops (Edge von Node zu sich selbst)
- Quelle:
image,text,note,group,compare,frame→ Source-Ports - Ziel:
ai-image,ai-video,compare→ Target-Ports - Video-Flow:
video-prompt → ai-video✅ (einzige gültige Kombination)ai-videoals Target akzeptiert nurvideo-promptals Source (ai-video-source-invalid)video-promptals Source akzeptiert nurai-videoals Target (video-prompt-target-invalid)text → video-prompt✅ (Prompt-Quelle, über default-Handles)
- Agent-MVP:
agentakzeptiert nur Content-/Kontext-Quellen (agent-source-invalidbei Prompt/Steuerknoten), ohne eingehendes Kantenlimit - Curves- und Adjustment-Node-Presets: Nur Presets nutzen, keine direkten Edges
ai-models.ts — Sync-Pflicht
// Muss identisch zu convex/openrouter.ts sein!
export const IMAGE_MODELS: AiModel[]
export const DEFAULT_MODEL_ID: string
Achtung: Diese Datei und convex/openrouter.ts müssen immer synchron gehalten werden. Bei neuen Modellen beide Dateien gleichzeitig aktualisieren. creditCost muss übereinstimmen — sonst stimmt die angezeigte Kostenvorschau nicht mit dem tatsächlichen Abzug überein.
ai-video-models.ts — Video-Modell-Registry
Zentrale Definition aller KI-Video-Modelle mit Freepik-Endpunkten, Credit-Kosten und Tier-Zugang.
export type VideoModelId = "wan-2-2-480p" | "wan-2-2-720p" | "kling-std-2-1" | "seedance-pro-1080p" | "kling-pro-2-6"
export type VideoModelTier = "free" | "starter" | "pro"
export type VideoModelDurationSeconds = 5 | 10
export const VIDEO_MODELS: Record<VideoModelId, VideoModel>
export const DEFAULT_VIDEO_MODEL_ID: VideoModelId // "wan-2-2-720p"
MVP-Modelle:
| ID | Label | Tier | Endpunkt | 5s (Cr) | 10s (Cr) |
|---|---|---|---|---|---|
wan-2-2-480p |
WAN 2.2 480p | free | /v1/ai/text-to-video/wan-2-5-t2v-720p |
28 | 56 |
wan-2-2-720p |
WAN 2.2 720p | free | /v1/ai/text-to-video/wan-2-5-t2v-720p |
52 | 104 |
kling-std-2-1 |
Kling Standard 2.1 | starter | /v1/ai/image-to-video/kling-v2-1-std |
50 | 100 |
seedance-pro-1080p |
Seedance Pro 1080p | starter | /v1/ai/video/seedance-1-5-pro-1080p |
33 | 66 |
kling-pro-2-6 |
Kling Pro 2.6 | pro | /v1/ai/image-to-video/kling-v2-6-pro |
59 | 118 |
Wichtig: Jedes Modell hat einen statusEndpointPath (z. B. /v1/ai/text-to-video/wan-2-5-t2v-720p/{task-id}), der für das Polling des Task-Status verwendet wird. Freepik hat keinen generischen Task-Status-Endpunkt.
Sync-Pflicht: Diese Datei und convex/freepik.ts / convex/ai.ts müssen synchron gehalten werden. creditCost muss mit dem Credit-System übereinstimmen.
Hilfsfunktionen:
isVideoModelId(value)— Type-Guard für VideoModelIdgetVideoModel(id)— Holt Modell-Definition, gibtundefinedbei ungültiger IDgetAvailableVideoModels(tier)— Filtert Modelle nach User-Tier
video-poll-logging.ts — Log-Volumen-Steuerung
Reduziert Konsolenausgabe beim Video-Polling (bis zu 30 Versuche pro Video).
export function shouldLogVideoPollAttempt(attempt: number): boolean
// true bei Versuch 1 und jedem 5. Versuch (5, 10, 15, ...)
export function shouldLogVideoPollResult(attempt: number, status: VideoPollStatus): boolean
// true bei jedem nicht-IN_PROGRESS Status oder wenn shouldLogVideoPollAttempt true ist
Verwendet in convex/ai.ts (pollVideoTask) und convex/freepik.ts (getVideoTaskStatus).
credits-activity.ts — Credits Analytics
Analytics-Helpers für die Dashboard Credits-Aktivitäts-Anzeige. Wird von components/dashboard/credits-activity-chart.tsx und convex/dashboard.ts verwendet.
Kernfunktionen:
// Transaktions-Priorisierung (Usage → Reservation → Refund → Topup → Subscription)
prioritizeRecentCreditTransactions(transactions, limit)
// Tages-aggregierte Activity-Series für Recharts (max. 7 Tage)
buildCreditsActivitySeries(transactions, availableCredits, locale, maxPoints?)
// Y-Achsen-Domain mit Headroom (mind. 8, +20% Headroom)
calculateUsageActivityDomain(points)
// Credit-Formatierung ("1.234 Cr")
formatCredits(value, locale)
Typen:
CreditTransactionLike— Minimales Transaction-Interface für AnalyticsCreditActivityPoint— Tages-Datenpunkt ({ day, usage, activity, available })
dashboard-snapshot-cache.ts — Dashboard Snapshot Cache
localStorage-basierter Cache für Dashboard-Snapshot-Daten.
readDashboardSnapshotCache<T>(userId, options?) // Cached Snapshot lesen (mit TTL-Prüfung)
writeDashboardSnapshotCache<T>(userId, snapshot) // Snapshot schreiben
clearDashboardSnapshotCache(userId) // Cache invalidieren
Konfiguration:
- Namespace:
lemonspace.dashboard - Key:
lemonspace.dashboard:snapshot:v1:<userId> - TTL: 12 Stunden (
DEFAULT_TTL_MS = 12 * 60 * 60 * 1000) - Version:
CACHE_VERSION = 1— Bumps invalidieren bestehende Caches - Alle Storage-Zugriffe defensiv (try-catch, quota handling)
canvas-local-persistence.ts — localStorage-Cache
readCanvasSnapshot(canvasId) // Letzten Snapshot laden
writeCanvasSnapshot(canvasId, {nodes, edges}) // Snapshot speichern
enqueueCanvasOp(canvasId, op) // Op in Queue schreiben
resolveCanvasOp(canvasId, opId) // Op aus Queue entfernen
readCanvasOps(canvasId) // Ausstehende Ops lesen
remapCanvasOpNodeId(canvasId, fromId, toId) // optimistic→real remap
dropCanvasOpsByNodeIds(canvasId, ids) // konfliktbedingtes Pruning
dropCanvasOpsByClientRequestIds(canvasId, ids) // Create-Cancel
dropCanvasOpsByEdgeIds(canvasId, ids) // Remove-Cancel
Key-Schema: lemonspace.canvas:snapshot:v1:<id> / lemonspace.canvas:ops:v1:<id>. Bei Version-Bumps (SNAPSHOT_VERSION, OPS_VERSION) werden alte Keys automatisch ignoriert.
canvas-op-queue.ts — Sync-Queue
Zentrale, persistente Queue für Canvas-Mutations mit IndexedDB (Fallback: localStorage), Retry-Backoff und 24h-TTL.
Wichtige APIs:
enqueueCanvasSyncOp(...)
listCanvasSyncOps(canvasId)
ackCanvasSyncOp(opId)
markCanvasSyncOpFailed(opId, { nextRetryAt, lastError })
dropExpiredCanvasSyncOps(canvasId, now)
remapCanvasSyncNodeId(canvasId, fromId, toId)
dropCanvasSyncOpsByNodeIds(canvasId, ids)
dropCanvasSyncOpsByClientRequestIds(canvasId, ids)
dropCanvasSyncOpsByEdgeIds(canvasId, ids)
Auth-Helpers
// Server (lib/auth-server.ts) — nur in Server Components / Route Handlers
getAuthUser() // → Better Auth User | null
getToken() // → Convex JWT Token | null (für initialToken im Root Layout)
// Client (lib/auth-client.ts)
authClient // Better Auth Client-Instanz für signIn, signUp, signOut etc.
Konventionen
- Keine React-Imports in
lib/— reines TypeScript utils.tsfür generische Helpers (cn,clamp, etc.)- Typen, die sowohl Frontend als auch Convex betreffen, gehören in
lib/, nicht inconvex/ - Modell-Registrys (
ai-models.ts,ai-video-models.ts) müssen immer mit den Backend-Äquivalenten synchron gehalten werden