fix(coding): scope metadata updates by project

This commit is contained in:
2026-08-24 09:43:45 +08:00
parent da92eb1957
commit fcd03f9f6d
5 changed files with 228 additions and 12 deletions

View File

@@ -42,6 +42,7 @@ export interface CodingWorkspaceState {
selectedAgentId: string | null;
loadState: 'idle' | 'loading' | 'ready' | 'error';
error: string | null;
conversationErrorsByProjectId: Record<string, Record<string, string>>;
creatingAgentIds: Record<string, true>;
load(): Promise<void>;
selectAgent(agentId: string): void;
@@ -51,7 +52,7 @@ export interface CodingWorkspaceState {
conversationId: string,
patch: { title?: string; archived?: boolean; unread?: boolean },
): Promise<CodingConversationMetadata>;
upsertConversation(conversation: CodingConversationMetadata): void;
upsertConversation(projectId: string, conversation: CodingConversationMetadata): void;
}
function enabledAgent(config: CodingProjectConfig | null, agentId: string | null): CodingProjectAgent | null {
@@ -76,6 +77,21 @@ function newestConversation(
.sort((left, right) => right.updatedAt.localeCompare(left.updatedAt))[0] ?? null;
}
function withConversationError(
errorsByProjectId: Record<string, Record<string, string>>,
projectId: string,
conversationId: string,
message: string | null,
): Record<string, Record<string, string>> {
const next = { ...errorsByProjectId };
const projectErrors = { ...(next[projectId] ?? {}) };
if (message) projectErrors[conversationId] = message;
else delete projectErrors[conversationId];
if (Object.keys(projectErrors).length > 0) next[projectId] = projectErrors;
else delete next[projectId];
return next;
}
function defaultDependencies(): CodingWorkspaceDependencies {
return {
listProjects: listCodingProjects,
@@ -103,6 +119,7 @@ export function createCodingWorkspaceStore(
selectedAgentId: null,
loadState: 'idle',
error: null,
conversationErrorsByProjectId: {},
creatingAgentIds: {},
async load() {
@@ -213,18 +230,36 @@ export function createCodingWorkspaceStore(
},
async patchConversation(conversationId, patch) {
set({ error: null });
const sourceProjectId = get().activeProjectId;
if (!sourceProjectId) throw new Error('当前没有可用的项目。');
set((current) => ({
conversationErrorsByProjectId: withConversationError(
current.conversationErrorsByProjectId,
sourceProjectId,
conversationId,
null,
),
}));
try {
const conversation = await deps.patchConversation(conversationId, patch);
get().upsertConversation(conversation);
get().upsertConversation(sourceProjectId, conversation);
return conversation;
} catch (error) {
set({ error: error instanceof Error ? error.message : String(error) });
const message = error instanceof Error ? error.message : String(error);
set((current) => ({
conversationErrorsByProjectId: withConversationError(
current.conversationErrorsByProjectId,
sourceProjectId,
conversationId,
message,
),
}));
throw error;
}
},
upsertConversation(conversation) {
upsertConversation(projectId, conversation) {
if (get().activeProjectId !== projectId) return;
set((current) => ({
conversations: [
conversation,