diff --git a/jsrepo.json b/jsrepo.json
index 0ed3231..1a79699 100644
--- a/jsrepo.json
+++ b/jsrepo.json
@@ -8,6 +8,7 @@
"paths": {
"*": "$lib/blocks",
"utils": "$lib/utils",
+ "ts": "$lib/utils",
"ui": "$lib/components/ui",
"actions": "$lib/actions",
"hooks": "$lib/hooks"
diff --git a/src/lib/auth.ts b/src/lib/auth.ts
index 7a96061..217cc86 100644
--- a/src/lib/auth.ts
+++ b/src/lib/auth.ts
@@ -14,5 +14,14 @@ export const auth = betterAuth({
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
},
},
+ databaseHooks: {
+ user: {
+ create: {
+ after: async ({ user }) => {
+ // TODO: automatically enable default models for the user
+ },
+ },
+ },
+ },
plugins: [],
});
diff --git a/src/lib/backend/convex/schema.ts b/src/lib/backend/convex/schema.ts
index a652632..c89c64c 100644
--- a/src/lib/backend/convex/schema.ts
+++ b/src/lib/backend/convex/schema.ts
@@ -6,14 +6,14 @@ export const providerValidator = v.union(...Object.values(Provider).map((p) => v
export default defineSchema({
user_keys: defineTable({
- user_id: v.id('users'),
+ user_id: v.string(),
provider: providerValidator,
key: v.string(),
})
.index('by_user', ['user_id'])
.index('by_provider_user', ['provider', 'user_id']),
user_enabled_models: defineTable({
- user_id: v.id('users'),
+ user_id: v.string(),
provider: providerValidator,
/** Different providers may use different ids for the same model */
model_id: v.string(),
diff --git a/src/lib/backend/convex/user_enabled_models.ts b/src/lib/backend/convex/user_enabled_models.ts
index 4bc2f47..ebdc635 100644
--- a/src/lib/backend/convex/user_enabled_models.ts
+++ b/src/lib/backend/convex/user_enabled_models.ts
@@ -1,16 +1,19 @@
-import { mutation } from './_generated/server';
+import { query, mutation } from './_generated/server';
import { v } from 'convex/values';
import { providerValidator } from './schema';
+import * as array from '../../utils/array';
-export const get = mutation({
+export const get_enabled = query({
args: {
- user_id: v.id('users'),
+ user_id: v.string(),
},
handler: async (ctx, args) => {
- return await ctx.db
+ const models = await ctx.db
.query('user_enabled_models')
.withIndex('by_user', (q) => q.eq('user_id', args.user_id))
.collect();
+
+ return array.toMap(models, (m) => [`${m.provider}:${m.model_id}`, m]);
},
});
@@ -18,7 +21,8 @@ export const set = mutation({
args: {
provider: providerValidator,
model_id: v.string(),
- user_id: v.id('users'),
+ user_id: v.string(),
+ enabled: v.boolean(),
},
handler: async (ctx, args) => {
const existing = await ctx.db
@@ -28,8 +32,15 @@ export const set = mutation({
)
.first();
- if (existing) return;
+ if (args.enabled && existing) return; // nothing to do here
- await ctx.db.insert('user_enabled_models', { ...args, pinned: null });
+ if (existing) {
+ await ctx.db.delete(existing._id);
+ } else {
+ await ctx.db.insert('user_enabled_models', {
+ ...{ ...args, enabled: undefined },
+ pinned: null,
+ });
+ }
},
});
diff --git a/src/lib/backend/convex/user_keys.ts b/src/lib/backend/convex/user_keys.ts
index 0839854..c685509 100644
--- a/src/lib/backend/convex/user_keys.ts
+++ b/src/lib/backend/convex/user_keys.ts
@@ -5,7 +5,7 @@ import { providerValidator } from './schema';
export const get = query({
args: {
- user_id: v.id('users'),
+ user_id: v.string(),
},
handler: async (ctx, args) => {
const allKeys = await ctx.db
@@ -26,7 +26,7 @@ export const get = query({
export const set = mutation({
args: {
provider: providerValidator,
- user_id: v.id('users'),
+ user_id: v.string(),
key: v.string(),
},
handler: async (ctx, args) => {
diff --git a/src/lib/components/ui/switch/index.ts b/src/lib/components/ui/switch/index.ts
new file mode 100644
index 0000000..42ac3b6
--- /dev/null
+++ b/src/lib/components/ui/switch/index.ts
@@ -0,0 +1,3 @@
+import Switch from './switch.svelte';
+
+export { Switch };
\ No newline at end of file
diff --git a/src/lib/components/ui/switch/switch.svelte b/src/lib/components/ui/switch/switch.svelte
new file mode 100644
index 0000000..a9d77db
--- /dev/null
+++ b/src/lib/components/ui/switch/switch.svelte
@@ -0,0 +1,24 @@
+
+
+
diff --git a/src/lib/utils/array.ts b/src/lib/utils/array.ts
new file mode 100644
index 0000000..9608d3f
--- /dev/null
+++ b/src/lib/utils/array.ts
@@ -0,0 +1,80 @@
+/*
+ Installed from @ieedan/std
+*/
+
+/** Maps the provided map into an array using the provided mapping function.
+ *
+ * @param map Map to be entered into an array
+ * @param fn A mapping function to transform each pair into an item
+ * @returns
+ *
+ * ## Usage
+ * ```ts
+ * console.log(map); // Map(5) { 0 => 5, 1 => 4, 2 => 3, 3 => 2, 4 => 1 }
+ *
+ * const arr = fromMap(map, (_, value) => value);
+ *
+ * console.log(arr); // [5, 4, 3, 2, 1]
+ * ```
+ */
+export function fromMap(map: Map, fn: (key: K, value: V) => T): T[] {
+ const items: T[] = [];
+
+ for (const [key, value] of map) {
+ items.push(fn(key, value));
+ }
+
+ return items;
+}
+
+/** Calculates the sum of all elements in the array based on the provided function.
+ *
+ * @param arr Array of items to be summed.
+ * @param fn Summing function
+ * @returns
+ *
+ * ## Usage
+ *
+ * ```ts
+ * const total = sum([1, 2, 3, 4, 5], (num) => num);
+ *
+ * console.log(total); // 15
+ * ```
+ */
+export function sum(arr: T[], fn: (item: T) => number): number {
+ let total = 0;
+
+ for (const item of arr) {
+ total = total + fn(item);
+ }
+
+ return total;
+}
+
+/** Maps the provided array into a map
+ *
+ * @param arr Array of items to be entered into a map
+ * @param fn A mapping function to transform each item into a key value pair
+ * @returns
+ *
+ * ## Usage
+ * ```ts
+ * const map = toMap([5, 4, 3, 2, 1], (item, i) => [i, item]);
+ *
+ * console.log(map); // Map(5) { 0 => 5, 1 => 4, 2 => 3, 3 => 2, 4 => 1 }
+ * ```
+ */
+export function toMap(
+ arr: T[],
+ fn: (item: T, index: number) => [key: string, value: V]
+): Record {
+ const map: Record = {};
+
+ for (let i = 0; i < arr.length; i++) {
+ const [key, value] = fn(arr[i], i);
+
+ map[key] = value;
+ }
+
+ return map;
+}
diff --git a/src/routes/account/api-keys/provider-card.svelte b/src/routes/account/api-keys/provider-card.svelte
index d3e6998..d207c42 100644
--- a/src/routes/account/api-keys/provider-card.svelte
+++ b/src/routes/account/api-keys/provider-card.svelte
@@ -39,7 +39,7 @@
const key = formData.get('key');
if (key === null || !session.current?.user.id) return;
- const res = await client.mutation(api.user_keys.set, {
+ await client.mutation(api.user_keys.set, {
provider,
user_id: session.current?.user.id ?? '',
key: `${key}`,
diff --git a/src/routes/account/models/+page.svelte b/src/routes/account/models/+page.svelte
index b72ab12..83df142 100644
--- a/src/routes/account/models/+page.svelte
+++ b/src/routes/account/models/+page.svelte
@@ -1,11 +1,15 @@
@@ -20,5 +24,6 @@
{#each data.openRouterModels as model}
-
+ {@const enabled = enabledModels.data?.[`${Provider.OpenRouter}:${model.id}`] !== undefined}
+
{/each}
diff --git a/src/routes/account/models/model.svelte b/src/routes/account/models/model.svelte
index 0459bda..dbeabbe 100644
--- a/src/routes/account/models/model.svelte
+++ b/src/routes/account/models/model.svelte
@@ -1,6 +1,10 @@
- {model.name}
- {showMore ? fullDescription : shortDescription ?? fullDescription}
+
+ {model.name}
+
+
+
+ {showMore ? fullDescription : (shortDescription ?? fullDescription)}
{#if shortDescription !== null}
{/if}
-
-
-
+