From 83277a42a77815e347dd7e8e85c3b0a4d1c01d25 Mon Sep 17 00:00:00 2001
From: bakanayatsu <migcarlo044@gmail.com>
Date: Sat, 20 Apr 2024 15:22:12 +0800
Subject: [PATCH 01/35] mobile responsive

---
 mikupad.html | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/mikupad.html b/mikupad.html
index 972078e..75e726d 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -10,6 +10,7 @@
   -- work.  If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
   -->
 <title>mikupad</title>
+<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0">
 <script type="importmap">
 {
 	"imports": {
@@ -884,6 +885,29 @@
 	border-top: 3px dotted var(--color-base-20);
 }
 
+.buttons #show-settings {
+	display: none;
+}
+
+.hide {
+	display: none;
+}
+
+@media (max-width: 768px) {
+  #prompt-container {
+    font-size: 1.35rem;
+	height: 96.9vh; /* There's a better way to this */
+  }
+  html.monospace-dark #sidebar {
+	width: 100%;
+    position: fixed;	
+	bottom: 0%;
+  }
+  .buttons #show-settings {
+	  display: block;
+  }
+}
+
 </style>
 <script type="module">
 
@@ -3183,6 +3207,16 @@
 			${!!tokens && html`
 				<${InputBox} label="Tokens" value=${tokens} readOnly/>`}
 			<div className="buttons">
+				<button
+					onClick=${() => {
+						toggleModal("settings");
+						document.getElementsByClassName("SelectBox")[0].classList.toggle("hide", modalState.settings);
+						document.getElementsByClassName("horz-separator")[0].classList.toggle("hide", modalState.settings);
+						for (const collapseGroup of document.getElementsByClassName("collapsible-group"))
+							collapseGroup.classList.toggle("hide", modalState.settings);
+					}}>
+					Settings
+				</button>
 				<button
 					title="Run next prediction (Ctrl + Enter)"
 					className=${cancel && !sessionEndpointConnecting ? (predictStartTokens === tokens ? 'processing' : 'completing') : ''}

From a9632f83cf9de93f36704c31daa0d34cdb216d47 Mon Sep 17 00:00:00 2001
From: bakanayatsu <migcarlo044@gmail.com>
Date: Sat, 20 Apr 2024 15:42:02 +0800
Subject: [PATCH 02/35] fix settings not properly dissapearing

---
 mikupad.html | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/mikupad.html b/mikupad.html
index 75e726d..74656b7 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -885,7 +885,7 @@
 	border-top: 3px dotted var(--color-base-20);
 }
 
-.buttons #show-settings {
+#button-settings {
 	display: none;
 }
 
@@ -903,7 +903,7 @@
     position: fixed;	
 	bottom: 0%;
   }
-  .buttons #show-settings {
+  #button-settings {
 	  display: block;
   }
 }
@@ -3208,6 +3208,7 @@
 				<${InputBox} label="Tokens" value=${tokens} readOnly/>`}
 			<div className="buttons">
 				<button
+					id="button-settings"
 					onClick=${() => {
 						toggleModal("settings");
 						document.getElementsByClassName("SelectBox")[0].classList.toggle("hide", modalState.settings);

From 7e3a4b07fd265658f0c76ef97829a1f6e928bb51 Mon Sep 17 00:00:00 2001
From: bakanayatsu <migcarlo044@gmail.com>
Date: Sat, 20 Apr 2024 16:09:14 +0800
Subject: [PATCH 03/35] changed button side

---
 mikupad.html | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/mikupad.html b/mikupad.html
index 74656b7..8ac08f2 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -3207,17 +3207,6 @@
 			${!!tokens && html`
 				<${InputBox} label="Tokens" value=${tokens} readOnly/>`}
 			<div className="buttons">
-				<button
-					id="button-settings"
-					onClick=${() => {
-						toggleModal("settings");
-						document.getElementsByClassName("SelectBox")[0].classList.toggle("hide", modalState.settings);
-						document.getElementsByClassName("horz-separator")[0].classList.toggle("hide", modalState.settings);
-						for (const collapseGroup of document.getElementsByClassName("collapsible-group"))
-							collapseGroup.classList.toggle("hide", modalState.settings);
-					}}>
-					Settings
-				</button>
 				<button
 					title="Run next prediction (Ctrl + Enter)"
 					className=${cancel && !sessionEndpointConnecting ? (predictStartTokens === tokens ? 'processing' : 'completing') : ''}
@@ -3258,6 +3247,17 @@
 						<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24"><path d="M6.974 22.957c-10.957-11.421 2.326-20.865 10.384-13.309l-2.464 2.352h9.106v-8.947l-2.232 2.229c-14.794-13.203-31.51 7.051-14.794 17.675z" fill="var(--color-light)"/></svg>
 					</button>
 				</div>
+				<button
+					id="button-settings"
+					onClick=${() => {
+						toggleModal("settings");
+						document.getElementsByClassName("SelectBox")[0].classList.toggle("hide", modalState.settings);
+						document.getElementsByClassName("horz-separator")[0].classList.toggle("hide", modalState.settings);
+						for (const collapseGroup of document.getElementsByClassName("collapsible-group"))
+							collapseGroup.classList.toggle("hide", modalState.settings);
+					}}>
+					Settings
+				</button>
 			</div>
 			${!!lastError && html`
 				<span className="error-text">${lastError}</span>`}

From cfab34683930505fb1d952a162640983bf3e422f Mon Sep 17 00:00:00 2001
From: bakanayatsu <migcarlo044@gmail.com>
Date: Sat, 20 Apr 2024 16:24:26 +0800
Subject: [PATCH 04/35] correct spacing

---
 mikupad.html | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/mikupad.html b/mikupad.html
index 8ac08f2..f884786 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -894,18 +894,18 @@
 }
 
 @media (max-width: 768px) {
-  #prompt-container {
-    font-size: 1.35rem;
-	height: 96.9vh; /* There's a better way to this */
-  }
-  html.monospace-dark #sidebar {
-	width: 100%;
-    position: fixed;	
-	bottom: 0%;
-  }
-  #button-settings {
-	  display: block;
-  }
+	#prompt-container {
+    	font-size: 1.35rem;
+		height: 96.9vh; /* There's a better way to this */
+	}
+	html.monospace-dark #sidebar {
+		width: 100%;
+		position: fixed;
+		bottom: 0%;
+	}
+	#button-settings {
+		display: block;
+	}
 }
 
 </style>

From d6deef9da1b277104a7ba85c1b20506eff176f7b Mon Sep 17 00:00:00 2001
From: bakanayatsu <migcarlo044@gmail.com>
Date: Mon, 20 May 2024 16:28:29 +0800
Subject: [PATCH 05/35] now works on any font

---
 mikupad.html | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/mikupad.html b/mikupad.html
index 32cd5a6..aabf5f3 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -1006,17 +1006,20 @@
 #button-settings {
 	display: none;
 }
-
 .hide {
 	display: none;
 }
 
-@media (max-width: 768px) {
+@media (max-width: 767.98px) {
 	#prompt-container {
     	font-size: 1.35rem;
 		height: 96.9vh; /* There's a better way to this */
 	}
-	html.monospace-dark #sidebar {
+	#prompt-container {
+		width: 100%;
+		max-width: 100%;
+	}
+	#sidebar {
 		width: 100%;
 		position: fixed;
 		bottom: 0%;

From a56d374725311e67fd93176ef1091ce99c802dba Mon Sep 17 00:00:00 2001
From: bakanayatsu <migcarlo044@gmail.com>
Date: Mon, 20 May 2024 16:51:20 +0800
Subject: [PATCH 06/35] fixed right margin and font size

---
 mikupad.html | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/mikupad.html b/mikupad.html
index aabf5f3..a786f85 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -1011,8 +1011,11 @@
 }
 
 @media (max-width: 767.98px) {
+	body {
+		flex-direction: column;
+	}
 	#prompt-container {
-    	font-size: 1.35rem;
+    	font-size: 1.125rem;
 		height: 96.9vh; /* There's a better way to this */
 	}
 	#prompt-container {
@@ -1020,8 +1023,12 @@
 		max-width: 100%;
 	}
 	#sidebar {
-		width: 100%;
+		width: auto;
 		position: fixed;
+		left: 0;
+		right: 0;
+		bottom: 0;
+	}
 		bottom: 0%;
 	}
 	#button-settings {

From e5d88769d3ebe4a25a5d18d5a16aea2791345189 Mon Sep 17 00:00:00 2001
From: bakanayatsu <migcarlo044@gmail.com>
Date: Mon, 20 May 2024 16:52:14 +0800
Subject: [PATCH 07/35] remove some accidents

---
 mikupad.html | 2 --
 1 file changed, 2 deletions(-)

diff --git a/mikupad.html b/mikupad.html
index a786f85..54ea5ae 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -1028,8 +1028,6 @@
 		left: 0;
 		right: 0;
 		bottom: 0;
-	}
-		bottom: 0%;
 	}
 	#button-settings {
 		display: block;

From 827ac6ec029b767943c4dea9a989039b28ada944 Mon Sep 17 00:00:00 2001
From: bakanayatsu <migcarlo044@gmail.com>
Date: Mon, 20 May 2024 16:59:52 +0800
Subject: [PATCH 08/35] fixed sidebar going through the roof

---
 mikupad.html | 1 +
 1 file changed, 1 insertion(+)

diff --git a/mikupad.html b/mikupad.html
index 54ea5ae..d3c39fa 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -1024,6 +1024,7 @@
 	}
 	#sidebar {
 		width: auto;
+		max-height: calc(93vh - 8px);
 		position: fixed;
 		left: 0;
 		right: 0;

From ecab8acd28e5282c757074a46c6ef438fbac5e3e Mon Sep 17 00:00:00 2001
From: bakanayatsu <migcarlo044@gmail.com>
Date: Mon, 20 May 2024 17:04:44 +0800
Subject: [PATCH 09/35] now works with monospace-dark and nockoffAI theme

---
 mikupad.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mikupad.html b/mikupad.html
index d3c39fa..96f82ee 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -1022,7 +1022,7 @@
 		width: 100%;
 		max-width: 100%;
 	}
-	#sidebar {
+	#sidebar, html.monospace-dark #sidebar, html.nockoffAI #sidebar {
 		width: auto;
 		max-height: calc(93vh - 8px);
 		position: fixed;

From 54804a02a40387795e416e014c28becc92a2b7a8 Mon Sep 17 00:00:00 2001
From: bakanayatsu <migcarlo044@gmail.com>
Date: Mon, 20 May 2024 20:59:00 +0800
Subject: [PATCH 10/35] made settings into svg gear icon

---
 mikupad.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mikupad.html b/mikupad.html
index 96f82ee..a3a75d4 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -4154,7 +4154,7 @@
 						for (const collapseGroup of document.getElementsByClassName("collapsible-group"))
 							collapseGroup.classList.toggle("hide", modalState.settings);
 					}}>
-					Settings
+					<svg transform="translate(0, 2)" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 512 512"><path d="M495.9 166.6c3.2 8.7 .5 18.4-6.4 24.6l-43.3 39.4c1.1 8.3 1.7 16.8 1.7 25.4s-.6 17.1-1.7 25.4l43.3 39.4c6.9 6.2 9.6 15.9 6.4 24.6c-4.4 11.9-9.7 23.3-15.8 34.3l-4.7 8.1c-6.6 11-14 21.4-22.1 31.2c-5.9 7.2-15.7 9.6-24.5 6.8l-55.7-17.7c-13.4 10.3-28.2 18.9-44 25.4l-12.5 57.1c-2 9.1-9 16.3-18.2 17.8c-13.8 2.3-28 3.5-42.5 3.5s-28.7-1.2-42.5-3.5c-9.2-1.5-16.2-8.7-18.2-17.8l-12.5-57.1c-15.8-6.5-30.6-15.1-44-25.4L83.1 425.9c-8.8 2.8-18.6 .3-24.5-6.8c-8.1-9.8-15.5-20.2-22.1-31.2l-4.7-8.1c-6.1-11-11.4-22.4-15.8-34.3c-3.2-8.7-.5-18.4 6.4-24.6l43.3-39.4C64.6 273.1 64 264.6 64 256s.6-17.1 1.7-25.4L22.4 191.2c-6.9-6.2-9.6-15.9-6.4-24.6c4.4-11.9 9.7-23.3 15.8-34.3l4.7-8.1c6.6-11 14-21.4 22.1-31.2c5.9-7.2 15.7-9.6 24.5-6.8l55.7 17.7c13.4-10.3 28.2-18.9 44-25.4l12.5-57.1c2-9.1 9-16.3 18.2-17.8C227.3 1.2 241.5 0 256 0s28.7 1.2 42.5 3.5c9.2 1.5 16.2 8.7 18.2 17.8l12.5 57.1c15.8 6.5 30.6 15.1 44 25.4l55.7-17.7c8.8-2.8 18.6-.3 24.5 6.8c8.1 9.8 15.5 20.2 22.1 31.2l4.7 8.1c6.1 11 11.4 22.4 15.8 34.3zM256 336a80 80 0 1 0 0-160 80 80 0 1 0 0 160z" fill="var(--color-light)"/></svg>
 				</button>
 			</div>
 			${!!lastError && html`

