diff --git a/studio/frontend/src/features/chat/chat-page.tsx b/studio/frontend/src/features/chat/chat-page.tsx
index 7a86950633..84fae04080 100644
--- a/studio/frontend/src/features/chat/chat-page.tsx
+++ b/studio/frontend/src/features/chat/chat-page.tsx
@@ -174,7 +174,8 @@ function InlineSidebar({
function TopBarActions({
onNewThread,
onNewCompare,
-}: { onNewThread: () => void; onNewCompare: () => void }) {
+ showCompare,
+}: { onNewThread: () => void; onNewCompare: () => void; showCompare: boolean }) {
const { state } = useSidebar();
if (state !== "collapsed") {
return null;
@@ -189,14 +190,16 @@ function TopBarActions({
New Chat
-
-
-
-
- Compare
-
+ {showCompare ? (
+
+
+
+
+ Compare
+
+ ) : null}
>
);
}
@@ -215,6 +218,11 @@ export function ChatPage(): ReactElement {
const lorasFromStore = useChatRuntimeStore((state) => state.loras);
const modelsError = useChatRuntimeStore((state) => state.modelsError);
const { refresh, selectModel, ejectModel } = useChatModelRuntime();
+ const canCompare = useMemo(() => {
+ const selected = inferenceParams.checkpoint;
+ if (!selected) return false;
+ return lorasFromStore.some((lora) => lora.id === selected);
+ }, [inferenceParams.checkpoint, lorasFromStore]);
const handleCheckpointChange = useCallback(
(value: string, meta?: { isLora: boolean }) => {
@@ -277,6 +285,7 @@ export function ChatPage(): ReactElement {
onSelect={setView}
onNewThread={handleNewThread}
onNewCompare={handleNewCompare}
+ showCompare={canCompare}
/>
@@ -287,6 +296,7 @@ export function ChatPage(): ReactElement {
();
+function fallbackTitleFromUserText(userText: string): string {
+ const firstLine = (userText || "").split(/\r?\n/, 1)[0] ?? "";
+ const cleaned = firstLine.replace(/\s+/g, " ").trim();
+ const max = 48;
+ if (!cleaned) return "New Chat";
+ return cleaned.slice(0, max) + (cleaned.length > max ? "..." : "");
+}
+
function toThreadMessage(m: MessageRecord): ThreadMessage {
const base = {
id: m.id,
@@ -342,7 +350,7 @@ function createDexieAdapter(
const userText = extractTextParts(firstUser) || "New Chat";
if (!autoTitle) {
- const title = userText.slice(0, 60) + (userText.length > 60 ? "..." : "");
+ const title = fallbackTitleFromUserText(userText);
await db.threads.update(remoteId, { title });
if (pairId) {
const paired = await db.threads
@@ -394,7 +402,7 @@ function createDexieAdapter(
(await generateTitleWithModel({
userText,
})) ||
- (userText.slice(0, 60) + (userText.length > 60 ? "..." : ""));
+ fallbackTitleFromUserText(userText);
await db.threads.update(remoteId, { title });
if (pairId) {
diff --git a/studio/frontend/src/features/chat/stores/chat-runtime-store.ts b/studio/frontend/src/features/chat/stores/chat-runtime-store.ts
index 682ea2ccce..10d5957906 100644
--- a/studio/frontend/src/features/chat/stores/chat-runtime-store.ts
+++ b/studio/frontend/src/features/chat/stores/chat-runtime-store.ts
@@ -57,7 +57,7 @@ export const useChatRuntimeStore = create((set) => ({
loras: [],
warmingByThreadId: {},
runningByThreadId: {},
- autoTitle: loadBool(AUTO_TITLE_KEY, true),
+ autoTitle: loadBool(AUTO_TITLE_KEY, false),
modelsError: null,
setParams: (params) => set({ params }),
setModels: (models) => set({ models }),
diff --git a/studio/frontend/src/features/chat/thread-sidebar.tsx b/studio/frontend/src/features/chat/thread-sidebar.tsx
index e1645e77bb..369dc30769 100644
--- a/studio/frontend/src/features/chat/thread-sidebar.tsx
+++ b/studio/frontend/src/features/chat/thread-sidebar.tsx
@@ -62,11 +62,13 @@ export function ThreadSidebar({
onSelect,
onNewThread,
onNewCompare,
+ showCompare,
}: {
view: ChatView;
onSelect: (view: ChatView) => void;
onNewThread: () => void;
onNewCompare: () => void;
+ showCompare: boolean;
}) {
const allThreads = useLiveQuery(
() => db.threads.orderBy("createdAt").reverse().toArray(),
@@ -112,12 +114,14 @@ export function ThreadSidebar({
New Chat
-
-
-
- Compare
-
-
+ {showCompare ? (
+
+
+
+ Compare
+
+
+ ) : null}