diff --git a/apps/mana/apps/landing/src/content/devlog/2026-04-07-encryption-phases-1-9-cycles-dreams-events.md b/apps/mana/apps/landing/src/content/devlog/2026-04-07-encryption-phases-1-9-period-dreams-events.md similarity index 100% rename from apps/mana/apps/landing/src/content/devlog/2026-04-07-encryption-phases-1-9-cycles-dreams-events.md rename to apps/mana/apps/landing/src/content/devlog/2026-04-07-encryption-phases-1-9-period-dreams-events.md diff --git a/apps/mana/apps/web/src/lib/components/settings/AiSettings.svelte b/apps/mana/apps/web/src/lib/components/settings/AiSettings.svelte index 38a12337d..67f8fa271 100644 --- a/apps/mana/apps/web/src/lib/components/settings/AiSettings.svelte +++ b/apps/mana/apps/web/src/lib/components/settings/AiSettings.svelte @@ -19,7 +19,8 @@ MODELS, DEFAULT_MODEL, } from '@mana/local-llm'; - import { Robot, Cpu, HardDrive, Cloud, Warning, CheckCircle } from '@mana/shared-icons'; + import { Robot, Cpu, HardDrive, Cloud, Warning, CheckCircle, Key } from '@mana/shared-icons'; + import ByokKeysManager from './ByokKeysManager.svelte'; const settings = $derived(llmSettingsState.current); const webgpuSupported = isLocalLlmSupported(); @@ -90,6 +91,17 @@ 'Keine Inhalte werden gespeichert', ], }, + { + tier: 'byok', + icon: Key, + title: 'Eigener API-Key', + subtitle: 'OpenAI, Anthropic, Google Gemini oder Mistral', + bullets: [ + 'Direkt aus dem Browser — keine Mana-Server-Zwischenstation', + 'Du zahlst beim Provider, wir sehen nichts davon', + 'Schluessel werden verschluesselt in deinem Vault gespeichert', + ], + }, { tier: 'cloud', icon: Cloud, @@ -229,6 +241,17 @@

{/if} + {#if card.tier === 'byok' && enabled} +
e.stopPropagation()} + onkeydown={(e) => e.stopPropagation()} + role="presentation" + > + +
+ {/if} + {#if card.tier === 'cloud' && enabled && !settings.cloudConsentGiven}
- - KI-Keys - Mana - - -
- - +
{#if vaultLocked}
Vault ist gesperrt — bitte zuerst anmelden um Keys zu verwalten.
{:else if loading} -
Laedt...
+
Laedt...
{:else} -
- -
+ {#if keys.length > 0} +
+ {#each keys as k (k.id)} +
+ {#if editingId === k.id} + + + + + {:else} +
+
+
+ {k.label} + {#if k.isDefault}Standard{/if} +
+
+ {providerDisplay(k.provider)} · {k.model || providerDefaultModel(k.provider)} · + {k.usageCount} Aufrufe · {formatCost(k.totalCostUsd)} +
+
+
+ {#if !k.isDefault} + + {/if} + + +
+ {/if} +
+ {/each} +
+ {/if} {#if showAdd}
-

Neuen Key hinzufuegen

- +
+ + +
- - - - - - - - - +
+ + +
{#if addError}
{addError}
{/if} -
+ {:else} + {/if} - -
- {#each keys as k (k.id)} -
- {#if editingId === k.id} -
- - - - -
- {:else} -
-
-
-
- {k.label} - {#if k.isDefault} - Standard - {/if} -
-
- {providerDisplay(k.provider)} - · {k.model || `Default (${providerDefaultModel(k.provider)})`} -
-
- {k.usageCount} Aufrufe · {k.totalTokens.toLocaleString('de-DE')} Token · {formatCost( - k.totalCostUsd - )} -
-
-
- {#if !k.isDefault} - - {/if} - - -
-
- {/if} -
- {:else} -
- -

Noch keine API-Keys hinterlegt.

-

- Klicke auf "Key hinzufuegen" um mit OpenAI, Anthropic, Gemini oder Mistral zu chatten. -

-
- {/each} -
{/if}