From 494f604c997ccf3041ca73a54cb8f425808f80b2 Mon Sep 17 00:00:00 2001
From: bakanayatsu <migcarlo044@gmail.com>
Date: Mon, 20 May 2024 21:23:52 +0800
Subject: [PATCH 11/35] remove useless css values

---
 mikupad.html | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/mikupad.html b/mikupad.html
index a3a75d4..2a57343 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -1014,10 +1014,6 @@
 	body {
 		flex-direction: column;
 	}
-	#prompt-container {
-    	font-size: 1.125rem;
-		height: 96.9vh; /* There's a better way to this */
-	}
 	#prompt-container {
 		width: 100%;
 		max-width: 100%;

From 50ff9c7a9b52fa4baf05fa2cab13797985af987a Mon Sep 17 00:00:00 2001
From: bakanayatsu <migcarlo044@gmail.com>
Date: Mon, 20 May 2024 22:05:40 +0800
Subject: [PATCH 12/35] shorten

---
 mikupad.html | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/mikupad.html b/mikupad.html
index 2a57343..e686aaf 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -1003,10 +1003,7 @@
 	transform: translate(-50%, -50%);
 } 
 
-#button-settings {
-	display: none;
-}
-.hide {
+#button-settings, .hide {
 	display: none;
 }
 
@@ -3072,7 +3069,7 @@
 			[modalKey]: false,
 		}));
 	};
-
+	
 	const promptText = useMemo(() => joinPrompt(promptChunks), [promptChunks]);
 
 	// compute separately as I imagine this can get expensive

From bf126ea4a74c12e50d77aaba868e1820f8b33b7f Mon Sep 17 00:00:00 2001
From: bakanayatsu <migcarlo044@gmail.com>
Date: Mon, 20 May 2024 22:09:00 +0800
Subject: [PATCH 13/35] fix settings button needing double click to close

---
 mikupad.html | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/mikupad.html b/mikupad.html
