-
Notifications
You must be signed in to change notification settings - Fork 0
remove SessionManager and update TelegramService to handle session management directly #19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,9 +4,12 @@ | |
| */ | ||
|
|
||
| import { | ||
| type BaseSessionService, | ||
| createSamplingHandler, | ||
| type EnhancedRunner, | ||
| extractTextFromContent, | ||
| type LlmRequest, | ||
| type MemoryService, | ||
| } from "@iqai/adk"; | ||
| import { createClawdAgent } from "../agents/agent.js"; | ||
| import { getTelegramAgent } from "../agents/telegram-agent/agent.js"; | ||
|
|
@@ -19,7 +22,6 @@ import { | |
| initScheduler, | ||
| stopScheduler, | ||
| } from "./SchedulerService.js"; | ||
| import { sessionManager } from "./SessionManager.js"; | ||
|
|
||
| const log = createLogger("Telegram"); | ||
|
|
||
|
|
@@ -227,51 +229,122 @@ adk-claw pairing approve telegram ${code} | |
| Code expires in 1 hour.`; | ||
| } | ||
|
|
||
| const commands: Record<string, CommandHandler> = { | ||
| "/start": async (chatId, userId) => { | ||
| const config = getRawConfig(); | ||
| /** | ||
| * Format duration between a unix timestamp (seconds) and now | ||
| */ | ||
| function formatDuration(startTimestamp: number): string { | ||
| const diffMs = Date.now() - startTimestamp * 1000; | ||
| const minutes = Math.floor(diffMs / 60000); | ||
| const hours = Math.floor(minutes / 60); | ||
|
|
||
| if (hours > 0) { | ||
| return `${hours}h ${minutes % 60}m`; | ||
| } | ||
| return `${minutes}m`; | ||
| } | ||
|
|
||
| /** | ||
| * Create command handlers bound to ADK session lifecycle. | ||
| * Uses sessionService.createSession / deleteSession and runner.setSession | ||
| * to properly create/destroy ADK sessions instead of local state. | ||
| */ | ||
| function createCommands(deps: { | ||
| runner: EnhancedRunner; | ||
| sessionService: BaseSessionService; | ||
| memoryService?: MemoryService; | ||
| }): Record<string, CommandHandler> { | ||
| const { runner, sessionService, memoryService } = deps; | ||
|
|
||
| return { | ||
| "/start": async (_chatId, userId) => { | ||
| const config = getRawConfig(); | ||
|
|
||
| // Check if user is already allowed | ||
| if (isAllowed("telegram", userId)) { | ||
| return `👋 Welcome back! | ||
| // Check if user is already allowed | ||
| if (isAllowed("telegram", userId)) { | ||
| return `👋 Welcome back! | ||
|
|
||
| I'm ${config.agent.name}, your personal AI assistant. | ||
|
|
||
| Commands: | ||
| /new - Save session & start fresh | ||
| /reset - Clear session without saving | ||
| /help - Show available commands`; | ||
| } | ||
| } | ||
|
|
||
| // User needs pairing | ||
| return getPairingResponse(userId, undefined, chatId); | ||
| }, | ||
| // User needs pairing | ||
| return getPairingResponse(userId, undefined, _chatId); | ||
| }, | ||
|
|
||
| "/new": async (chatId, _userId) => { | ||
| const summary = await sessionManager.saveAndReset(chatId); | ||
| return `✅ Session saved to memory. | ||
| "/new": async (_chatId, _userId) => { | ||
| const currentSession = runner.getSession(); | ||
|
|
||
| // Save current session to memory if it has events | ||
| if (memoryService && currentSession.events.length > 0) { | ||
| const freshSession = await sessionService.getSession( | ||
| currentSession.appName, | ||
| currentSession.userId, | ||
| currentSession.id, | ||
| ); | ||
| if (freshSession) { | ||
| await memoryService.addSessionToMemory(freshSession); | ||
| } | ||
| } | ||
|
|
||
| // Derive summary from ADK session events | ||
| const eventCount = currentSession.events.length; | ||
| let summary = "No conversation to save."; | ||
| if (eventCount > 0) { | ||
| const firstTimestamp = currentSession.events[0].timestamp; | ||
| const duration = formatDuration(firstTimestamp); | ||
| summary = `${eventCount} events over ${duration}`; | ||
| } | ||
|
|
||
| // Create a new ADK session and swap it into the runner | ||
| const newSession = await sessionService.createSession( | ||
| currentSession.appName, | ||
| currentSession.userId, | ||
| ); | ||
| runner.setSession(newSession); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Calling References
|
||
|
|
||
| return `✅ Session saved to memory. | ||
|
|
||
| 📝 Summary: ${summary} | ||
|
|
||
| 🆕 New session started!`; | ||
| }, | ||
| }, | ||
|
|
||
| "/reset": async (chatId, _userId) => { | ||
| sessionManager.reset(chatId); | ||
| return "🔄 Session cleared (not saved). Fresh start!"; | ||
| }, | ||
| "/reset": async (_chatId, _userId) => { | ||
| const currentSession = runner.getSession(); | ||
|
|
||
| "/help": async (_chatId, _userId) => { | ||
| return `📚 Available commands: | ||
| // Delete the old session without saving to memory | ||
| await sessionService.deleteSession( | ||
| currentSession.appName, | ||
| currentSession.userId, | ||
| currentSession.id, | ||
| ); | ||
|
|
||
| // Create a fresh ADK session | ||
| const newSession = await sessionService.createSession( | ||
| currentSession.appName, | ||
| currentSession.userId, | ||
| ); | ||
| runner.setSession(newSession); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar to the References
|
||
|
|
||
| return "🔄 Session cleared (not saved). Fresh start!"; | ||
| }, | ||
|
|
||
| "/help": async (_chatId, _userId) => { | ||
| return `📚 Available commands: | ||
|
|
||
| /start - Start the bot and pair | ||
| /new - Save session & start fresh | ||
| /reset - Clear session without saving | ||
| /help - Show this help message | ||
|
|
||
| Just send a message to chat with me!`; | ||
| }, | ||
| }; | ||
| }, | ||
| }; | ||
| } | ||
|
|
||
| /** | ||
| * Start the Telegram bot with MCP sampling | ||
|
|
@@ -291,10 +364,8 @@ export async function startTelegramBot(): Promise<void> { | |
| channel: "telegram", | ||
| }); | ||
|
|
||
| // Wire memory service into session manager for /new command | ||
| if (memoryService) { | ||
| sessionManager.setDeps(memoryService, sessionService, session); | ||
| } | ||
| // Create command handlers bound to ADK session lifecycle | ||
| const commands = createCommands({ runner, sessionService, memoryService }); | ||
|
|
||
| // Create sampling handler with command detection | ||
| const samplingHandler = createSamplingHandler( | ||
|
|
@@ -327,17 +398,9 @@ export async function startTelegramBot(): Promise<void> { | |
| registerUserCommands(config.telegramBotToken, chatId); | ||
| } | ||
|
|
||
| // Track in session | ||
| sessionManager.getOrCreate(chatId, userId); | ||
| sessionManager.addMessage(chatId, "user", messageText); | ||
|
|
||
| // Get response from agent | ||
| // Get response from agent (ADK tracks events in session automatically) | ||
| try { | ||
| const response = await runner.ask(messageText); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The removal of References
|
||
|
|
||
| // Track response | ||
| sessionManager.addMessage(chatId, "assistant", response); | ||
|
|
||
| return response; | ||
| } catch (error) { | ||
| log.error( | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fetching a 'fresh' session from
sessionServiceis redundant and risks a race condition. Therunnerholds the most up-to-date session incurrentSession. Re-fetching from the persistence layer could retrieve a stale session if recent events aren't persisted yet, leading to data loss when saving to memory. It's safer to usecurrentSessiondirectly.