-
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 all commits
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,115 @@ 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 currentSession = runner.getSession(); | ||
|
|
||
| "/new": async (chatId, _userId) => { | ||
| const summary = await sessionManager.saveAndReset(chatId); | ||
| return `✅ Session saved to memory. | ||
| // Save current session to memory if it has events | ||
| if (memoryService && currentSession.events.length > 0) { | ||
| await memoryService.addSessionToMemory(currentSession); | ||
| } | ||
|
|
||
| // 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); | ||
|
|
||
| return `✅ Session saved to memory. | ||
|
|
||
| 📝 Summary: ${summary} | ||
|
|
||
| 🆕 New session started!`; | ||
| }, | ||
| }, | ||
|
|
||
| "/reset": async (_chatId, _userId) => { | ||
| const currentSession = runner.getSession(); | ||
|
|
||
| // 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
|
||
|
|
||
| "/reset": async (chatId, _userId) => { | ||
| sessionManager.reset(chatId); | ||
| return "🔄 Session cleared (not saved). Fresh start!"; | ||
| }, | ||
| return "🔄 Session cleared (not saved). Fresh start!"; | ||
| }, | ||
|
|
||
| "/help": async (_chatId, _userId) => { | ||
| return `📚 Available commands: | ||
| "/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 +357,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 +391,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.
Calling
runner.setSession(newSession)on a sharedrunnerinstance will globally change the active session for all Telegram users. If one user triggers the/newcommand, it will effectively reset the conversation for every other user currently interacting with the bot. This is a significant issue if the application is intended for multi-user scenarios, where session state must be isolated perchatId. However, if this application is designed for single-user or paired-user contexts (e.g., a personal bot), this behavior might be acceptable as per repository guidelines.References