mirror of
https://github.com/rait-09/obsidian-agent-client.git
synced 2026-07-22 06:43:37 +00:00
feat(session-history): Add delete button and show sessions for all agents
- Add deleteSession method to useSessionHistory hook - Add Delete button to all session items (always visible) - Change early return for restoration non-supporting agents to warning banner - Show locally saved sessions for all agents (for deletion) - Add warning banner and delete button styles
This commit is contained in:
parent
a9f412113a
commit
89aef910c7
4 changed files with 125 additions and 19 deletions
|
|
@ -381,6 +381,16 @@ function ChatComponent({
|
|||
logger.error("Session fork error:", error);
|
||||
}
|
||||
},
|
||||
onDeleteSession: async (sessionId: string) => {
|
||||
try {
|
||||
logger.log(`[ChatView] Deleting session: ${sessionId}`);
|
||||
await sessionHistory.deleteSession(sessionId);
|
||||
new Notice("[Agent Client] Session deleted");
|
||||
} catch (error) {
|
||||
new Notice("[Agent Client] Failed to delete session");
|
||||
logger.error("Session delete error:", error);
|
||||
}
|
||||
},
|
||||
onLoadMore: () => {
|
||||
void sessionHistory.loadMoreSessions();
|
||||
},
|
||||
|
|
@ -452,6 +462,16 @@ function ChatComponent({
|
|||
logger.error("Session fork error:", error);
|
||||
}
|
||||
},
|
||||
onDeleteSession: async (sessionId: string) => {
|
||||
try {
|
||||
logger.log(`[ChatView] Deleting session: ${sessionId}`);
|
||||
await sessionHistory.deleteSession(sessionId);
|
||||
new Notice("[Agent Client] Session deleted");
|
||||
} catch (error) {
|
||||
new Notice("[Agent Client] Failed to delete session");
|
||||
logger.error("Session delete error:", error);
|
||||
}
|
||||
},
|
||||
onLoadMore: () => {
|
||||
void sessionHistory.loadMoreSessions();
|
||||
},
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@ export interface SessionHistoryContentProps {
|
|||
onResumeSession: (sessionId: string, cwd: string) => Promise<void>;
|
||||
/** Callback when a session is forked (create new branch) */
|
||||
onForkSession: (sessionId: string, cwd: string) => Promise<void>;
|
||||
/** Callback when a session is deleted */
|
||||
onDeleteSession: (sessionId: string) => Promise<void>;
|
||||
/** Callback to load more sessions (pagination) */
|
||||
onLoadMore: () => void;
|
||||
/** Callback to fetch sessions with filter */
|
||||
|
|
@ -229,6 +231,7 @@ function SessionItem({
|
|||
onLoadSession,
|
||||
onResumeSession,
|
||||
onForkSession,
|
||||
onDeleteSession,
|
||||
onClose,
|
||||
}: {
|
||||
session: SessionInfo;
|
||||
|
|
@ -238,6 +241,7 @@ function SessionItem({
|
|||
onLoadSession: (sessionId: string, cwd: string) => Promise<void>;
|
||||
onResumeSession: (sessionId: string, cwd: string) => Promise<void>;
|
||||
onForkSession: (sessionId: string, cwd: string) => Promise<void>;
|
||||
onDeleteSession: (sessionId: string) => Promise<void>;
|
||||
onClose: () => void;
|
||||
}) {
|
||||
const handleLoad = useCallback(() => {
|
||||
|
|
@ -255,6 +259,10 @@ function SessionItem({
|
|||
void onForkSession(session.sessionId, session.cwd);
|
||||
}, [session, onForkSession, onClose]);
|
||||
|
||||
const handleDelete = useCallback(() => {
|
||||
void onDeleteSession(session.sessionId);
|
||||
}, [session.sessionId, onDeleteSession]);
|
||||
|
||||
return (
|
||||
<div className="agent-client-session-history-item">
|
||||
<div className="agent-client-session-history-item-content">
|
||||
|
|
@ -297,6 +305,12 @@ function SessionItem({
|
|||
onClick={handleFork}
|
||||
/>
|
||||
)}
|
||||
<IconButton
|
||||
iconName="trash-2"
|
||||
label="Delete session"
|
||||
className="agent-client-session-history-action-icon agent-client-session-history-delete-icon"
|
||||
onClick={handleDelete}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
@ -328,6 +342,7 @@ export function SessionHistoryContent({
|
|||
onLoadSession,
|
||||
onResumeSession,
|
||||
onForkSession,
|
||||
onDeleteSession,
|
||||
onLoadMore,
|
||||
onFetchSessions,
|
||||
onClose,
|
||||
|
|
@ -361,18 +376,11 @@ export function SessionHistoryContent({
|
|||
// Check if any session operation is available
|
||||
const canPerformAnyOperation = canLoad || canResume || canFork;
|
||||
|
||||
// Show message if no session operations are supported
|
||||
if (!canPerformAnyOperation && !debugMode) {
|
||||
return (
|
||||
<div className="agent-client-session-history-empty">
|
||||
<p className="agent-client-session-history-empty-text">
|
||||
This agent does not support session restoration.
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const canShowList = canList || isUsingLocalSessions;
|
||||
// Show local sessions list (always show for delete functionality)
|
||||
// - If agent supports list: use agent's session/list
|
||||
// - If agent doesn't support list OR doesn't support restoration: use locally saved sessions
|
||||
const canShowList =
|
||||
canList || isUsingLocalSessions || !canPerformAnyOperation;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
@ -387,13 +395,21 @@ export function SessionHistoryContent({
|
|||
/>
|
||||
)}
|
||||
|
||||
{/* Warning banner for agents that don't support restoration */}
|
||||
{!canPerformAnyOperation && (
|
||||
<div className="agent-client-session-history-warning-banner">
|
||||
<p>
|
||||
This agent does not support session restoration.
|
||||
Messages are saved locally but cannot be restored to the
|
||||
agent.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Local sessions banner */}
|
||||
{isUsingLocalSessions && (
|
||||
{(isUsingLocalSessions || !canPerformAnyOperation) && (
|
||||
<div className="agent-client-session-history-local-banner">
|
||||
<span>
|
||||
Locally saved sessions (agent doesn't support
|
||||
session/list)
|
||||
</span>
|
||||
<span>Locally saved sessions</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
|
@ -470,6 +486,7 @@ export function SessionHistoryContent({
|
|||
onLoadSession={onLoadSession}
|
||||
onResumeSession={onResumeSession}
|
||||
onForkSession={onForkSession}
|
||||
onDeleteSession={onDeleteSession}
|
||||
onClose={onClose}
|
||||
/>
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -132,6 +132,12 @@ export interface UseSessionHistoryReturn {
|
|||
*/
|
||||
forkSession: (sessionId: string, cwd: string) => Promise<void>;
|
||||
|
||||
/**
|
||||
* Delete a session (local metadata + message file).
|
||||
* @param sessionId - Session to delete
|
||||
*/
|
||||
deleteSession: (sessionId: string) => Promise<void>;
|
||||
|
||||
/**
|
||||
* Invalidate the session cache.
|
||||
* Call this when creating a new session to refresh the list.
|
||||
|
|
@ -220,15 +226,25 @@ export function useSessionHistory(
|
|||
cacheRef.current = null;
|
||||
}, []);
|
||||
|
||||
// Check if any restoration operation is available
|
||||
const canPerformAnyOperation =
|
||||
capabilities.canLoad || capabilities.canResume || capabilities.canFork;
|
||||
|
||||
/**
|
||||
* Fetch sessions list from agent or local storage.
|
||||
* Uses agent's session/list if supported, otherwise falls back to local storage.
|
||||
* For agents that don't support restoration, local sessions are used for deletion.
|
||||
* Replaces existing sessions in state.
|
||||
*/
|
||||
const fetchSessions = useCallback(
|
||||
async (cwd?: string) => {
|
||||
// If agent doesn't support list, use local sessions
|
||||
if (!capabilities.canList) {
|
||||
// Use local sessions if:
|
||||
// - Agent doesn't support session/list, OR
|
||||
// - Agent doesn't support any restoration operation (for delete only)
|
||||
const shouldUseLocalSessions =
|
||||
!capabilities.canList || !canPerformAnyOperation;
|
||||
|
||||
if (shouldUseLocalSessions) {
|
||||
// Get locally saved sessions for this agent
|
||||
const localSessions = settingsAccess.getSavedSessions(
|
||||
session.agentId,
|
||||
|
|
@ -289,6 +305,7 @@ export function useSessionHistory(
|
|||
[
|
||||
agentClient,
|
||||
capabilities.canList,
|
||||
canPerformAnyOperation,
|
||||
isCacheValid,
|
||||
settingsAccess,
|
||||
session.agentId,
|
||||
|
|
@ -450,6 +467,33 @@ export function useSessionHistory(
|
|||
],
|
||||
);
|
||||
|
||||
/**
|
||||
* Delete a session (local metadata + message file).
|
||||
* Removes from both local state and persistent storage.
|
||||
*/
|
||||
const deleteSession = useCallback(
|
||||
async (sessionId: string) => {
|
||||
try {
|
||||
// Delete from persistent storage (metadata + message file)
|
||||
await settingsAccess.deleteSession(sessionId);
|
||||
|
||||
// Remove from local state
|
||||
setSessions((prev) =>
|
||||
prev.filter((s) => s.sessionId !== sessionId),
|
||||
);
|
||||
|
||||
// Invalidate cache to ensure consistency
|
||||
invalidateCache();
|
||||
} catch (err) {
|
||||
const errorMessage =
|
||||
err instanceof Error ? err.message : String(err);
|
||||
setError(`Failed to delete session: ${errorMessage}`);
|
||||
throw err; // Re-throw to allow caller to handle
|
||||
}
|
||||
},
|
||||
[settingsAccess, invalidateCache],
|
||||
);
|
||||
|
||||
return {
|
||||
sessions,
|
||||
loading,
|
||||
|
|
@ -475,6 +519,7 @@ export function useSessionHistory(
|
|||
loadSession,
|
||||
resumeSession,
|
||||
forkSession,
|
||||
deleteSession,
|
||||
invalidateCache,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
24
styles.css
24
styles.css
|
|
@ -1519,3 +1519,27 @@ If your plugin does not need CSS, delete this file.
|
|||
color: var(--text-muted);
|
||||
border-left: 3px solid var(--interactive-accent);
|
||||
}
|
||||
|
||||
/* Warning banner for agents that don't support restoration */
|
||||
.agent-client-session-history-warning-banner {
|
||||
padding: 8px 12px;
|
||||
margin-bottom: 12px;
|
||||
background: var(--background-secondary);
|
||||
border-radius: 4px;
|
||||
border-left: 3px solid var(--text-warning);
|
||||
}
|
||||
|
||||
.agent-client-session-history-warning-banner p {
|
||||
margin: 0;
|
||||
color: var(--text-muted);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* Delete button */
|
||||
.agent-client-session-history-delete-icon {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.agent-client-session-history-delete-icon:hover {
|
||||
color: var(--text-error);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue