Hausmeister: Inline-Buttons fuer Memory-Kandidaten + /memory Befehl
This commit is contained in:
parent
1fc197dd13
commit
f9ea49013a
2 changed files with 85 additions and 3 deletions
|
|
@ -155,6 +155,32 @@ def log_message(session_id: str, role: str, content: str, source: str = None, me
|
||||||
_post(f"/sessions/{session_id}/messages", data)
|
_post(f"/sessions/{session_id}/messages", data)
|
||||||
|
|
||||||
|
|
||||||
|
def get_candidates() -> list[dict]:
|
||||||
|
"""Holt alle offenen Memory-Kandidaten."""
|
||||||
|
result = _get("/memory", {"status": "candidate", "limit": 20})
|
||||||
|
if result and "items" in result:
|
||||||
|
return result["items"]
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
def activate_candidate(item_id: int) -> bool:
|
||||||
|
"""Setzt einen Kandidaten auf aktiv."""
|
||||||
|
result = _patch(f"/memory/{item_id}", {"status": "active"})
|
||||||
|
return bool(result and result.get("ok"))
|
||||||
|
|
||||||
|
|
||||||
|
def delete_candidate(item_id: int) -> bool:
|
||||||
|
"""Loescht einen Kandidaten."""
|
||||||
|
_ensure_config()
|
||||||
|
if not _base_url:
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
r = requests.delete(f"{_base_url}/memory/{item_id}", headers=_headers(), timeout=5)
|
||||||
|
return r.ok
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def get_active_memory() -> list[dict]:
|
def get_active_memory() -> list[dict]:
|
||||||
"""Holt alle aktiven Memory-Items fuer den System-Prompt."""
|
"""Holt alle aktiven Memory-Items fuer den System-Prompt."""
|
||||||
result = _get("/memory", {"status": "active", "limit": 100})
|
result = _get("/memory", {"status": "active", "limit": 100})
|
||||||
|
|
|
||||||
|
|
@ -37,9 +37,9 @@ def _release_lock():
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
from telegram import BotCommand, Update, ReplyKeyboardMarkup, KeyboardButton
|
from telegram import BotCommand, Update, ReplyKeyboardMarkup, KeyboardButton, InlineKeyboardMarkup, InlineKeyboardButton
|
||||||
from telegram.ext import (
|
from telegram.ext import (
|
||||||
Application, CommandHandler, MessageHandler, filters, ContextTypes,
|
Application, CommandHandler, MessageHandler, CallbackQueryHandler, filters, ContextTypes,
|
||||||
)
|
)
|
||||||
|
|
||||||
BOT_COMMANDS = [
|
BOT_COMMANDS = [
|
||||||
|
|
@ -52,6 +52,7 @@ BOT_COMMANDS = [
|
||||||
BotCommand("report", "Tagesbericht"),
|
BotCommand("report", "Tagesbericht"),
|
||||||
BotCommand("check", "Monitoring-Check"),
|
BotCommand("check", "Monitoring-Check"),
|
||||||
BotCommand("feeds", "Feed-Status & Artikel heute"),
|
BotCommand("feeds", "Feed-Status & Artikel heute"),
|
||||||
|
BotCommand("memory", "Offene Memory-Kandidaten"),
|
||||||
BotCommand("start", "Hilfe anzeigen"),
|
BotCommand("start", "Hilfe anzeigen"),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -284,6 +285,47 @@ async def cmd_feeds(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
await update.message.reply_text(f"Fehler: {e}")
|
await update.message.reply_text(f"Fehler: {e}")
|
||||||
|
|
||||||
|
def _memory_buttons(item_id: int) -> InlineKeyboardMarkup:
|
||||||
|
return InlineKeyboardMarkup([[
|
||||||
|
InlineKeyboardButton("✅ Merken", callback_data=f"mem_activate:{item_id}"),
|
||||||
|
InlineKeyboardButton("❌ Verwerfen", callback_data=f"mem_delete:{item_id}"),
|
||||||
|
]])
|
||||||
|
|
||||||
|
|
||||||
|
async def cmd_memory(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
|
||||||
|
if not _authorized(update):
|
||||||
|
return
|
||||||
|
candidates = memory_client.get_candidates()
|
||||||
|
if not candidates:
|
||||||
|
await update.message.reply_text("Keine offenen Kandidaten.")
|
||||||
|
return
|
||||||
|
for item in candidates:
|
||||||
|
text = f"📝 [{item['scope']}/{item['kind']}]\n{item['content']}"
|
||||||
|
await update.message.reply_text(text, reply_markup=_memory_buttons(item["id"]))
|
||||||
|
|
||||||
|
|
||||||
|
async def handle_memory_callback(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
|
||||||
|
query = update.callback_query
|
||||||
|
await query.answer()
|
||||||
|
data = query.data or ""
|
||||||
|
|
||||||
|
if data.startswith("mem_activate:"):
|
||||||
|
item_id = int(data.split(":")[1])
|
||||||
|
ok = memory_client.activate_candidate(item_id)
|
||||||
|
if ok:
|
||||||
|
await query.edit_message_text("✅ Aktiviert: " + query.message.text.split("\n", 1)[-1])
|
||||||
|
else:
|
||||||
|
await query.edit_message_text("Fehler beim Aktivieren.")
|
||||||
|
|
||||||
|
elif data.startswith("mem_delete:"):
|
||||||
|
item_id = int(data.split(":")[1])
|
||||||
|
ok = memory_client.delete_candidate(item_id)
|
||||||
|
if ok:
|
||||||
|
await query.edit_message_text("🗑 Verworfen.")
|
||||||
|
else:
|
||||||
|
await query.edit_message_text("Fehler beim Loeschen.")
|
||||||
|
|
||||||
|
|
||||||
async def handle_message(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
|
async def handle_message(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
|
||||||
"""Button-Presses und Freitext-Fragen verarbeiten."""
|
"""Button-Presses und Freitext-Fragen verarbeiten."""
|
||||||
if not _authorized(update):
|
if not _authorized(update):
|
||||||
|
|
@ -311,12 +353,24 @@ async def handle_message(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
|
||||||
|
|
||||||
await update.message.reply_text("🤔 Denke nach...")
|
await update.message.reply_text("🤔 Denke nach...")
|
||||||
try:
|
try:
|
||||||
|
candidates_before = {c["id"] for c in memory_client.get_candidates()}
|
||||||
handlers = context.get_tool_handlers(session_id=session_id)
|
handlers = context.get_tool_handlers(session_id=session_id)
|
||||||
answer = llm.ask_with_tools(text, handlers, session_id=session_id)
|
answer = llm.ask_with_tools(text, handlers, session_id=session_id)
|
||||||
if session_id:
|
if session_id:
|
||||||
memory_client.log_message(session_id, "user", text)
|
memory_client.log_message(session_id, "user", text)
|
||||||
memory_client.log_message(session_id, "assistant", answer)
|
memory_client.log_message(session_id, "assistant", answer)
|
||||||
await update.message.reply_text(answer[:4000], reply_markup=KEYBOARD)
|
|
||||||
|
candidates_after = memory_client.get_candidates()
|
||||||
|
new_candidates = [c for c in candidates_after if c["id"] not in candidates_before]
|
||||||
|
|
||||||
|
if new_candidates:
|
||||||
|
c = new_candidates[0]
|
||||||
|
await update.message.reply_text(
|
||||||
|
answer[:4000] + "\n\n📝 " + c["content"],
|
||||||
|
reply_markup=_memory_buttons(c["id"]),
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
await update.message.reply_text(answer[:4000], reply_markup=KEYBOARD)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.exception("Fehler bei Freitext")
|
log.exception("Fehler bei Freitext")
|
||||||
await update.message.reply_text(f"Fehler: {e}")
|
await update.message.reply_text(f"Fehler: {e}")
|
||||||
|
|
@ -345,6 +399,8 @@ def main():
|
||||||
app.add_handler(CommandHandler("report", cmd_report))
|
app.add_handler(CommandHandler("report", cmd_report))
|
||||||
app.add_handler(CommandHandler("check", cmd_check))
|
app.add_handler(CommandHandler("check", cmd_check))
|
||||||
app.add_handler(CommandHandler("feeds", cmd_feeds))
|
app.add_handler(CommandHandler("feeds", cmd_feeds))
|
||||||
|
app.add_handler(CommandHandler("memory", cmd_memory))
|
||||||
|
app.add_handler(CallbackQueryHandler(handle_memory_callback, pattern=r"^mem_"))
|
||||||
app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message))
|
app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message))
|
||||||
|
|
||||||
async def post_init(application):
|
async def post_init(application):
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue