feat: update Makelore modules and conversations
This commit is contained in:
117
src/stores/project-conversations.ts
Normal file
117
src/stores/project-conversations.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
import { create } from 'zustand';
|
||||
import { hostApiFetch } from '@/lib/host-api';
|
||||
import type {
|
||||
ProjectConversationState,
|
||||
ProjectSessionMetadata,
|
||||
} from '../../shared/project-conversations';
|
||||
|
||||
type ProjectConversationResponse = {
|
||||
state?: ProjectConversationState;
|
||||
success?: boolean;
|
||||
error?: string;
|
||||
};
|
||||
|
||||
type ConversationAction = 'link' | 'archive' | 'restore' | 'delete' | 'read' | 'increment-unread' | 'complete';
|
||||
|
||||
type ProjectConversationStore = {
|
||||
statesByProjectId: Record<string, ProjectConversationState>;
|
||||
loadingProjectId: string | null;
|
||||
errorsByProjectId: Record<string, string>;
|
||||
load: (projectId: string) => Promise<ProjectConversationState>;
|
||||
linkSession: (projectId: string, sessionId: string, agentId: string) => Promise<ProjectConversationState>;
|
||||
archiveSession: (projectId: string, sessionId: string) => Promise<ProjectConversationState>;
|
||||
restoreSession: (projectId: string, sessionId: string) => Promise<ProjectConversationState>;
|
||||
deleteSession: (projectId: string, sessionId: string) => Promise<ProjectConversationState>;
|
||||
markSessionRead: (projectId: string, sessionId: string) => Promise<ProjectConversationState>;
|
||||
markSessionUnread: (projectId: string, sessionId: string) => Promise<ProjectConversationState>;
|
||||
completeSession: (projectId: string, sessionId: string, incrementUnread?: boolean) => Promise<ProjectConversationState>;
|
||||
getSession: (projectId: string, sessionId: string) => ProjectSessionMetadata | undefined;
|
||||
remove: (projectId: string) => void;
|
||||
};
|
||||
|
||||
function emptyState(): ProjectConversationState {
|
||||
return { schemaVersion: 1, sessions: [], updatedAt: new Date().toISOString() };
|
||||
}
|
||||
|
||||
export const useProjectConversationStore = create<ProjectConversationStore>((set, get) => {
|
||||
async function dispatch(projectId: string, sessionId: string, action: ConversationAction, agentId?: string, unread?: boolean) {
|
||||
const response = await hostApiFetch<ProjectConversationResponse>('/api/opencode/projects/conversations', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ projectId, sessionId, action, ...(agentId ? { agentId } : {}), ...(unread ? { unread: true } : {}) }),
|
||||
});
|
||||
if (!response.success || !response.state) throw new Error(response.error || '更新会话归属失败');
|
||||
set((state) => ({
|
||||
statesByProjectId: { ...state.statesByProjectId, [projectId]: response.state as ProjectConversationState },
|
||||
errorsByProjectId: Object.fromEntries(Object.entries(state.errorsByProjectId).filter(([id]) => id !== projectId)),
|
||||
}));
|
||||
return response.state;
|
||||
}
|
||||
|
||||
return {
|
||||
statesByProjectId: {},
|
||||
loadingProjectId: null,
|
||||
errorsByProjectId: {},
|
||||
|
||||
async load(projectId) {
|
||||
set({ loadingProjectId: projectId });
|
||||
try {
|
||||
const response = await hostApiFetch<ProjectConversationResponse>(
|
||||
`/api/opencode/projects/conversations?projectId=${encodeURIComponent(projectId)}`,
|
||||
);
|
||||
const nextState = response.state ?? emptyState();
|
||||
set((state) => ({
|
||||
loadingProjectId: null,
|
||||
statesByProjectId: { ...state.statesByProjectId, [projectId]: nextState },
|
||||
errorsByProjectId: Object.fromEntries(Object.entries(state.errorsByProjectId).filter(([id]) => id !== projectId)),
|
||||
}));
|
||||
return nextState;
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
set((state) => ({
|
||||
loadingProjectId: null,
|
||||
errorsByProjectId: { ...state.errorsByProjectId, [projectId]: message },
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
linkSession(projectId, sessionId, agentId) {
|
||||
return dispatch(projectId, sessionId, 'link', agentId);
|
||||
},
|
||||
|
||||
archiveSession(projectId, sessionId) {
|
||||
return dispatch(projectId, sessionId, 'archive');
|
||||
},
|
||||
|
||||
restoreSession(projectId, sessionId) {
|
||||
return dispatch(projectId, sessionId, 'restore');
|
||||
},
|
||||
|
||||
deleteSession(projectId, sessionId) {
|
||||
return dispatch(projectId, sessionId, 'delete');
|
||||
},
|
||||
|
||||
markSessionRead(projectId, sessionId) {
|
||||
return dispatch(projectId, sessionId, 'read');
|
||||
},
|
||||
|
||||
markSessionUnread(projectId, sessionId) {
|
||||
return dispatch(projectId, sessionId, 'increment-unread');
|
||||
},
|
||||
|
||||
completeSession(projectId, sessionId, incrementUnread = false) {
|
||||
return dispatch(projectId, sessionId, 'complete', undefined, incrementUnread);
|
||||
},
|
||||
|
||||
getSession(projectId, sessionId) {
|
||||
return get().statesByProjectId[projectId]?.sessions.find((item) => item.sessionId === sessionId);
|
||||
},
|
||||
|
||||
remove(projectId) {
|
||||
set((state) => ({
|
||||
statesByProjectId: Object.fromEntries(Object.entries(state.statesByProjectId).filter(([id]) => id !== projectId)),
|
||||
errorsByProjectId: Object.fromEntries(Object.entries(state.errorsByProjectId).filter(([id]) => id !== projectId)),
|
||||
}));
|
||||
},
|
||||
};
|
||||
});
|
||||
Reference in New Issue
Block a user