diff --git a/backend/apps/web/models/modelfiles.py b/backend/apps/web/models/modelfiles.py
index 4d8202db..8231d8df 100644
--- a/backend/apps/web/models/modelfiles.py
+++ b/backend/apps/web/models/modelfiles.py
@@ -12,7 +12,7 @@ from apps.web.internal.db import DB
import json
####################
-# User DB Schema
+# Modelfile DB Schema
####################
diff --git a/backend/apps/web/models/prompts.py b/backend/apps/web/models/prompts.py
new file mode 100644
index 00000000..bb0710b6
--- /dev/null
+++ b/backend/apps/web/models/prompts.py
@@ -0,0 +1,117 @@
+from pydantic import BaseModel
+from peewee import *
+from playhouse.shortcuts import model_to_dict
+from typing import List, Union, Optional
+import time
+
+from utils.utils import decode_token
+from utils.misc import get_gravatar_url
+
+from apps.web.internal.db import DB
+
+import json
+
+####################
+# Prompts DB Schema
+####################
+
+
+class Prompt(Model):
+ command = CharField(unique=True)
+ user_id = CharField()
+ title = CharField()
+ content = TextField()
+ timestamp = DateField()
+
+ class Meta:
+ database = DB
+
+
+class PromptModel(BaseModel):
+ command: str
+ user_id: str
+ title: str
+ content: str
+ timestamp: int # timestamp in epoch
+
+
+####################
+# Forms
+####################
+
+
+class PromptForm(BaseModel):
+ command: str
+ title: str
+ content: str
+
+
+class PromptsTable:
+ def __init__(self, db):
+ self.db = db
+ self.db.create_tables([Prompt])
+
+ def insert_new_prompt(
+ self, user_id: str, form_data: PromptForm
+ ) -> Optional[PromptModel]:
+ prompt = PromptModel(
+ **{
+ "user_id": user_id,
+ "command": form_data.command,
+ "title": form_data.title,
+ "content": form_data.content,
+ "timestamp": int(time.time()),
+ }
+ )
+
+ try:
+ result = Prompt.create(**prompt.model_dump())
+ if result:
+ return prompt
+ else:
+ return None
+ except:
+ return None
+
+ def get_prompt_by_command(self, command: str) -> Optional[PromptModel]:
+ try:
+ prompt = Prompt.get(Prompt.command == command)
+ return PromptModel(**model_to_dict(prompt))
+ except:
+ return None
+
+ def get_prompts(self) -> List[PromptModel]:
+ return [
+ PromptModel(**model_to_dict(prompt))
+ for prompt in Prompt.select()
+ # .limit(limit).offset(skip)
+ ]
+
+ def update_prompt_by_command(
+ self, command: str, form_data: PromptForm
+ ) -> Optional[PromptModel]:
+ try:
+ query = Prompt.update(
+ title=form_data.title,
+ content=form_data.content,
+ timestamp=int(time.time()),
+ ).where(Prompt.command == command)
+
+ query.execute()
+
+ prompt = Prompt.get(Prompt.command == command)
+ return PromptModel(**model_to_dict(prompt))
+ except:
+ return None
+
+ def delete_prompt_by_command(self, command: str) -> bool:
+ try:
+ query = Prompt.delete().where((Prompt.command == command))
+ query.execute() # Remove the rows, return number of rows removed.
+
+ return True
+ except:
+ return False
+
+
+Prompts = PromptsTable(DB)
diff --git a/src/lib/components/chat/MessageInput/PromptCommands.svelte b/src/lib/components/chat/MessageInput/PromptCommands.svelte
index 2b41bac0..865dc36a 100644
--- a/src/lib/components/chat/MessageInput/PromptCommands.svelte
+++ b/src/lib/components/chat/MessageInput/PromptCommands.svelte
@@ -1,158 +1,13 @@
+
+
+
+
+
+
+
+
+ {#if $prompts.length === 0}
+
+ {:else}
+ {#each $prompts.filter((p) => query === '' || p.command.includes(query)) as prompt}
+
+
+
+
+
{prompt.command}
+
+ {prompt.title}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/each}
+ {/if}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/routes/(app)/prompts/create/+page.svelte b/src/routes/(app)/prompts/create/+page.svelte
new file mode 100644
index 00000000..5cdf5940
--- /dev/null
+++ b/src/routes/(app)/prompts/create/+page.svelte
@@ -0,0 +1,224 @@
+
+
+
+
+
+
My Prompts
+
+
+
+
+
+
+
+
diff --git a/src/routes/(app)/prompts/edit/+page.svelte b/src/routes/(app)/prompts/edit/+page.svelte
new file mode 100644
index 00000000..11dec182
--- /dev/null
+++ b/src/routes/(app)/prompts/edit/+page.svelte
@@ -0,0 +1,520 @@
+
+
+
+
+
+
{
+ let reader = new FileReader();
+ reader.onload = (event) => {
+ let originalImageUrl = `${event.target.result}`;
+
+ const img = new Image();
+ img.src = originalImageUrl;
+
+ img.onload = function () {
+ const canvas = document.createElement('canvas');
+ const ctx = canvas.getContext('2d');
+
+ // Calculate the aspect ratio of the image
+ const aspectRatio = img.width / img.height;
+
+ // Calculate the new width and height to fit within 100x100
+ let newWidth, newHeight;
+ if (aspectRatio > 1) {
+ newWidth = 100 * aspectRatio;
+ newHeight = 100;
+ } else {
+ newWidth = 100;
+ newHeight = 100 / aspectRatio;
+ }
+
+ // Set the canvas size
+ canvas.width = 100;
+ canvas.height = 100;
+
+ // Calculate the position to center the image
+ const offsetX = (100 - newWidth) / 2;
+ const offsetY = (100 - newHeight) / 2;
+
+ // Draw the image on the canvas
+ ctx.drawImage(img, offsetX, offsetY, newWidth, newHeight);
+
+ // Get the base64 representation of the compressed image
+ const compressedSrc = canvas.toDataURL('image/jpeg');
+
+ // Display the compressed image
+ imageUrl = compressedSrc;
+
+ inputFiles = null;
+ };
+ };
+
+ if (
+ inputFiles &&
+ inputFiles.length > 0 &&
+ ['image/gif', 'image/jpeg', 'image/png'].includes(inputFiles[0]['type'])
+ ) {
+ reader.readAsDataURL(inputFiles[0]);
+ } else {
+ console.log(`Unsupported File Type '${inputFiles[0]['type']}'.`);
+ inputFiles = null;
+ }
+ }}
+ />
+
+
My Modelfiles
+
+
+
+
+
+
+
+