feat: store working directory for sessions (#1559)

This commit is contained in:
Salman Mohammed
2025-03-07 11:12:57 -05:00
committed by GitHub
parent 2d0cd8e245
commit 32f20cd690
20 changed files with 334 additions and 144 deletions
+14 -55
View File
@@ -48,63 +48,28 @@ export default function ChatView({
const resumedSession = viewOptions?.resumedSession;
// Generate or retrieve session ID
const [sessionId] = useState(() => {
// If resuming a session, use that session ID
if (resumedSession?.session_id) {
// Store the resumed session ID in sessionStorage
window.sessionStorage.setItem('goose-session-id', resumedSession.session_id);
return resumedSession.session_id;
}
// For a new chat, generate a new session ID
const newId = generateSessionId();
window.sessionStorage.setItem('goose-session-id', newId);
return newId;
});
// The session ID should not change for the duration of the chat
const sessionId = resumedSession?.session_id || generateSessionId();
const [chat, setChat] = useState<ChatType>(() => {
// If resuming a session, convert the session messages to our format
if (resumedSession) {
try {
// Convert the resumed session messages to the expected format
const convertedMessages = resumedSession.messages.map((msg): Message => {
return {
id: `${msg.role}-${msg.created}`,
role: msg.role,
created: msg.created,
content: msg.content,
};
});
return {
id: Date.now(),
title: resumedSession.metadata?.description || `ID: ${resumedSession.session_id}`,
messageHistoryIndex: convertedMessages.length,
messages: convertedMessages,
};
} catch (e) {
console.error('Failed to parse resumed session:', e);
}
return {
id: resumedSession.session_id,
title: resumedSession.metadata?.description || `ID: ${resumedSession.session_id}`,
messages: resumedSession.messages,
messageHistoryIndex: resumedSession.messages.length,
};
}
// Try to load saved chat from sessionStorage
const savedChat = window.sessionStorage.getItem(`goose-chat-${sessionId}`);
if (savedChat) {
try {
return JSON.parse(savedChat);
} catch (e) {
console.error('Failed to parse saved chat:', e);
}
}
// Return default chat if no saved chat exists
return {
id: Date.now(),
title: 'Chat 1',
id: sessionId,
title: 'New Chat',
messages: [],
messageHistoryIndex: 0,
};
});
const [messageMetadata, setMessageMetadata] = useState<Record<string, string[]>>({});
const [hasMessages, setHasMessages] = useState(false);
const [lastInteractionTime, setLastInteractionTime] = useState<number>(Date.now());
@@ -124,8 +89,8 @@ export default function ChatView({
handleSubmit: _submitMessage,
} = useMessageStream({
api: getApiUrl('/reply'),
initialMessages: chat?.messages || [],
body: { session_id: sessionId },
initialMessages: resumedSession ? resumedSession.messages : chat?.messages || [],
body: { session_id: sessionId, session_working_dir: window.appConfig.get('GOOSE_WORKING_DIR') },
onFinish: async (message, _reason) => {
window.electron.stopPowerSaveBlocker();
@@ -155,15 +120,9 @@ export default function ChatView({
useEffect(() => {
setChat((prevChat) => {
const updatedChat = { ...prevChat, messages };
// Save to sessionStorage
try {
window.sessionStorage.setItem(`goose-chat-${sessionId}`, JSON.stringify(updatedChat));
} catch (e) {
console.error('Failed to save chat to sessionStorage:', e);
}
return updatedChat;
});
}, [messages, sessionId]);
}, [messages, sessionId, resumedSession]);
useEffect(() => {
if (messages.length > 0) {
+4 -1
View File
@@ -247,7 +247,10 @@ export default function MoreMenu({
<button
onClick={() => {
setOpen(false);
window.electron.createChatWindow();
window.electron.createChatWindow(
undefined,
window.appConfig.get('GOOSE_WORKING_DIR')
);
}}
className="w-full text-left p-2 text-sm hover:bg-bgSubtle transition-colors"
>
@@ -1,5 +1,5 @@
import React from 'react';
import { Clock, MessageSquare, ArrowLeft, AlertCircle } from 'lucide-react';
import { Clock, MessageSquare, Folder, AlertCircle } from 'lucide-react';
import { type SessionDetails } from '../../sessions';
import { Card } from '../ui/card';
import { Button } from '../ui/button';
@@ -69,6 +69,10 @@ const SessionHistoryView: React.FC<SessionHistoryViewProps> = ({
<Clock className="w-4 h-4 mr-1" />
{new Date(session.messages[0]?.created * 1000).toLocaleString()}
</span>
<span className="flex items-center">
<Folder className="w-4 h-4 mr-1" />
{session.metadata.working_dir}
</span>
<span className="flex items-center">
<MessageSquare className="w-4 h-4 mr-1" />
{session.metadata.message_count} messages
@@ -1,6 +1,6 @@
import React, { useEffect, useState } from 'react';
import { ViewConfig } from '../../App';
import { MessageSquare, Loader, AlertCircle, Calendar, ChevronRight } from 'lucide-react';
import { MessageSquare, Loader, AlertCircle, Calendar, ChevronRight, Folder } from 'lucide-react';
import { fetchSessions, type Session } from '../../sessions';
import { Card } from '../ui/card';
import { Button } from '../ui/button';
@@ -104,9 +104,15 @@ const SessionListView: React.FC<SessionListViewProps> = ({ setView, onSelectSess
<h3 className="text-base font-medium text-textStandard truncate">
{session.metadata.description || session.id}
</h3>
<div className="flex items-center mt-1 text-textSubtle text-sm">
<Calendar className="w-3 h-3 mr-1 flex-shrink-0" />
<span className="truncate">{formatDate(session.modified)}</span>
<div className="flex gap-3">
<div className="flex items-center text-textSubtle text-sm">
<Calendar className="w-3 h-3 mr-1 flex-shrink-0" />
<span className="truncate">{formatDate(session.modified)}</span>
</div>
<div className="flex items-center text-textSubtle text-sm">
<Folder className="w-3 h-3 mr-1 flex-shrink-0" />
<span className="truncate">{session.metadata.working_dir}</span>
</div>
</div>
</div>
@@ -40,10 +40,26 @@ const SessionsView: React.FC<SessionsViewProps> = ({ setView }) => {
const handleResumeSession = () => {
if (selectedSession) {
// Pass the session to ChatView for resuming
setView('chat', {
resumedSession: selectedSession,
});
// Get the working directory from the session metadata
const workingDir = selectedSession.metadata.working_dir;
if (workingDir) {
console.log(
`Resuming session with ID: ${selectedSession.session_id}, in working dir: ${workingDir}`
);
// Create a new chat window with the working directory and session ID
window.electron.createChatWindow(
undefined,
workingDir,
undefined,
selectedSession.session_id
);
} else {
// Fallback if no working directory is found
console.error('No working directory found in session metadata');
// We could show a toast or alert here
}
}
};