feat: ditch triplit, move to postgresql + drizzle orm

This commit is contained in:
Zoe
2026-04-08 17:03:07 -05:00
parent c341c96798
commit e2e3ac6e86
121 changed files with 6680 additions and 4373 deletions
+17 -25
View File
@@ -1,5 +1,7 @@
<script setup lang="ts">
import { type Model } from '~/types/model';
import { type Model } from '~/composables/useModels';
const { updateModel, deleteModel } = await useModels();
const props = withDefaults(defineProps<{
model: Model;
@@ -22,8 +24,6 @@ const emit = defineEmits<{
edit: [model: Model];
}>();
const triplit = useTriplitClient();
const formatContextWindow = (window: number | null | undefined): string => {
if (!window) return '';
if (window >= 1000000) return `${(window / 1000000).toFixed(0)}M`;
@@ -31,28 +31,16 @@ const formatContextWindow = (window: number | null | undefined): string => {
return window.toString();
};
const hasCapability = (capability: string): boolean => {
return props.model.attributes.capabilities.has(capability);
};
const hasInputModality = (modality: string): boolean => {
return (props.model.attributes.inputModalities as ReadonlySet<string>).has(modality);
};
const showCost = computed(() => {
return props.showCost && (props.model.cost.prompt || props.model.cost.completion || props.model.cost.request);
});
const toggleModel = async (id: string) => {
await triplit.update('models', id, {
await updateModel(id, {
enabled: !props.model.enabled,
});
};
const deleteModel = async () => {
await triplit.delete('models', props.model.id);
};
const handleEdit = () => {
emit('edit', props.model);
};
@@ -79,11 +67,11 @@ const handleEdit = () => {
<div v-if="showEdit" class="flex items-center gap-2">
<!-- Edit button - only for custom models -->
<button v-if="model.isCustom" @click="handleEdit"
class="rounded h-5 w-5 flex items-center justify-center opacity-0 group-hover:opacity-100 hover:bg-[var(--color-accent)]/30 text-[var(--color-accent)] transition-all duration-200 ease-[cubic-bezier(0.5,_1,_0.89,_1)]">
class="rounded h-5 w-5 flex items-center justify-center opacity-0 group-hover:opacity-100 @hover:bg-[var(--color-accent)]/30 text-[var(--color-accent)] transition-all duration-200 ease-[cubic-bezier(0.5,_1,_0.89,_1)]">
<span class="i-mynaui-pencil text-3.5"></span>
</button>
<button @click="deleteModel"
class="rounded h-5 w-5 flex items-center justify-center opacity-0 group-hover:opacity-100 hover:bg-red-500/30 text-red-500 transition-all duration-200 ease-[cubic-bezier(0.5,_1,_0.89,_1)]">
<button @click="deleteModel(model.id)"
class="rounded h-5 w-5 flex items-center justify-center opacity-0 group-hover:opacity-100 @hover:bg-red-500/30 text-red-500 transition-all duration-200 ease-[cubic-bezier(0.5,_1,_0.89,_1)]">
<span class="i-mynaui-trash text-3.5"></span>
</button>
</div>
@@ -91,7 +79,11 @@ const handleEdit = () => {
<div v-if="details" class="flex items-center gap-1.5 flex-wrap text-[var(--text-tertiary)]">
<span v-if="showReleaseDate && model.releasedAt" class="text-xs whitespace-nowrap">
Released on {{ model.releasedAt.toISOString().split('T')[0] }}
Released on {{
typeof model.releasedAt === 'string'
? (model.releasedAt as string).split('T')[0]
: model.releasedAt.toISOString().split('T')[0]
}}
</span>
<template v-if="showCost">
<span v-if="model.cost.prompt" class="text-xs whitespace-nowrap flex items-center">
@@ -114,23 +106,23 @@ const handleEdit = () => {
<div class="flex items-center gap-1 shrink-0">
<div class="flex items-center gap-0.5">
<div v-if="hasInputModality('image')" title="Vision"
<div v-if="model.inputModalities.includes('image')" title="Vision"
class="w-4.5 h-4.5 bg-emerald/10 rounded flex items-center justify-center">
<span class="i-mynaui-image text-2.5 text-emerald"></span>
</div>
<div v-if="hasCapability('reasoning')" title="Reasoning"
<div v-if="model.capabilities.includes('reasoning')" title="Reasoning"
class="w-4.5 h-4.5 bg-[color-mix(in_srgb,_transparent_90%,_var(--reasoning-accent)_10%)] rounded flex items-center justify-center">
<span class="i-mynaui-atom text-2.5 text-[var(--reasoning-accent)]"></span>
</div>
<div v-if="hasCapability('tools')" title="Tools"
<div v-if="model.capabilities.includes('tools')" title="Tools"
class="w-4.5 h-4.5 bg-emerald/10 rounded flex items-center justify-center">
<span class="i-mynaui-tool text-2.5 text-sky"></span>
</div>
</div>
<span v-if="model.attributes.contextWindow"
<span v-if="model.contextWindow"
class="text-xs font-mono text-[var(--text-secondary)] px-1.5 py-0.5 rounded bg-[var(--bg-container)]">
{{ formatContextWindow(model.attributes.contextWindow) }}
{{ formatContextWindow(model.contextWindow) }}
</span>
<Slider v-if="showEdit" :checked="model.enabled" @click="toggleModel(model.id)" />