feat: organize project conversations and add coding teacher side chat
This commit is contained in:
@@ -30,7 +30,7 @@ interface CodingWorkspaceDependencies {
|
||||
listConversations(projectId: string): Promise<CodingConversationMetadata[]>;
|
||||
createConversation(input: {
|
||||
projectId: string;
|
||||
agentId: string;
|
||||
agentId?: string;
|
||||
title: string;
|
||||
}): Promise<CodingConversationMetadata>;
|
||||
patchConversation(
|
||||
@@ -74,7 +74,7 @@ export interface CodingWorkspaceState {
|
||||
removeProject(projectId: string): Promise<void>;
|
||||
selectAgent(agentId: string): void;
|
||||
ensureConversation(agentId: string): Promise<CodingConversationMetadata>;
|
||||
createConversation(agentId: string): Promise<CodingConversationMetadata>;
|
||||
createConversation(agentId?: string): Promise<CodingConversationMetadata>;
|
||||
patchConversation(
|
||||
conversationId: string,
|
||||
patch: { title?: string; archived?: boolean; unread?: boolean },
|
||||
@@ -90,7 +90,8 @@ function enabledAgent(config: CodingProjectConfig | null, agentId: string | null
|
||||
}
|
||||
|
||||
function firstEnabledAgent(config: CodingProjectConfig): CodingProjectAgent | null {
|
||||
return config.agents.find((agent) => agent.enabled && !agent.archivedAt && agent.pinned)
|
||||
return config.agents.find((agent) => agent.id === config.defaultAgentId && agent.enabled && !agent.archivedAt)
|
||||
?? config.agents.find((agent) => agent.enabled && !agent.archivedAt && agent.pinned)
|
||||
?? config.agents.find((agent) => agent.enabled && !agent.archivedAt)
|
||||
?? null;
|
||||
}
|
||||
@@ -142,6 +143,8 @@ export function createCodingWorkspaceStore(
|
||||
let loadGeneration = 0;
|
||||
let metadataRevision = 0;
|
||||
let metadataTail = Promise.resolve();
|
||||
let activationIntent = 0;
|
||||
let activationTail: Promise<unknown> = Promise.resolve();
|
||||
const refreshFlights = new Map<string, { dirty: boolean; promise: Promise<void> }>();
|
||||
|
||||
return createStore<CodingWorkspaceState>((set, get) => ({
|
||||
@@ -252,8 +255,13 @@ export function createCodingWorkspaceStore(
|
||||
},
|
||||
|
||||
async setActiveProject(projectId) {
|
||||
const project = await deps.setActiveProject(projectId);
|
||||
await get().load();
|
||||
const intent = ++activationIntent;
|
||||
++loadGeneration;
|
||||
loadFlight = null;
|
||||
const activation = activationTail.catch(() => undefined).then(() => deps.setActiveProject(projectId));
|
||||
activationTail = activation;
|
||||
const project = await activation;
|
||||
if (intent === activationIntent) await get().load();
|
||||
return project;
|
||||
},
|
||||
|
||||
@@ -275,14 +283,16 @@ export function createCodingWorkspaceStore(
|
||||
|
||||
async createConversation(agentId) {
|
||||
const state = get();
|
||||
if (!state.activeProject || !enabledAgent(state.config, agentId)) {
|
||||
agentId ??= state.config?.defaultAgentId ?? (state.config ? firstEnabledAgent(state.config)?.id : undefined);
|
||||
if (!state.activeProject || !enabledAgent(state.config, agentId ?? null)) {
|
||||
throw new Error('当前项目没有可用的智能体。');
|
||||
}
|
||||
const flightKey = `${state.activeProject.id}:${agentId}`;
|
||||
const resolvedAgentId = agentId!;
|
||||
const flightKey = `${state.activeProject.id}:${resolvedAgentId}`;
|
||||
const existingFlight = conversationFlights.get(flightKey);
|
||||
if (existingFlight) return await existingFlight;
|
||||
set((current) => ({
|
||||
creatingAgentIds: { ...current.creatingAgentIds, [agentId]: true },
|
||||
creatingAgentIds: { ...current.creatingAgentIds, [resolvedAgentId]: true },
|
||||
error: null,
|
||||
}));
|
||||
let flight: Promise<CodingConversationMetadata>;
|
||||
@@ -307,7 +317,7 @@ export function createCodingWorkspaceStore(
|
||||
conversationFlights.delete(flightKey);
|
||||
set((current) => {
|
||||
const creatingAgentIds = { ...current.creatingAgentIds };
|
||||
delete creatingAgentIds[agentId];
|
||||
delete creatingAgentIds[resolvedAgentId];
|
||||
return { creatingAgentIds };
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user