feat(coding): add conversation archive and first-message titles
This commit is contained in:
@@ -10,6 +10,8 @@ export const CODING_CONVERSATIONS_PATH = '.makelore/conversations.json';
|
||||
export interface CodingConversationV2 extends CodingConversationMetadata, ConversationModelState {
|
||||
piSessionId?: string;
|
||||
sessionKey?: string;
|
||||
titleMode?: 'automatic' | 'manual';
|
||||
autoTitleSet?: boolean;
|
||||
}
|
||||
|
||||
export interface CodingConversationFileV2 {
|
||||
@@ -22,6 +24,7 @@ export interface CreateCodingConversationInput {
|
||||
title: string;
|
||||
model: ProductModelRef | null;
|
||||
modelResolution: 'resolved' | 'required';
|
||||
titleMode?: 'automatic' | 'manual';
|
||||
}
|
||||
|
||||
export interface PiSessionBinding {
|
||||
@@ -83,6 +86,8 @@ function normalizeConversation(value: unknown): CodingConversationV2 {
|
||||
id,
|
||||
agentId,
|
||||
title,
|
||||
titleMode: record.titleMode === 'automatic' ? 'automatic' : 'manual',
|
||||
autoTitleSet: record.titleMode === 'automatic' ? record.autoTitleSet === true : true,
|
||||
...normalizeModelState(record),
|
||||
...(piSessionId ? { piSessionId } : {}),
|
||||
...(sessionKey ? { sessionKey } : {}),
|
||||
@@ -139,7 +144,9 @@ export function createCodingConversationStore(
|
||||
file: CodingConversationFileV2;
|
||||
}>): Promise<T> {
|
||||
const execute = async () => {
|
||||
const change = await operation(await readNow());
|
||||
const current = await readNow();
|
||||
const change = await operation(current);
|
||||
if (change.file === current) return change.result;
|
||||
const normalized = normalizeCodingConversationFileV2(change.file);
|
||||
await writer(conversationFilePath(projectPath), normalized);
|
||||
return change.result;
|
||||
@@ -167,6 +174,8 @@ export function createCodingConversationStore(
|
||||
id: createId(),
|
||||
agentId: input.agentId,
|
||||
title: input.title,
|
||||
titleMode: input.titleMode ?? 'manual',
|
||||
autoTitleSet: input.titleMode !== 'automatic',
|
||||
model: input.model,
|
||||
modelResolution: input.modelResolution,
|
||||
archivedAt: null,
|
||||
@@ -192,10 +201,10 @@ export function createCodingConversationStore(
|
||||
if (!current) throw new Error('Conversation does not exist');
|
||||
const updated = normalizeConversation({
|
||||
...current,
|
||||
...(patch.title !== undefined ? { title: patch.title } : {}),
|
||||
...(patch.title !== undefined ? { title: patch.title, titleMode: 'manual', autoTitleSet: true } : {}),
|
||||
...(patch.archivedAt !== undefined ? { archivedAt: patch.archivedAt } : {}),
|
||||
...(patch.unread !== undefined ? { unread: patch.unread } : {}),
|
||||
updatedAt: now(),
|
||||
updatedAt: patch.archivedAt !== undefined || patch.unread !== undefined ? now() : current.updatedAt,
|
||||
});
|
||||
return {
|
||||
result: updated,
|
||||
@@ -207,6 +216,16 @@ export function createCodingConversationStore(
|
||||
});
|
||||
},
|
||||
|
||||
async setFirstMessageTitle(conversationId: string, title: string) {
|
||||
return await mutate(async (file) => {
|
||||
const current = file.conversations.find((item) => item.id === conversationId);
|
||||
if (!current || current.titleMode !== 'automatic' || current.autoTitleSet) return { result: null, file };
|
||||
const updated = { ...current, title, autoTitleSet: true };
|
||||
return { result: updated, file: { ...file,
|
||||
conversations: file.conversations.map((item) => item.id === conversationId ? updated : item) } };
|
||||
});
|
||||
},
|
||||
|
||||
async setModelState(
|
||||
conversationId: string,
|
||||
modelState: ConversationModelState,
|
||||
|
||||
Reference in New Issue
Block a user