index e686aaf..732e5e8 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -4142,10 +4142,10 @@
 					id="button-settings"
 					onClick=${() => {
 						toggleModal("settings");
-						document.getElementsByClassName("SelectBox")[0].classList.toggle("hide", modalState.settings);
-						document.getElementsByClassName("horz-separator")[0].classList.toggle("hide", modalState.settings);
+						document.getElementsByClassName("SelectBox")[0].classList.toggle("hide", !modalState.settings);
+						document.getElementsByClassName("horz-separator")[0].classList.toggle("hide", !modalState.settings);
 						for (const collapseGroup of document.getElementsByClassName("collapsible-group"))
-							collapseGroup.classList.toggle("hide", modalState.settings);
+							collapseGroup.classList.toggle("hide", !modalState.settings);
 					}}>
 					<svg transform="translate(0, 2)" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 512 512"><path d="M495.9 166.6c3.2 8.7 .5 18.4-6.4 24.6l-43.3 39.4c1.1 8.3 1.7 16.8 1.7 25.4s-.6 17.1-1.7 25.4l43.3 39.4c6.9 6.2 9.6 15.9 6.4 24.6c-4.4 11.9-9.7 23.3-15.8 34.3l-4.7 8.1c-6.6 11-14 21.4-22.1 31.2c-5.9 7.2-15.7 9.6-24.5 6.8l-55.7-17.7c-13.4 10.3-28.2 18.9-44 25.4l-12.5 57.1c-2 9.1-9 16.3-18.2 17.8c-13.8 2.3-28 3.5-42.5 3.5s-28.7-1.2-42.5-3.5c-9.2-1.5-16.2-8.7-18.2-17.8l-12.5-57.1c-15.8-6.5-30.6-15.1-44-25.4L83.1 425.9c-8.8 2.8-18.6 .3-24.5-6.8c-8.1-9.8-15.5-20.2-22.1-31.2l-4.7-8.1c-6.1-11-11.4-22.4-15.8-34.3c-3.2-8.7-.5-18.4 6.4-24.6l43.3-39.4C64.6 273.1 64 264.6 64 256s.6-17.1 1.7-25.4L22.4 191.2c-6.9-6.2-9.6-15.9-6.4-24.6c4.4-11.9 9.7-23.3 15.8-34.3l4.7-8.1c6.6-11 14-21.4 22.1-31.2c5.9-7.2 15.7-9.6 24.5-6.8l55.7 17.7c13.4-10.3 28.2-18.9 44-25.4l12.5-57.1c2-9.1 9-16.3 18.2-17.8C227.3 1.2 241.5 0 256 0s28.7 1.2 42.5 3.5c9.2 1.5 16.2 8.7 18.2 17.8l12.5 57.1c15.8 6.5 30.6 15.1 44 25.4l55.7-17.7c8.8-2.8 18.6-.3 24.5 6.8c8.1 9.8 15.5 20.2 22.1 31.2l4.7 8.1c6.1 11 11.4 22.4 15.8 34.3zM256 336a80 80 0 1 0 0-160 80 80 0 1 0 0 160z" fill="var(--color-light)"/></svg>
 				</button>

From f68bf5152649fb01106ecb2f8b3da8024b294cfa Mon Sep 17 00:00:00 2001
From: bakanayatsu <migcarlo044@gmail.com>
Date: Mon, 20 May 2024 22:10:44 +0800
Subject: [PATCH 14/35] extra tab...

---
 mikupad.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mikupad.html b/mikupad.html
index 732e5e8..df1b950 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -3069,7 +3069,7 @@
 			[modalKey]: false,
 		}));
 	};
-	
+
 	const promptText = useMemo(() => joinPrompt(promptChunks), [promptChunks]);
 
 	// compute separately as I imagine this can get expensive

From 4914910a2d3e95c296becee023872c563e1f3c31 Mon Sep 17 00:00:00 2001
From: lmg-anon <139719567+lmg-anon@users.noreply.github.com>
Date: Tue, 21 May 2024 01:48:46 -0300
Subject: [PATCH 15/35] Don't add the instruct suffix if it has already been
 added

---
 mikupad.html | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/mikupad.html b/mikupad.html
index 3ca1e21..a3a6ca5 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -3818,11 +3818,16 @@
 			setPredictStartTokens(tokenCount);
 
 			// Chat Mode
-			if (chatMode && !restartedPredict) {
+			if (chatMode && !restartedPredict && templates[selectedTemplate]) {
 				// add user EOT template (instruct suffix) if not switch completion
-				const eotUser = templates[selectedTemplate]?.instSuf.replace(/\\n/g, '\n')
-				setPromptChunks(p => [...p, { type: 'user', content: eotUser }])
-				prompt += `${eotUser}`
+				const { instSuf, instPre } = templates[selectedTemplate];
+				const instSufIndex = instSuf ? prompt.lastIndexOf(instSuf) : -1;
+				const instPreIndex = instPre ? prompt.lastIndexOf(instPre) : -1;
+				if (instSufIndex <= instPreIndex) {
+					const eotUser = instSuf.replace(/\\n/g, '\n')
+					setPromptChunks(p => [...p, { type: 'user', content: eotUser }])
+					prompt += eotUser;
+				}
 			}
 			setRestartedPredict(false)
 

From 9f8d62107eff77fab515741eef22556a3a93f920 Mon Sep 17 00:00:00 2001
From: lmg-anon <139719567+lmg-anon@users.noreply.github.com>
Date: Tue, 21 May 2024 14:06:56 -0300
Subject: [PATCH 16/35] Replace line breaks in template

---
 mikupad.html | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/mikupad.html b/mikupad.html
index a3a6ca5..6b6158d 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -3422,6 +3422,12 @@
 	return replacedString;
 }
 
+function replaceNewlines(template) {
+	return Object.fromEntries(
+		Object.entries(template).map(([key, value]) => [key, value.replaceAll("\\n", "\n")])
+	);
+}
+
 function useSessionState(sessionStorage, name, initialState) {
 	const savedState = useMemo(() => {
 		try {
@@ -3820,13 +3826,12 @@
 			// Chat Mode
 			if (chatMode && !restartedPredict && templates[selectedTemplate]) {
 				// add user EOT template (instruct suffix) if not switch completion
-				const { instSuf, instPre } = templates[selectedTemplate];
+				const { instSuf, instPre } = replaceNewlines(templates[selectedTemplate]);
 				const instSufIndex = instSuf ? prompt.lastIndexOf(instSuf) : -1;
 				const instPreIndex = instPre ? prompt.lastIndexOf(instPre) : -1;
 				if (instSufIndex <= instPreIndex) {
-					const eotUser = instSuf.replace(/\\n/g, '\n')
-					setPromptChunks(p => [...p, { type: 'user', content: eotUser }])
-					prompt += eotUser;
+					setPromptChunks(p => [...p, { type: 'user', content: instSuf }])
+					prompt += instSuf;
 				}
 			}
 			setRestartedPredict(false)

From 465312f079c08f63ef6b0cd52fef25586acf6564 Mon Sep 17 00:00:00 2001
From: bakanayatsu <migcarlo044@gmail.com>
Date: Wed, 22 May 2024 02:21:24 +0800
Subject: [PATCH 17/35] hide settings on start & show settings on desktop mode
 via resize event listener

---
 mikupad.html | 29 +++++++++++++++++++++++------
 1 file changed, 23 insertions(+), 6 deletions(-)

diff --git a/mikupad.html b/mikupad.html
index df1b950..daf2351 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -1003,7 +1003,7 @@
 	transform: translate(-50%, -50%);
 } 
 
-#button-settings, .hide {
+#button-settings {
 	display: none;
 }
 
@@ -1014,6 +1014,7 @@
 	#prompt-container {
 		width: 100%;
 		max-width: 100%;
+		border: none !important;
 	}
 	#sidebar, html.monospace-dark #sidebar, html.nockoffAI #sidebar {
 		width: auto;
@@ -1023,6 +1024,9 @@
 		right: 0;
 		bottom: 0;
 	}
+	.SelectBox, .horz-separator, .collapsible-group {
+		display: none;
+	}
 	#button-settings {
 		display: block;
 	}
@@ -3855,6 +3859,23 @@
 		showProbs && promptChunks[currentPromptChunk?.index]?.completion_probabilities?.[0]?.probs,
 		[promptChunks, currentPromptChunk, showProbs]);
 
+	const toggleSettings = () => {
+		toggleModal("settings");
+		document.getElementsByClassName("SelectBox")[0].style.display = modalState.settings ? "none" : "block";
+		document.getElementsByClassName("horz-separator")[0].style.display = modalState.settings ? "none" : "block";
+		for (const collapseGroup of document.getElementsByClassName("collapsible-group"))
+			collapseGroup.style.display = modalState.settings ? "none" : "block";
+	}
+	function updateSize() {
+		if (window.innerWidth > 767.98 && !modalState.settings) {
+			toggleSettings();
+		}
+	}
+	let timeout = false;
+	window.addEventListener('resize', () => {
+		clearTimeout(timeout);
+		timeout = setTimeout(updateSize, 100);
+	});
 	return html`
 		<div id="prompt-container" onMouseMove=${onPromptMouseMove}>
 			<button
@@ -4141,11 +4162,7 @@
 				<button
 					id="button-settings"
 					onClick=${() => {
-						toggleModal("settings");
-						document.getElementsByClassName("SelectBox")[0].classList.toggle("hide", !modalState.settings);
-						document.getElementsByClassName("horz-separator")[0].classList.toggle("hide", !modalState.settings);
-						for (const collapseGroup of document.getElementsByClassName("collapsible-group"))
-							collapseGroup.classList.toggle("hide", !modalState.settings);
+						toggleSettings();
 					}}>
 					<svg transform="translate(0, 2)" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 512 512"><path d="M495.9 166.6c3.2 8.7 .5 18.4-6.4 24.6l-43.3 39.4c1.1 8.3 1.7 16.8 1.7 25.4s-.6 17.1-1.7 25.4l43.3 39.4c6.9 6.2 9.6 15.9 6.4 24.6c-4.4 11.9-9.7 23.3-15.8 34.3l-4.7 8.1c-6.6 11-14 21.4-22.1 31.2c-5.9 7.2-15.7 9.6-24.5 6.8l-55.7-17.7c-13.4 10.3-28.2 18.9-44 25.4l-12.5 57.1c-2 9.1-9 16.3-18.2 17.8c-13.8 2.3-28 3.5-42.5 3.5s-28.7-1.2-42.5-3.5c-9.2-1.5-16.2-8.7-18.2-17.8l-12.5-57.1c-15.8-6.5-30.6-15.1-44-25.4L83.1 425.9c-8.8 2.8-18.6 .3-24.5-6.8c-8.1-9.8-15.5-20.2-22.1-31.2l-4.7-8.1c-6.1-11-11.4-22.4-15.8-34.3c-3.2-8.7-.5-18.4 6.4-24.6l43.3-39.4C64.6 273.1 64 264.6 64 256s.6-17.1 1.7-25.4L22.4 191.2c-6.9-6.2-9.6-15.9-6.4-24.6c4.4-11.9 9.7-23.3 15.8-34.3l4.7-8.1c6.6-11 14-21.4 22.1-31.2c5.9-7.2 15.7-9.6 24.5-6.8l55.7 17.7c13.4-10.3 28.2-18.9 44-25.4l12.5-57.1c2-9.1 9-16.3 18.2-17.8C227.3 1.2 241.5 0 256 0s28.7 1.2 42.5 3.5c9.2 1.5 16.2 8.7 18.2 17.8l12.5 57.1c15.8 6.5 30.6 15.1 44 25.4l55.7-17.7c8.8-2.8 18.6-.3 24.5 6.8c8.1 9.8 15.5 20.2 22.1 31.2l4.7 8.1c6.1 11 11.4 22.4 15.8 34.3zM256 336a80 80 0 1 0 0-160 80 80 0 1 0 0 160z" fill="var(--color-light)"/></svg>
 				</button>

From 65eec04f987cac86c083b37622ef2df239085790 Mon Sep 17 00:00:00 2001
From: bakanayatsu <migcarlo044@gmail.com>
Date: Wed, 22 May 2024 02:27:09 +0800
Subject: [PATCH 18/35] add bottom margin to prompt container in mobile view

---
 mikupad.html | 1 +
 1 file changed, 1 insertion(+)

diff --git a/mikupad.html b/mikupad.html
index daf2351..1f143f4 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -1014,6 +1014,7 @@
 	#prompt-container {
 		width: 100%;
 		max-width: 100%;
+		margin-bottom: 28px;
 		border: none !important;
 	}
 	#sidebar, html.monospace-dark #sidebar, html.nockoffAI #sidebar {

From 47a9b0e7d6bf0e059030b67d3c92a470abb7e656 Mon Sep 17 00:00:00 2001
From: bakanayatsu <migcarlo044@gmail.com>
Date: Wed, 22 May 2024 02:32:29 +0800
Subject: [PATCH 19/35] add comments

---
 mikupad.html | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/mikupad.html b/mikupad.html
index 1f143f4..23efa38 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -3868,12 +3868,14 @@
 			collapseGroup.style.display = modalState.settings ? "none" : "block";
 	}
 	function updateSize() {
+		// Show sidebar on desktop if it was hidden just before
 		if (window.innerWidth > 767.98 && !modalState.settings) {
 			toggleSettings();
 		}
 	}
 	let timeout = false;
 	window.addEventListener('resize', () => {
+		// Without this delay, the cpu usage is high and would lag for some reason
 		clearTimeout(timeout);
 		timeout = setTimeout(updateSize, 100);
 	});

From c83d6695856bf44e822b1b9ff3fe58a0e15f5c0c Mon Sep 17 00:00:00 2001
From: bakanayatsu <migcarlo044@gmail.com>
Date: Wed, 22 May 2024 02:33:56 +0800
Subject: [PATCH 20/35] minor comment specify

---
 mikupad.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mikupad.html b/mikupad.html
index 23efa38..077ca0b 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -3875,7 +3875,7 @@
 	}
 	let timeout = false;
 	window.addEventListener('resize', () => {
-		// Without this delay, the cpu usage is high and would lag for some reason
+		// Without this delay, the cpu usage is high when resizing window and would lag for some reason (useful for debugging)
 		clearTimeout(timeout);
 		timeout = setTimeout(updateSize, 100);
 	});

From abea415a134740fae8af12608a2cd69ed07cfa47 Mon Sep 17 00:00:00 2001
From: bakanayatsu <migcarlo044@gmail.com>
Date: Wed, 22 May 2024 02:39:09 +0800
Subject: [PATCH 21/35] comment on css

---
 mikupad.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mikupad.html b/mikupad.html
index 077ca0b..914584e 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -1015,7 +1015,7 @@
 		width: 100%;
 		max-width: 100%;
 		margin-bottom: 28px;
-		border: none !important;
+		border: none !important; /* put this here because for some reason, something adds "border-right: 2px dotted transparent;border-left: 2px dotted transparent;" to prompt-container whenever this element is clicked*/
 	}
 	#sidebar, html.monospace-dark #sidebar, html.nockoffAI #sidebar {
 		width: auto;

From 7fb3ce541e2999525fb19a0741beb8e29e61486a Mon Sep 17 00:00:00 2001
From: bakanayatsu <migcarlo044@gmail.com>
Date: Wed, 22 May 2024 16:46:40 +0800
Subject: [PATCH 22/35] actually no need for resize eventlistener lol

---
 mikupad.html | 19 +++++++------------
 1 file changed, 7 insertions(+), 12 deletions(-)

diff --git a/mikupad.html b/mikupad.html
index 914584e..1ca5dd5 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -1033,6 +1033,12 @@
 	}
 }
 
+@media (min-width: 767.98px) {
+	.SelectBox, .horz-separator, .collapsible-group {
+		display: block !important;
+	}
+}
+
 </style>
 <script type="module">
 
@@ -3867,18 +3873,7 @@
 		for (const collapseGroup of document.getElementsByClassName("collapsible-group"))
 			collapseGroup.style.display = modalState.settings ? "none" : "block";
 	}
-	function updateSize() {
-		// Show sidebar on desktop if it was hidden just before
-		if (window.innerWidth > 767.98 && !modalState.settings) {
-			toggleSettings();
-		}
-	}
-	let timeout = false;
-	window.addEventListener('resize', () => {
-		// Without this delay, the cpu usage is high when resizing window and would lag for some reason (useful for debugging)
-		clearTimeout(timeout);
-		timeout = setTimeout(updateSize, 100);
-	});
+
 	return html`
 		<div id="prompt-container" onMouseMove=${onPromptMouseMove}>
 			<button

From fa21256cb328429a496000627d3e0e229d488117 Mon Sep 17 00:00:00 2001
From: bakanayatsu <migcarlo044@gmail.com>
Date: Wed, 22 May 2024 16:47:47 +0800
Subject: [PATCH 23/35] refactor

---
 mikupad.html | 14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/mikupad.html b/mikupad.html
index 1ca5dd5..b2e193c 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -3866,14 +3866,6 @@
 		showProbs && promptChunks[currentPromptChunk?.index]?.completion_probabilities?.[0]?.probs,
 		[promptChunks, currentPromptChunk, showProbs]);
 
-	const toggleSettings = () => {
-		toggleModal("settings");
-		document.getElementsByClassName("SelectBox")[0].style.display = modalState.settings ? "none" : "block";
-		document.getElementsByClassName("horz-separator")[0].style.display = modalState.settings ? "none" : "block";
-		for (const collapseGroup of document.getElementsByClassName("collapsible-group"))
-			collapseGroup.style.display = modalState.settings ? "none" : "block";
-	}
-
 	return html`
 		<div id="prompt-container" onMouseMove=${onPromptMouseMove}>
 			<button
@@ -4160,7 +4152,11 @@
 				<button
 					id="button-settings"
 					onClick=${() => {
-						toggleSettings();
+						toggleModal("settings");
+						document.getElementsByClassName("SelectBox")[0].style.display = modalState.settings ? "none" : "block";
+						document.getElementsByClassName("horz-separator")[0].style.display = modalState.settings ? "none" : "block";
+						for (const collapseGroup of document.getElementsByClassName("collapsible-group"))
+							collapseGroup.style.display = modalState.settings ? "none" : "block";
 					}}>
 					<svg transform="translate(0, 2)" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 512 512"><path d="M495.9 166.6c3.2 8.7 .5 18.4-6.4 24.6l-43.3 39.4c1.1 8.3 1.7 16.8 1.7 25.4s-.6 17.1-1.7 25.4l43.3 39.4c6.9 6.2 9.6 15.9 6.4 24.6c-4.4 11.9-9.7 23.3-15.8 34.3l-4.7 8.1c-6.6 11-14 21.4-22.1 31.2c-5.9 7.2-15.7 9.6-24.5 6.8l-55.7-17.7c-13.4 10.3-28.2 18.9-44 25.4l-12.5 57.1c-2 9.1-9 16.3-18.2 17.8c-13.8 2.3-28 3.5-42.5 3.5s-28.7-1.2-42.5-3.5c-9.2-1.5-16.2-8.7-18.2-17.8l-12.5-57.1c-15.8-6.5-30.6-15.1-44-25.4L83.1 425.9c-8.8 2.8-18.6 .3-24.5-6.8c-8.1-9.8-15.5-20.2-22.1-31.2l-4.7-8.1c-6.1-11-11.4-22.4-15.8-34.3c-3.2-8.7-.5-18.4 6.4-24.6l43.3-39.4C64.6 273.1 64 264.6 64 256s.6-17.1 1.7-25.4L22.4 191.2c-6.9-6.2-9.6-15.9-6.4-24.6c4.4-11.9 9.7-23.3 15.8-34.3l4.7-8.1c6.6-11 14-21.4 22.1-31.2c5.9-7.2 15.7-9.6 24.5-6.8l55.7 17.7c13.4-10.3 28.2-18.9 44-25.4l12.5-57.1c2-9.1 9-16.3 18.2-17.8C227.3 1.2 241.5 0 256 0s28.7 1.2 42.5 3.5c9.2 1.5 16.2 8.7 18.2 17.8l12.5 57.1c15.8 6.5 30.6 15.1 44 25.4l55.7-17.7c8.8-2.8 18.6-.3 24.5 6.8c8.1 9.8 15.5 20.2 22.1 31.2l4.7 8.1c6.1 11 11.4 22.4 15.8 34.3zM256 336a80 80 0 1 0 0-160 80 80 0 1 0 0 160z" fill="var(--color-light)"/></svg>
 				</button>

From db1a70404a921f630cd06b33c01a89348bf3c1cd Mon Sep 17 00:00:00 2001
From: bakanayatsu <migcarlo044@gmail.com>
Date: Wed, 22 May 2024 18:32:32 +0800
Subject: [PATCH 24/35] change margin-bottom to the height of the sidebar
 dynamically

---
 mikupad.html | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/mikupad.html b/mikupad.html
index b2e193c..9c365f6 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -1014,7 +1014,6 @@
 	#prompt-container {
 		width: 100%;
 		max-width: 100%;
-		margin-bottom: 28px;
 		border: none !important; /* put this here because for some reason, something adds "border-right: 2px dotted transparent;border-left: 2px dotted transparent;" to prompt-container whenever this element is clicked*/
 	}
 	#sidebar, html.monospace-dark #sidebar, html.nockoffAI #sidebar {
@@ -3866,8 +3865,20 @@
 		showProbs && promptChunks[currentPromptChunk?.index]?.completion_probabilities?.[0]?.probs,
 		[promptChunks, currentPromptChunk, showProbs]);
 
+	const sidebar = useRef(null);
+	const [height, setHeight] = useState(100);
+	useEffect(() => {
+		setHeight(sidebar.current.scrollHeight);
+		const observer = new SVResizeObserver(() => {
+			setHeight(sidebar.current.scrollHeight);
+			console.log(sidebar.current.scrollHeight);
+		});
+		observer.observe(sidebar.current);
+		return () => observer.disconnect();
+	});
+
 	return html`
-		<div id="prompt-container" onMouseMove=${onPromptMouseMove}>
+		<div id="prompt-container" onMouseMove=${onPromptMouseMove} style=${{ 'margin-bottom': height + 'px' }}>
 			<button
 				className="textAreaSettings"
 				onClick=${() => toggleModal("prompt")}>
@@ -3908,7 +3919,7 @@
 						<div className="prob">${(prob.prob * 100).toFixed(2)}%</div>
 					</button>`)}
 			</div>` : null}
-		<div id="sidebar">
+		<div id="sidebar" ref=${sidebar} style=${{ 'max-height': ''}}>
 			<${SelectBox}
 				label="Theme"
 				value=${theme}

From ccbab66308f3f2028f7fd0d8638f7bdbcab92cc0 Mon Sep 17 00:00:00 2001
From: bakanayatsu <migcarlo044@gmail.com>
Date: Wed, 22 May 2024 18:36:13 +0800
Subject: [PATCH 25/35] set 0 to 100, woops

---
 mikupad.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mikupad.html b/mikupad.html
index 9c365f6..fce5012 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -3866,7 +3866,7 @@
 		[promptChunks, currentPromptChunk, showProbs]);
 
 	const sidebar = useRef(null);
-	const [height, setHeight] = useState(100);
+	const [height, setHeight] = useState(0);
 	useEffect(() => {
 		setHeight(sidebar.current.scrollHeight);
 		const observer = new SVResizeObserver(() => {

From b94a66a7346d9dfe7954d83f265e0ed91d3ece23 Mon Sep 17 00:00:00 2001
From: bakanayatsu <migcarlo044@gmail.com>
Date: Wed, 22 May 2024 18:48:48 +0800
Subject: [PATCH 26/35] added condition for bottom margin on desktop mode

---
 mikupad.html | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/mikupad.html b/mikupad.html
index fce5012..a3c44e7 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -3867,18 +3867,19 @@
 
 	const sidebar = useRef(null);
 	const [height, setHeight] = useState(0);
+	const [isMobile, setIsMobile] = useState(false);
 	useEffect(() => {
 		setHeight(sidebar.current.scrollHeight);
 		const observer = new SVResizeObserver(() => {
+			setIsMobile(window.innerWidth < 767.8);
 			setHeight(sidebar.current.scrollHeight);
-			console.log(sidebar.current.scrollHeight);
 		});
 		observer.observe(sidebar.current);
 		return () => observer.disconnect();
 	});
 
 	return html`
-		<div id="prompt-container" onMouseMove=${onPromptMouseMove} style=${{ 'margin-bottom': height + 'px' }}>
+		<div id="prompt-container" onMouseMove=${onPromptMouseMove} style=${{ 'margin-bottom': isMobile ? height + 'px' : 0 }}>
 			<button
 				className="textAreaSettings"
 				onClick=${() => toggleModal("prompt")}>

From fc53d98dcea1157383c4659fe3cdfc40313b47ab Mon Sep 17 00:00:00 2001
From: bakanayatsu <78297228+ihatenumbers@users.noreply.github.com>
Date: Wed, 22 May 2024 23:01:31 +0800
Subject: [PATCH 27/35] Update mikupad.html

Co-authored-by: lmg-anon <139719567+lmg-anon@users.noreply.github.com>
---
 mikupad.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mikupad.html b/mikupad.html
index a3c44e7..5897d0b 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -3876,7 +3876,7 @@
 		});
 		observer.observe(sidebar.current);
 		return () => observer.disconnect();
-	});
+	}, []);
 
 	return html`
 		<div id="prompt-container" onMouseMove=${onPromptMouseMove} style=${{ 'margin-bottom': isMobile ? height + 'px' : 0 }}>

From 2b7f0b09cf52782a3a661d777b36aa47e45407be Mon Sep 17 00:00:00 2001
From: lmg-anon <139719567+lmg-anon@users.noreply.github.com>
Date: Wed, 22 May 2024 12:03:10 -0300
Subject: [PATCH 28/35] Add version check to server

---
 mikupad.html     | 14 +++++++++++---
 server/server.js |  7 +++++++
 2 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/mikupad.html b/mikupad.html
index 6b6158d..25b6c00 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -2915,9 +2915,17 @@
 	}
 
 	async init() {
-		// Test connection
-		const db = await this.openDatabase();
-		await this.loadFromDatabase(db, "Sessions", "selectedSessionId");
+		const res = await fetch(new URL('/version', this.sessionEndpoint), {
+			method: 'GET',
+			headers: {
+				'Content-Type': 'application/json'
+			}
+		});
+		if (!res.ok)
+			throw new Error("Not a mikupad server or version mismatch.");
+		const { version } = await res.json();
+		if (version !== 2)
+			throw new Error("Mikupad server version mismatch.");
 	}
 
 	async openDatabase() {
diff --git a/server/server.js b/server/server.js
index 3272525..96453bc 100644
--- a/server/server.js
+++ b/server/server.js
@@ -62,6 +62,11 @@ app.get('/', (req, res) => {
     res.sendFile(path.join(__dirname, '..', 'mikupad.html'));
 });
 
+// GET route to get the server version
+app.get('/version', (req, res) => {
+    res.json({ version: 2 });
+});
+
 // Dynamic POST proxy route
 app.post('/proxy/*', async (req, res) => {
     // Capture the part of the URL after '/proxy'
@@ -148,6 +153,8 @@ app.get('/proxy/*', async (req, res) => {
 });
 
 const normalizeStoreName = (storeName) => {
+    if (!storeName)
+        return "Sessions";
     return storeName.split(' ')[0].toLowerCase();
 };
 

From 05c372fa59e20370964a3f6e496e61e5df7d0223 Mon Sep 17 00:00:00 2001
From: bakanayatsu <migcarlo044@gmail.com>
Date: Wed, 22 May 2024 23:36:32 +0800
Subject: [PATCH 29/35] rename

---
 mikupad.html | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/mikupad.html b/mikupad.html
index 5897d0b..dea15f0 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -3866,20 +3866,20 @@
 		[promptChunks, currentPromptChunk, showProbs]);
 
 	const sidebar = useRef(null);
-	const [height, setHeight] = useState(0);
+	const [sidebarHeight, setSidebarHeight] = useState(0);
 	const [isMobile, setIsMobile] = useState(false);
 	useEffect(() => {
-		setHeight(sidebar.current.scrollHeight);
+		setSidebarHeight(sidebar.current.scrollHeight);
 		const observer = new SVResizeObserver(() => {
 			setIsMobile(window.innerWidth < 767.8);
-			setHeight(sidebar.current.scrollHeight);
+			setSidebarHeight(sidebar.current.scrollHeight);
 		});
 		observer.observe(sidebar.current);
 		return () => observer.disconnect();
-	}, []);
+	});
 
 	return html`
-		<div id="prompt-container" onMouseMove=${onPromptMouseMove} style=${{ 'margin-bottom': isMobile ? height + 'px' : 0 }}>
+		<div id="prompt-container" onMouseMove=${onPromptMouseMove} style=${{ 'margin-bottom': isMobile ? sidebarHeight + 'px' : 0 }}>
 			<button
 				className="textAreaSettings"
 				onClick=${() => toggleModal("prompt")}>

From 507aa66b1c85f36ce331d411b5d334b1956d9925 Mon Sep 17 00:00:00 2001
From: bakanayatsu <migcarlo044@gmail.com>
Date: Wed, 22 May 2024 23:56:53 +0800
Subject: [PATCH 30/35] fix disappearing selectbox

---
 mikupad.html | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/mikupad.html b/mikupad.html
index dea15f0..40ffed4 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -1016,7 +1016,7 @@
 		max-width: 100%;
 		border: none !important; /* put this here because for some reason, something adds "border-right: 2px dotted transparent;border-left: 2px dotted transparent;" to prompt-container whenever this element is clicked*/
 	}
-	#sidebar, html.monospace-dark #sidebar, html.nockoffAI #sidebar {
+	html.monospace-dark #sidebar, html.nockoffAI #sidebar {
 		width: auto;
 		max-height: calc(93vh - 8px);
 		position: fixed;
@@ -1024,7 +1024,7 @@
 		right: 0;
 		bottom: 0;
 	}
-	.SelectBox, .horz-separator, .collapsible-group {
+	#sidebar .SelectBox:first-child, .horz-separator, .collapsible-group {
 		display: none;
 	}
 	#button-settings {
@@ -1033,7 +1033,7 @@
 }
 
 @media (min-width: 767.98px) {
-	.SelectBox, .horz-separator, .collapsible-group {
+	#sidebar .SelectBox:first-child, , .horz-separator, .collapsible-group {
 		display: block !important;
 	}
 }

From 04593770a94851f81aba5d8f5223223b634e5b2e Mon Sep 17 00:00:00 2001
From: bakanayatsu <migcarlo044@gmail.com>
Date: Wed, 22 May 2024 23:57:16 +0800
Subject: [PATCH 31/35] remove extra comma

---
 mikupad.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mikupad.html b/mikupad.html
index 40ffed4..33e748f 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -1033,7 +1033,7 @@
 }
 
 @media (min-width: 767.98px) {
-	#sidebar .SelectBox:first-child, , .horz-separator, .collapsible-group {
+	#sidebar .SelectBox:first-child, .horz-separator, .collapsible-group {
 		display: block !important;
 	}
 }

From 25629c290b357ec5fe7ee114a9c03d6ca111a2a6 Mon Sep 17 00:00:00 2001
From: bakanayatsu <migcarlo044@gmail.com>
Date: Wed, 22 May 2024 23:58:22 +0800
Subject: [PATCH 32/35] fix accident

---
 mikupad.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mikupad.html b/mikupad.html
index 33e748f..58162d1 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -1016,7 +1016,7 @@
 		max-width: 100%;
 		border: none !important; /* put this here because for some reason, something adds "border-right: 2px dotted transparent;border-left: 2px dotted transparent;" to prompt-container whenever this element is clicked*/
 	}
-	html.monospace-dark #sidebar, html.nockoffAI #sidebar {
+	#sidebar, html.monospace-dark #sidebar, html.nockoffAI #sidebar {
 		width: auto;
 		max-height: calc(93vh - 8px);
 		position: fixed;

From 5984ba3c2fef56fa2c8e586e5077302fe8e726d5 Mon Sep 17 00:00:00 2001
From: lmg-anon <139719567+lmg-anon@users.noreply.github.com>
Date: Wed, 22 May 2024 14:52:57 -0300
Subject: [PATCH 33/35] Update mikupad.html

---
 mikupad.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mikupad.html b/mikupad.html
index 58162d1..d8cca62 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -3876,7 +3876,7 @@
 		});
 		observer.observe(sidebar.current);
 		return () => observer.disconnect();
-	});
+	}, []);
 
 	return html`
 		<div id="prompt-container" onMouseMove=${onPromptMouseMove} style=${{ 'margin-bottom': isMobile ? sidebarHeight + 'px' : 0 }}>

From 58dbe06b830ab121239fa9f474cb3f14ce5c2d5f Mon Sep 17 00:00:00 2001
From: lmg-anon <139719567+lmg-anon@users.noreply.github.com>
Date: Mon, 20 May 2024 10:23:44 -0300
Subject: [PATCH 34/35] Implement basic fill-in-the-middle support

---
 mikupad.html | 230 +++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 168 insertions(+), 62 deletions(-)

diff --git a/mikupad.html b/mikupad.html
index aee1605..e4d252e 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -3684,8 +3684,7 @@
 
 	const promptText = useMemo(() => joinPrompt(promptChunks), [promptChunks]);
 
-	// compute separately as I imagine this can get expensive
-	const assembledWorldInfo = useMemo(() => {
+	const assembleWorldInfo = (promptText) => {
 		// assemble non-empty wi
 		const validWorldInfo = !Array.isArray(worldInfo.entries) ? [] : worldInfo.entries.filter(entry =>
 			entry.keys.length > 0 && !(entry.keys.length == 1 && entry.keys[0] == "") && entry.text !== "");
@@ -3720,16 +3719,19 @@
 			});
 		});
 
-		const assembledWorldInfo = activeWorldInfo.length > 0
+		return activeWorldInfo.length > 0
 			? activeWorldInfo.map(entry => entry.text).join("\n")
 			: "";
+	};
 
-		return assembledWorldInfo
+	// compute separately as I imagine this can get expensive
+	const assembledWorldInfo = useMemo(() => {
+		return assembleWorldInfo(promptText);
 	}, [worldInfo]);
 
-	const additionalContextPrompt = useMemo(() => {
-		// add world info to memory for easier assembly
-		memoryTokens["worldInfo"] = assembledWorldInfo;
+	const assembleAdditionalContext = (assembledWorldInfo, promptText) => {
+		if ("worldInfo" in memoryTokens)
+			delete memoryTokens["worldInfo"];
 
 		const order = ["prefix","text","suffix"]
 		const assembledAuthorNote = authorNoteTokens.text && authorNoteTokens.text !== ""
@@ -3738,19 +3740,19 @@
 
 		// replacements for the contextOrder string
 		const contextReplacements = {
-			"{wiPrefix}": memoryTokens.worldInfo && memoryTokens.worldInfo !== ""
+			"{wiPrefix}": assembledWorldInfo && assembledWorldInfo !== ""
 				? worldInfo.prefix
 				: "", // wi prefix and suffix will be added whenever wi isn't empty
-			"{wiText}": memoryTokens.worldInfo,
-			"{wiSuffix}": memoryTokens.worldInfo && memoryTokens.worldInfo !== ""
+			"{wiText}": assembledWorldInfo,
+			"{wiSuffix}": assembledWorldInfo && assembledWorldInfo !== ""
 				? worldInfo.suffix
 				: "",
 
-			"{memPrefix}": memoryTokens.text && memoryTokens.text !== "" || memoryTokens.worldInfo !== ""
+			"{memPrefix}": memoryTokens.text && memoryTokens.text !== "" || assembledWorldInfo !== ""
 				? memoryTokens.prefix
 				: "", // memory prefix and suffix will be added whenever memory or wi aren't empty
 			"{memText}": memoryTokens.text,
-			"{memSuffix}": memoryTokens.text && memoryTokens.text !== "" || memoryTokens.worldInfo !== ""
+			"{memSuffix}": memoryTokens.text && memoryTokens.text !== "" || assembledWorldInfo !== ""
 				? memoryTokens.suffix
 				: "",
 		}
@@ -3799,9 +3801,13 @@
 		}).join("\n").replace(/\\n/g, '\n');
 
 		return permContextPrompt;
+	};
+
+	const additionalContextPrompt = useMemo(() => {
+		return assembleAdditionalContext(assembledWorldInfo, promptText);
 	}, [contextLength, promptText, memoryTokens, authorNoteTokens, authorNoteDepth, assembledWorldInfo, worldInfo.prefix, worldInfo.suffix]);
 
-	const modifiedPrompt = useMemo(() => {
+	const assembleFinalPrompt = (additionalContextPrompt) => {
 		const templateReplacements = {
 			"{inst}": templates[selectedTemplate]?.instPre && templates[selectedTemplate]?.instPre !== ""
 				? templates[selectedTemplate]?.instPre
@@ -3824,9 +3830,75 @@
 			}).replace(/\\n/g, '\n');
 
 		return finalPrompt;
+	}
+
+	const modifiedPrompt = useMemo(() => {
+		return assembleFinalPrompt(additionalContextPrompt);
 	}, [additionalContextPrompt, templates, selectedTemplate]);
 
-	async function predict(prompt = modifiedPrompt, chunkCount = promptChunks.length) {
+	// predict all {fill} placeholders
+	async function fillsPredict() {
+		const fillPlaceholder = "{fill}";
+
+		let leftPromptChunks = [];
+		let rightPromptChunks = [];
+		let fillIdx = undefined;
+
+		for (let i = 0; i < promptChunks.length; i++) {
+			const chunk = promptChunks[i];
+			if (chunk.content.includes(fillPlaceholder)) {
+				// split the chunk in 2
+				const left = { content: chunk.content.substring(0, chunk.content.indexOf(fillPlaceholder)), type: "user" };
+				const right = { content: chunk.content.substring(chunk.content.indexOf(fillPlaceholder) + fillPlaceholder.length), type: "user" };
+				fillIdx = i + 1;
+				leftPromptChunks = [
+					...promptChunks.slice(0, Math.max(0, i - 1)),
+					...[left]
+				];
+				rightPromptChunks = [
+					...[right],
+					...promptChunks.slice(i + 1, promptChunks.length - 1),
+				];
+				break;
+			}
+		}
+
+		if (!fillIdx)
+			return;
+
+		const promptText = joinPrompt(leftPromptChunks);
+		const assembledWorldInfo = assembleWorldInfo(promptText);
+		const additionalContextPrompt = assembleAdditionalContext(assembledWorldInfo, promptText);
+		const finalPrompt = assembleFinalPrompt(additionalContextPrompt);
+		
+		predict(finalPrompt, leftPromptChunks.length, (chunk) => {
+			console.log(chunk);
+			if (rightPromptChunks[0]) {
+				if (chunk.content.trim().startsWith(rightPromptChunks[0].content[0])) {
+					if (chunk.content[0] == ' ' && rightPromptChunks[0].content[0] != ' ') {
+						rightPromptChunks[0].content = ' ' + rightPromptChunks[0].content;
+						setPromptChunks(p => [
+							...leftPromptChunks,
+							...rightPromptChunks
+						]);
+					}
+					return false;
+				}
+			}
+			leftPromptChunks = [
+				...leftPromptChunks,
+				chunk
+			];
+			setPromptChunks(p => [
+				...leftPromptChunks,
+				...rightPromptChunks
+			]);
+			setTokens(t => t + (chunk?.completion_probabilities?.length ?? 1));
+			return true;
+		});
+	}
+
+	async function predict(prompt = modifiedPrompt, chunkCount = promptChunks.length, callback = undefined) {
 		if (cancel) {
 			cancel?.();
 
@@ -3836,7 +3908,7 @@
 			setCancel(() => () => cancelled = true);
 			await new Promise(resolve => setTimeout(resolve, 500));
 			if (cancelled)
-				return;
+				return false;
 		}
 
 		const ac = new AbortController();
@@ -3856,34 +3928,36 @@
 			// so let's set the predictStartTokens beforehand.
 			setPredictStartTokens(tokens);
 
-			const tokenCount = await getTokenCount({
-				endpoint,
-				endpointAPI,
-				...(endpointAPI == 3 || endpointAPI == 0 ? { endpointAPIKey } : {}),
-				content: prompt,
-				signal: ac.signal,
-				...(isMikupadEndpoint ? { proxyEndpoint: sessionStorage.proxyEndpoint } : {})
-			});
-			setTokens(tokenCount);
-			setPredictStartTokens(tokenCount);
-
-			// Chat Mode
-			if (chatMode && !restartedPredict && templates[selectedTemplate]) {
-				// add user EOT template (instruct suffix) if not switch completion
-				const { instSuf, instPre } = replaceNewlines(templates[selectedTemplate]);
-				const instSufIndex = instSuf ? prompt.lastIndexOf(instSuf) : -1;
-				const instPreIndex = instPre ? prompt.lastIndexOf(instPre) : -1;
-				if (instSufIndex <= instPreIndex) {
-					setPromptChunks(p => [...p, { type: 'user', content: instSuf }])
-					prompt += instSuf;
+			if (!callback) {
+				const tokenCount = await getTokenCount({
+					endpoint,
+					endpointAPI,
+					...(endpointAPI == 3 || endpointAPI == 0 ? { endpointAPIKey } : {}),
+					content: prompt,
+					signal: ac.signal,
+					...(isMikupadEndpoint ? { proxyEndpoint: sessionStorage.proxyEndpoint } : {})
+				});
+				setTokens(tokenCount);
+				setPredictStartTokens(tokenCount);
+
+				// Chat Mode
+				if (chatMode && !restartedPredict && templates[selectedTemplate]) {
+					// add user EOT template (instruct suffix) if not switch completion
+					const { instSuf, instPre } = replaceNewlines(templates[selectedTemplate]);
+					const instSufIndex = instSuf ? prompt.lastIndexOf(instSuf) : -1;
+					const instPreIndex = instPre ? prompt.lastIndexOf(instPre) : -1;
+					if (instSufIndex <= instPreIndex) {
+						setPromptChunks(p => [...p, { type: 'user', content: instSuf }])
+						prompt += instSuf;
+					}
 				}
-			}
-			setRestartedPredict(false)
+				setRestartedPredict(false)
 
-			while (undoStack.current.at(-1) >= chunkCount)
-				undoStack.current.pop();
-			undoStack.current.push(chunkCount);
-			redoStack.current = [];
+				while (undoStack.current.at(-1) >= chunkCount)
+					undoStack.current.pop();
+				undoStack.current.push(chunkCount);
+				redoStack.current = [];
+			}
 			setUndoHovered(false);
 			setRejectedAPIKey(false);
 			promptArea.current.scrollTarget = undefined;
@@ -3936,8 +4010,13 @@
 					chunk.content = chunk.stopping_word;
 				if (!chunk.content)
 					continue;
-				setPromptChunks(p => [...p, chunk]);
-				setTokens(t => t + (chunk?.completion_probabilities?.length ?? 1));
+				if (callback) {
+					if (!callback(chunk))
+						break;
+				} else {
+					setPromptChunks(p => [...p, chunk]);
+					setTokens(t => t + (chunk?.completion_probabilities?.length ?? 1));
+				}
 				chunkCount += 1;
 			}
 		} catch (e) {
@@ -3956,16 +4035,21 @@
 			return false;
 		} finally {
 			setCancel(c => c === cancelThis ? null : c);
-			if (undoStack.current.at(-1) === chunkCount)
-				undoStack.current.pop();
+			if (!callback) {
+				if (undoStack.current.at(-1) === chunkCount)
+					undoStack.current.pop();
+			}
 		}
+
 		// Chat Mode
-		if (chatMode) {
+		if (!callback && chatMode) {
 			// add bot EOT template (instruct prefix)
 			const eotBot = templates[selectedTemplate]?.instPre.replace(/\\n/g, '\n')
 			setPromptChunks(p => [...p, { type: 'user', content: eotBot }])
 			prompt += `${eotBot}`
 		}
+		
+		return true;
 	}
 
 	function undo() {
@@ -4193,7 +4277,7 @@
 			switch (`${altKey}:${ctrlKey}:${shiftKey}:${key}`) {
 			case 'false:false:true:Enter':
 			case 'false:true:false:Enter':
-				predict();
+				fillsPredict();//predict();
 				break;
 			case 'false:false:false:Escape':
 				cancel();
@@ -4340,28 +4424,50 @@
 				newValue = newValue.slice(0, -chunk.content.length);
 			}
 
+			// Merge chunks if they're from the user
+			let mergeUserChunks = (chunks, newContent) => {
+				let lastChunk = chunks[chunks.length - 1];
+				while (lastChunk && lastChunk.type === 'user') {
+					lastChunk.content += newContent;
+					if (chunks[chunks.length - 2] && chunks[chunks.length - 2].type === 'user') {
+						newContent = lastChunk.content;
+						lastChunk = chunks[chunks.length - 2];
+						chunks.splice(chunks.length - 1, 1);
+					} else {
+						return chunks;
+					}
+				}
+				return [...chunks, { type: 'user', content: newContent }];
+			};
+
+			let newPrompt = [...start];
+			if (newValue) {
+				newPrompt = mergeUserChunks(newPrompt, newValue);
+			}
+			if (end.length && end[0].type === 'user') {
+				newPrompt = mergeUserChunks(newPrompt, end.shift().content);
+			}
+			newPrompt.push(...end);
+
 			// Remove all undo positions within the modified range.
-			undoStack.current = undoStack.current.filter(pos => start.length < pos);
+			undoStack.current = undoStack.current.filter(pos => pos > start.length && pos < newPrompt.length);
 			if (!undoStack.current.length)
 				setUndoHovered(false);
 
-			// Update all undo positions.
-			if (start.length + end.length + (+!!newValue) !== oldPromptLength) {
-				// Reset redo stack if a new chunk is added/removed at the end.
-				if (!end.length)
-					redoStack.current = [];
+			// Adjust undo/redo stacks.
+			const chunkDifference = oldPromptLength - newPrompt.length;
+			undoStack.current = undoStack.current.map(pos => {
+				if (pos >= start.length) {
+					return pos - chunkDifference;
+				}
+				return pos;
+			});
 
-				if (!oldPrompt.length)
-					undoStack.current = undoStack.current.map(pos => pos + 1);
-				else
-					undoStack.current = undoStack.current.map(pos => pos - oldPrompt.length);
+			// Reset redo stack if a new chunk is added/removed at the end.
+			if (chunkDifference < 0 && !end.length) {
+				redoStack.current = [];
 			}
 
-			const newPrompt = [
-				...start,
-				...(newValue ? [{ type: 'user', content: newValue }] : []),
-				...end,
-			];
 			return newPrompt;
 		});
 	}

From 43fc694329b7219fc9d27d702a319f4996b272c5 Mon Sep 17 00:00:00 2001
From: lmg-anon <139719567+lmg-anon@users.noreply.github.com>
Date: Mon, 20 May 2024 23:33:23 -0300
Subject: [PATCH 35/35] Some fixes

---
 mikupad.html | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/mikupad.html b/mikupad.html
index e4d252e..80b32df 100644
--- a/mikupad.html
+++ b/mikupad.html
@@ -3850,15 +3850,15 @@
 				// split the chunk in 2
 				const left = { content: chunk.content.substring(0, chunk.content.indexOf(fillPlaceholder)), type: "user" };
 				const right = { content: chunk.content.substring(chunk.content.indexOf(fillPlaceholder) + fillPlaceholder.length), type: "user" };
-				fillIdx = i + 1;
 				leftPromptChunks = [
-					...promptChunks.slice(0, Math.max(0, i - 1)),
-					...[left]
+					...promptChunks.slice(0, i),
+					left
 				];
 				rightPromptChunks = [
-					...[right],
+					right,
 					...promptChunks.slice(i + 1, promptChunks.length - 1),
 				];
+				fillIdx = i + 1;
 				break;
 			}
 		}
@@ -3872,9 +3872,9 @@
 		const finalPrompt = assembleFinalPrompt(additionalContextPrompt);
 		
 		predict(finalPrompt, leftPromptChunks.length, (chunk) => {
-			console.log(chunk);
 			if (rightPromptChunks[0]) {
-				if (chunk.content.trim().startsWith(rightPromptChunks[0].content[0])) {
+				const trimmedChunk = chunk.content.replace(/^ +| +$/gm, "")
+				if (trimmedChunk.startsWith(rightPromptChunks[0].content[0])) {
 					if (chunk.content[0] == ' ' && rightPromptChunks[0].content[0] != ' ') {
 						rightPromptChunks[0].content = ' ' + rightPromptChunks[0].content;
 						setPromptChunks(p => [
@@ -3956,8 +3956,10 @@
 				while (undoStack.current.at(-1) >= chunkCount)
 					undoStack.current.pop();
 				undoStack.current.push(chunkCount);
-				redoStack.current = [];
+			} else {
+				undoStack.current = [];
 			}
+			redoStack.current = [];
 			setUndoHovered(false);
 			setRejectedAPIKey(false);
 			promptArea.current.scrollTarget = undefined;