70 lines
2.3 KiB
TypeScript
70 lines
2.3 KiB
TypeScript
// ==================== Conversation Summary ====================
|
|
|
|
/**
|
|
* OpenAI message format (used by director)
|
|
*/
|
|
export interface OpenAIMessage {
|
|
role: 'system' | 'user' | 'assistant';
|
|
content: string;
|
|
}
|
|
|
|
/**
|
|
* Regex used only for content stripping — removes the [senderName]: display prefix
|
|
* that message-converter.ts adds to role:'user' messages.
|
|
* Used cosmetically in summarizeConversation() output; NOT used for discrimination.
|
|
*/
|
|
const SENDER_PREFIX_RE = /^\[[^\]]+\]:\s*/;
|
|
|
|
/**
|
|
* Summarize conversation history for the director agent.
|
|
*
|
|
* In the director path, convertMessagesToOpenAI() is called without currentAgentId,
|
|
* so peer agent messages remain as role:'assistant'. The role field is therefore a
|
|
* reliable discriminator:
|
|
* - role:'user' → genuine human student message
|
|
* - role:'assistant' → agent turn
|
|
*
|
|
* message-converter.ts adds a [senderName]: display prefix to role:'user' content
|
|
* (e.g. "[You]: Can a 3D object be axisymmetric?"). This prefix is stripped from
|
|
* the summary output for readability — it is NOT used for discrimination.
|
|
*
|
|
* @param messages - OpenAI-format messages from the director path
|
|
* @param maxMessages - Maximum number of recent messages to include (default 10)
|
|
* @param maxContentLength - Maximum content length per message (default 200)
|
|
*/
|
|
export function summarizeConversation(
|
|
messages: OpenAIMessage[],
|
|
maxMessages = 10,
|
|
maxContentLength = 200,
|
|
): string {
|
|
if (messages.length === 0) {
|
|
return 'No conversation history yet.';
|
|
}
|
|
|
|
const recent = messages.slice(-maxMessages);
|
|
const lines = recent.map((msg) => {
|
|
let roleLabel: string;
|
|
let content: string;
|
|
|
|
if (msg.role === 'user') {
|
|
// In the director path, all role:'user' messages are genuine human turns.
|
|
// Strip the [senderName]: display prefix added by message-converter for readability.
|
|
roleLabel = 'Student (Human)';
|
|
content = msg.content.replace(SENDER_PREFIX_RE, '');
|
|
} else if (msg.role === 'assistant') {
|
|
roleLabel = 'Agent';
|
|
content = msg.content;
|
|
} else {
|
|
roleLabel = 'System';
|
|
content = msg.content;
|
|
}
|
|
|
|
const truncated =
|
|
content.length > maxContentLength ? content.slice(0, maxContentLength) + '...' : content;
|
|
|
|
return `[${roleLabel}] ${truncated}`;
|
|
});
|
|
|
|
return lines.join('\n');
|
|
}
|