Makelore 2.0 initial clean snapshot

This commit is contained in:
inman
2026-07-29 17:22:35 +08:00
commit b8ca3f8eea
694 changed files with 139782 additions and 0 deletions

View File

@@ -0,0 +1,188 @@
import { create } from 'zustand';
import {
addImageWorkspaceAgent,
createImageWorkspaceProject,
fetchImageWorkspace,
ImageWorkspaceApiError,
sendImageWorkspaceMessage,
uploadImageWorkspaceReference,
} from '@/lib/image-workspace';
import { useAuthStore } from '@/stores/auth';
import {
IMAGE_WORKSPACE_UNAVAILABLE_CODE,
type ImageWorkspaceProject,
type ImageWorkspaceReferenceUploadInput,
type ImageWorkspaceReferenceUploadResult,
type ImageWorkspaceSendMessageInput,
type ImageWorkspaceSnapshot,
} from '../../shared/image-workspace';
export type ImageWorkspaceLoadStatus = 'idle' | 'loading' | 'ready' | 'unavailable' | 'error';
type ImageWorkspaceState = {
status: ImageWorkspaceLoadStatus;
snapshot: ImageWorkspaceSnapshot | null;
activeProjectId: string | null;
activeAgentIds: Record<string, string>;
error: string | null;
load: () => Promise<ImageWorkspaceSnapshot | null>;
createProject: (name: string) => Promise<ImageWorkspaceSnapshot>;
addAgent: (projectId: string) => Promise<ImageWorkspaceSnapshot>;
sendMessage: (input: ImageWorkspaceSendMessageInput) => Promise<ImageWorkspaceSnapshot>;
uploadReference: (input: ImageWorkspaceReferenceUploadInput) => Promise<ImageWorkspaceReferenceUploadResult>;
selectProject: (projectId: string) => void;
selectAgent: (projectId: string, agentId: string) => void;
reset: () => void;
};
let inFlightLoad: Promise<ImageWorkspaceSnapshot | null> | null = null;
function findProject(snapshot: ImageWorkspaceSnapshot, projectId: string | null): ImageWorkspaceProject | undefined {
return snapshot.projects.find((project) => project.id === projectId);
}
function resolveProjectId(snapshot: ImageWorkspaceSnapshot, currentProjectId: string | null): string | null {
if (findProject(snapshot, currentProjectId)) return currentProjectId;
if (findProject(snapshot, snapshot.activeProjectId ?? null)) return snapshot.activeProjectId ?? null;
return snapshot.projects[0]?.id ?? null;
}
function resolveAgentIds(
snapshot: ImageWorkspaceSnapshot,
currentAgentIds: Record<string, string>,
): Record<string, string> {
return Object.fromEntries(snapshot.projects.flatMap((project) => {
const currentAgentId = currentAgentIds[project.id];
let selectedAgentId: string | undefined;
if (currentAgentId && project.agents.some((agent) => agent.id === currentAgentId)) {
selectedAgentId = currentAgentId;
} else if (project.activeAgentId
&& project.agents.some((agent) => agent.id === project.activeAgentId)) {
selectedAgentId = project.activeAgentId;
} else {
selectedAgentId = project.agents[0]?.id;
}
return selectedAgentId ? [[project.id, selectedAgentId]] : [];
}));
}
function unavailable(error: unknown): boolean {
return error instanceof ImageWorkspaceApiError
&& (error.status === 501 || error.code === IMAGE_WORKSPACE_UNAVAILABLE_CODE);
}
async function getOptionalAccessToken(): Promise<string | null> {
return await useAuthStore.getState().getValidAccessToken();
}
async function getRequiredAccessToken(): Promise<string> {
const accessToken = await useAuthStore.getState().getValidAccessToken();
if (!accessToken) throw new Error('请先登录后再使用创作空间');
return accessToken;
}
function usesAnonymousDevelopmentAdapter(): boolean {
return typeof window !== 'undefined'
&& window.electron?.imageWorkspaceLocalDevelopment === true;
}
export const useImageWorkspaceStore = create<ImageWorkspaceState>((set, get) => {
const applySnapshot = (snapshot: ImageWorkspaceSnapshot) => {
set((state) => ({
status: 'ready',
snapshot,
activeProjectId: resolveProjectId(snapshot, state.activeProjectId),
activeAgentIds: resolveAgentIds(snapshot, state.activeAgentIds),
error: null,
}));
return snapshot;
};
const failLoad = (error: unknown) => {
const message = error instanceof Error ? error.message : String(error);
set({
status: unavailable(error) ? 'unavailable' : 'error',
snapshot: null,
activeProjectId: null,
activeAgentIds: {},
error: message,
});
};
const mutate = async (
request: (accessToken: string | null) => Promise<ImageWorkspaceSnapshot>,
): Promise<ImageWorkspaceSnapshot> => {
try {
const accessToken = usesAnonymousDevelopmentAdapter()
? null
: await getRequiredAccessToken();
return applySnapshot(await request(accessToken));
} catch (error) {
set({ error: error instanceof Error ? error.message : String(error) });
throw error;
}
};
return {
status: 'idle',
snapshot: null,
activeProjectId: null,
activeAgentIds: {},
error: null,
load: () => {
if (inFlightLoad) return inFlightLoad;
set({ status: 'loading', error: null });
inFlightLoad = (async () => {
try {
return applySnapshot(await fetchImageWorkspace(await getOptionalAccessToken()));
} catch (error) {
failLoad(error);
return null;
} finally {
inFlightLoad = null;
}
})();
return inFlightLoad;
},
createProject: (name) => mutate((accessToken) => createImageWorkspaceProject(accessToken, name)),
addAgent: (projectId) => mutate((accessToken) => addImageWorkspaceAgent(accessToken, projectId)),
sendMessage: (input) => mutate((accessToken) => sendImageWorkspaceMessage(accessToken, input)),
uploadReference: async (input) => {
try {
const accessToken = usesAnonymousDevelopmentAdapter()
? null
: await getRequiredAccessToken();
const result = await uploadImageWorkspaceReference(accessToken, input);
applySnapshot(result.workspace);
return result;
} catch (error) {
set({ error: error instanceof Error ? error.message : String(error) });
throw error;
}
},
selectProject: (projectId) => {
if (!get().snapshot?.projects.some((project) => project.id === projectId)) return;
set({ activeProjectId: projectId });
},
selectAgent: (projectId, agentId) => {
const project = get().snapshot?.projects.find((item) => item.id === projectId);
if (!project?.agents.some((agent) => agent.id === agentId)) return;
set((state) => ({ activeAgentIds: { ...state.activeAgentIds, [projectId]: agentId } }));
},
reset: () => {
inFlightLoad = null;
set({
status: 'idle',
snapshot: null,
activeProjectId: null,
activeAgentIds: {},
error: null,
});
},
};
});