fix(coding): scope metadata updates by project
This commit is contained in:
@@ -96,6 +96,9 @@ export function CodingChatPanel({
|
||||
const selectedAgentId = useCodingWorkspaceStore((state) => state.selectedAgentId);
|
||||
const workspaceLoadState = useCodingWorkspaceStore((state) => state.loadState);
|
||||
const workspaceError = useCodingWorkspaceStore((state) => state.error);
|
||||
const conversationErrorsByProjectId = useCodingWorkspaceStore(
|
||||
(state) => state.conversationErrorsByProjectId,
|
||||
);
|
||||
const creatingAgentIds = useCodingWorkspaceStore((state) => state.creatingAgentIds);
|
||||
const loadWorkspace = useCodingWorkspaceStore((state) => state.load);
|
||||
const selectAgent = useCodingWorkspaceStore((state) => state.selectAgent);
|
||||
@@ -149,6 +152,9 @@ export function CodingChatPanel({
|
||||
&& !conversation.archivedAt
|
||||
)) ?? null;
|
||||
const targetConversationId = selectedConversation?.id ?? null;
|
||||
const conversationMetadataError = activeProject && targetConversationId
|
||||
? conversationErrorsByProjectId[activeProject.id]?.[targetConversationId] ?? null
|
||||
: null;
|
||||
const provisionalDraftKey = activeProject && selectedAgent
|
||||
? `new:${activeProject.id}:${selectedAgent.id}`
|
||||
: null;
|
||||
@@ -340,9 +346,10 @@ export function CodingChatPanel({
|
||||
const sourceAgentId = selectedAgent.id;
|
||||
const sourceConversationId = targetConversationId;
|
||||
const forked = await forkCodingConversation(sourceConversationId, sourceEntryId);
|
||||
upsertConversation(forked);
|
||||
primeConversation(createLocalConversationSnapshot(sourceProjectId, forked));
|
||||
const workspace = codingWorkspaceStore.getState();
|
||||
if (workspace.activeProjectId !== sourceProjectId) return;
|
||||
upsertConversation(sourceProjectId, forked);
|
||||
primeConversation(createLocalConversationSnapshot(sourceProjectId, forked));
|
||||
const selectedId = codingConversationStore.getState().selectedConversationId;
|
||||
if (workspace.activeProjectId === sourceProjectId
|
||||
&& workspace.selectedAgentId === sourceAgentId
|
||||
@@ -656,10 +663,12 @@ export function CodingChatPanel({
|
||||
onOpenSettings={onOpenProjectSettings}
|
||||
/>
|
||||
|
||||
{(workspaceError || connectionError) && (
|
||||
{(workspaceError || conversationMetadataError || connectionError) && (
|
||||
<div className="mx-4 mt-3 flex min-h-10 items-center gap-2 rounded-xl bg-destructive/5 px-3 py-2 text-xs text-destructive sm:mx-5">
|
||||
<CircleAlert className="h-4 w-4 shrink-0" aria-hidden="true" />
|
||||
<p className="min-w-0 flex-1 text-pretty">{workspaceError ?? connectionError}</p>
|
||||
<p className="min-w-0 flex-1 text-pretty">
|
||||
{workspaceError ?? conversationMetadataError ?? connectionError}
|
||||
</p>
|
||||
{workspaceError && (
|
||||
<Button
|
||||
type="button"
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user