feat: organize project conversations and add coding teacher side chat

This commit is contained in:
2026-09-22 12:30:26 +08:00
parent 2f82b9f79c
commit 9242a40d87
45 changed files with 2987 additions and 1137 deletions

View File

@@ -48,6 +48,8 @@ interface AcceptanceRecord {
}
export interface CodingConversationServiceOptions {
readHistory?(projectId: string, conversation: CodingConversationV2): Promise<ConversationSnapshot>;
onDelete?(projectId: string, conversationId: string): Promise<void>;
archiveSession?(input: {
projectId: string;
sessionKey: string;
@@ -320,14 +322,14 @@ export class CodingConversationService {
async createConversation(input: {
projectId?: string;
agentId: unknown;
title: unknown;
agentId?: unknown;
title?: unknown;
}): Promise<CodingConversationV2> {
const project = input.projectId
? await this.projects.getProject(input.projectId)
: await this.projects.requireActiveProject();
const config = await this.projects.getConfig(project.id);
const agentId = requiredString(input.agentId, 'Agent id', 64);
const agentId = requiredString(input.agentId ?? config.config.defaultAgentId, 'Agent id', 64);
const agent = config.config.agents.find((candidate) => (
candidate.id === agentId && candidate.enabled && !candidate.archivedAt
));
@@ -385,6 +387,7 @@ export class CodingConversationService {
runtimeError(error);
}
await this.archiveSession(project.id, conversation.sessionKey);
await this.options.onDelete?.(project.id, conversationId);
await persist(() => this.projects.conversationStore(project.path).delete(conversationId));
this.titleContexts.delete(conversationId);
this.prepareFlights.delete(conversationId);
@@ -394,6 +397,12 @@ export class CodingConversationService {
}
async getSnapshot(conversationId: string): Promise<ConversationSnapshot> {
const { project, conversation } = await this.projects.findActiveConversation(conversationId);
const { config } = await this.projects.getConfig(project.id);
const agent = config.agents.find((item) => item.id === conversation.agentId);
if (this.options.readHistory && (!agent?.enabled || agent.archivedAt)) {
return await this.options.readHistory(project.id, conversation);
}
await this.ensurePrepared(conversationId);
try {
return await this.runtime.getSnapshot(conversationId);