167 lines
4.6 KiB
TypeScript
167 lines
4.6 KiB
TypeScript
// src/tools/chat/summarize.ts
|
|
// Copyright (C) 2025 DTP Technologies, LLC
|
|
// All Rights Reserved
|
|
|
|
import type { ToolDefinition } from "../../lib/ai-client.js";
|
|
import type { IUser } from "../../models/user.js";
|
|
|
|
import {
|
|
DtpTool,
|
|
type ToolArguments,
|
|
type ToolContext,
|
|
} from "../../lib/tool.js";
|
|
import { ChatHistory } from "../../models/chat-history.js";
|
|
import { ChatSession, ChatSessionMode } from "../../models/chat-session.js";
|
|
import AiService from "../../services/ai.js";
|
|
|
|
export class ChatSummarizeTool extends DtpTool {
|
|
get name(): string {
|
|
return "ChatSummarizeTool";
|
|
}
|
|
get slug(): string {
|
|
return "chat-summarize";
|
|
}
|
|
get metadata() {
|
|
return {
|
|
name: this.definition.function.name || "chat_summarize",
|
|
category: "chat",
|
|
tags: ["summarize", "session", "overview", "recap"],
|
|
modes: [
|
|
ChatSessionMode.Plan,
|
|
ChatSessionMode.Build,
|
|
ChatSessionMode.Test,
|
|
ChatSessionMode.Ship,
|
|
ChatSessionMode.Develop,
|
|
],
|
|
};
|
|
}
|
|
|
|
public definition: ToolDefinition = {
|
|
type: "function",
|
|
function: {
|
|
name: "chat_summarize",
|
|
description:
|
|
"Summarize the conversation in the current or specified session. Returns a concise summary of the key topics, decisions, and outcomes discussed.",
|
|
parameters: {
|
|
type: "object",
|
|
properties: {
|
|
session_id: {
|
|
type: "string",
|
|
description:
|
|
"Optional: Session ID to summarize. If omitted, summarizes the current session.",
|
|
},
|
|
max_length: {
|
|
type: "number",
|
|
description:
|
|
"Optional: Maximum length of summary in words (default: 100).",
|
|
},
|
|
},
|
|
required: [],
|
|
},
|
|
},
|
|
};
|
|
|
|
public async execute(
|
|
context: ToolContext,
|
|
args: ToolArguments,
|
|
): Promise<string> {
|
|
const { session_id, max_length = 100 } = args;
|
|
const user = context.session.user as IUser;
|
|
const userId = user._id.toHexString();
|
|
const currentSessionId = context.session._id.toHexString();
|
|
|
|
const targetSessionId =
|
|
(session_id as string | undefined) || currentSessionId;
|
|
if (!targetSessionId) {
|
|
return this.error(
|
|
"MISSING_SESSION",
|
|
"No session ID provided and no current session context.",
|
|
);
|
|
}
|
|
|
|
try {
|
|
const session = await ChatSession.findOne({
|
|
_id: targetSessionId,
|
|
user: userId,
|
|
});
|
|
|
|
if (!session) {
|
|
return this.error(
|
|
"NOT_FOUND",
|
|
`Session not found: ${targetSessionId}`,
|
|
{
|
|
recoveryHint:
|
|
"Verify the session ID exists and belongs to the current user.",
|
|
},
|
|
);
|
|
}
|
|
|
|
const history = await ChatHistory.find({
|
|
session: targetSessionId,
|
|
status: "success",
|
|
})
|
|
.sort({ createdAt: 1 })
|
|
.lean();
|
|
|
|
if (history.length === 0) {
|
|
return this.success(
|
|
{ summary: "", turnCount: 0 },
|
|
"No conversation history found in this session.",
|
|
);
|
|
}
|
|
|
|
const conversationText = history
|
|
.map((turn) => {
|
|
let text = `User: ${turn.prompt}\n`;
|
|
if (turn.response?.message) {
|
|
text += `Assistant: ${turn.response.message}`;
|
|
}
|
|
return text;
|
|
})
|
|
.join("\n\n---\n\n");
|
|
|
|
const summaryPrompt = `Summarize the following conversation in approximately ${max_length} words or less. Focus on the main topics discussed, any decisions made, and key outcomes. Be concise and factual.
|
|
|
|
Conversation:
|
|
${conversationText}`;
|
|
|
|
this.log.debug("Generating summary", {
|
|
sessionId: targetSessionId,
|
|
turnCount: history.length,
|
|
maxLength: max_length,
|
|
});
|
|
|
|
const utilityClient = await AiService.getUtilityClient(userId);
|
|
const utilityModel = await AiService.getUtilityModel(userId);
|
|
|
|
const response = await utilityClient.chat(
|
|
[{ role: "user", content: summaryPrompt }],
|
|
[],
|
|
utilityModel,
|
|
);
|
|
|
|
const summary = response.content.trim();
|
|
return this.success({ summary }, summary);
|
|
} catch (error) {
|
|
const errorMessage =
|
|
error instanceof Error ? error.message : String(error);
|
|
|
|
this.log.error("Failed to summarize session", {
|
|
sessionId: targetSessionId,
|
|
error: errorMessage,
|
|
});
|
|
|
|
return this.error(
|
|
"OPERATION_FAILED",
|
|
`Failed to generate summary: ${errorMessage}`,
|
|
{
|
|
recoveryHint:
|
|
"Try again with a smaller max_length, or proceed without a summary.",
|
|
},
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
export default new ChatSummarizeTool();
|