refactor: split api.py monolith into 19 route modules (Phase B)
Split 3,598-line api.py into thin orchestrator (128 lines) + 19 route
modules in bot/routes/:
core.py (7 routes), mood.py (10), language.py (3), evil_mode.py (6),
bipolar_mode.py (9), gpu.py (2), bot_actions.py (4), autonomous.py (13),
profile_picture.py (26), manual_send.py (3), servers.py (6),
figurines.py (5), dms.py (18), image_generation.py (4), chat.py (1),
config.py (7), logging_config.py (9), voice.py (3), memory.py (10)
All 146 routes verified present via test_route_split.py (149 tests).
21/21 regression tests (test_config_state.py) pass.
Monolith backup: bot/api_monolith_backup.py (revert: cp it to api.py).
2026-04-15 11:38:14 +03:00
|
|
|
"""Cheshire Cat memory management routes."""
|
|
|
|
|
|
2026-05-17 11:31:26 +03:00
|
|
|
import asyncio
|
|
|
|
|
import time
|
|
|
|
|
from datetime import datetime
|
refactor: split api.py monolith into 19 route modules (Phase B)
Split 3,598-line api.py into thin orchestrator (128 lines) + 19 route
modules in bot/routes/:
core.py (7 routes), mood.py (10), language.py (3), evil_mode.py (6),
bipolar_mode.py (9), gpu.py (2), bot_actions.py (4), autonomous.py (13),
profile_picture.py (26), manual_send.py (3), servers.py (6),
figurines.py (5), dms.py (18), image_generation.py (4), chat.py (1),
config.py (7), logging_config.py (9), voice.py (3), memory.py (10)
All 146 routes verified present via test_route_split.py (149 tests).
21/21 regression tests (test_config_state.py) pass.
Monolith backup: bot/api_monolith_backup.py (revert: cp it to api.py).
2026-04-15 11:38:14 +03:00
|
|
|
from typing import Optional
|
|
|
|
|
from fastapi import APIRouter, Form
|
2026-04-15 15:43:18 +03:00
|
|
|
from fastapi.responses import JSONResponse
|
refactor: split api.py monolith into 19 route modules (Phase B)
Split 3,598-line api.py into thin orchestrator (128 lines) + 19 route
modules in bot/routes/:
core.py (7 routes), mood.py (10), language.py (3), evil_mode.py (6),
bipolar_mode.py (9), gpu.py (2), bot_actions.py (4), autonomous.py (13),
profile_picture.py (26), manual_send.py (3), servers.py (6),
figurines.py (5), dms.py (18), image_generation.py (4), chat.py (1),
config.py (7), logging_config.py (9), voice.py (3), memory.py (10)
All 146 routes verified present via test_route_split.py (149 tests).
21/21 regression tests (test_config_state.py) pass.
Monolith backup: bot/api_monolith_backup.py (revert: cp it to api.py).
2026-04-15 11:38:14 +03:00
|
|
|
import globals
|
|
|
|
|
from routes.models import MemoryDeleteRequest, MemoryEditRequest, MemoryCreateRequest
|
|
|
|
|
from utils.logger import get_logger
|
|
|
|
|
|
|
|
|
|
logger = get_logger('api')
|
|
|
|
|
|
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/memory/status")
|
|
|
|
|
async def get_cat_memory_status():
|
feat(memory): add automated nightly consolidation at 4:00 AM UTC
Step 2 of memory system overhaul: automated scheduling.
- New consolidation_scheduler.py: run_nightly_consolidation() function that
checks Cat health, triggers consolidation via WebSocket, and tracks
run history with success/failure stats
- bot.py on_ready: register APScheduler cron job (hour=4, minute=0)
alongside the existing daily DM analysis job
- routes/memory.py: expose consolidation status (last_run, last_result,
last_error, is_running, total_runs, successful_runs) in the
/memory/status API response
- Web UI: show consolidation schedule info (last run time, success/fail,
run counts) below the manual consolidate button, with 'running now'
indicator when active
The 'sleep consolidation' metaphor is now actually automated instead of
being manual-only.
2026-05-15 13:54:54 +03:00
|
|
|
"""Get Cheshire Cat connection status, feature flag, and consolidation state."""
|
refactor: split api.py monolith into 19 route modules (Phase B)
Split 3,598-line api.py into thin orchestrator (128 lines) + 19 route
modules in bot/routes/:
core.py (7 routes), mood.py (10), language.py (3), evil_mode.py (6),
bipolar_mode.py (9), gpu.py (2), bot_actions.py (4), autonomous.py (13),
profile_picture.py (26), manual_send.py (3), servers.py (6),
figurines.py (5), dms.py (18), image_generation.py (4), chat.py (1),
config.py (7), logging_config.py (9), voice.py (3), memory.py (10)
All 146 routes verified present via test_route_split.py (149 tests).
21/21 regression tests (test_config_state.py) pass.
Monolith backup: bot/api_monolith_backup.py (revert: cp it to api.py).
2026-04-15 11:38:14 +03:00
|
|
|
from utils.cat_client import cat_adapter
|
feat(memory): add automated nightly consolidation at 4:00 AM UTC
Step 2 of memory system overhaul: automated scheduling.
- New consolidation_scheduler.py: run_nightly_consolidation() function that
checks Cat health, triggers consolidation via WebSocket, and tracks
run history with success/failure stats
- bot.py on_ready: register APScheduler cron job (hour=4, minute=0)
alongside the existing daily DM analysis job
- routes/memory.py: expose consolidation status (last_run, last_result,
last_error, is_running, total_runs, successful_runs) in the
/memory/status API response
- Web UI: show consolidation schedule info (last run time, success/fail,
run counts) below the manual consolidate button, with 'running now'
indicator when active
The 'sleep consolidation' metaphor is now actually automated instead of
being manual-only.
2026-05-15 13:54:54 +03:00
|
|
|
from utils.consolidation_scheduler import get_consolidation_status
|
refactor: split api.py monolith into 19 route modules (Phase B)
Split 3,598-line api.py into thin orchestrator (128 lines) + 19 route
modules in bot/routes/:
core.py (7 routes), mood.py (10), language.py (3), evil_mode.py (6),
bipolar_mode.py (9), gpu.py (2), bot_actions.py (4), autonomous.py (13),
profile_picture.py (26), manual_send.py (3), servers.py (6),
figurines.py (5), dms.py (18), image_generation.py (4), chat.py (1),
config.py (7), logging_config.py (9), voice.py (3), memory.py (10)
All 146 routes verified present via test_route_split.py (149 tests).
21/21 regression tests (test_config_state.py) pass.
Monolith backup: bot/api_monolith_backup.py (revert: cp it to api.py).
2026-04-15 11:38:14 +03:00
|
|
|
is_healthy = await cat_adapter.health_check()
|
|
|
|
|
return {
|
|
|
|
|
"enabled": globals.USE_CHESHIRE_CAT,
|
|
|
|
|
"healthy": is_healthy,
|
|
|
|
|
"url": globals.CHESHIRE_CAT_URL,
|
|
|
|
|
"circuit_breaker_active": cat_adapter._is_circuit_broken(),
|
feat(memory): add automated nightly consolidation at 4:00 AM UTC
Step 2 of memory system overhaul: automated scheduling.
- New consolidation_scheduler.py: run_nightly_consolidation() function that
checks Cat health, triggers consolidation via WebSocket, and tracks
run history with success/failure stats
- bot.py on_ready: register APScheduler cron job (hour=4, minute=0)
alongside the existing daily DM analysis job
- routes/memory.py: expose consolidation status (last_run, last_result,
last_error, is_running, total_runs, successful_runs) in the
/memory/status API response
- Web UI: show consolidation schedule info (last run time, success/fail,
run counts) below the manual consolidate button, with 'running now'
indicator when active
The 'sleep consolidation' metaphor is now actually automated instead of
being manual-only.
2026-05-15 13:54:54 +03:00
|
|
|
"consecutive_failures": cat_adapter._consecutive_failures,
|
|
|
|
|
"consolidation": get_consolidation_status(),
|
refactor: split api.py monolith into 19 route modules (Phase B)
Split 3,598-line api.py into thin orchestrator (128 lines) + 19 route
modules in bot/routes/:
core.py (7 routes), mood.py (10), language.py (3), evil_mode.py (6),
bipolar_mode.py (9), gpu.py (2), bot_actions.py (4), autonomous.py (13),
profile_picture.py (26), manual_send.py (3), servers.py (6),
figurines.py (5), dms.py (18), image_generation.py (4), chat.py (1),
config.py (7), logging_config.py (9), voice.py (3), memory.py (10)
All 146 routes verified present via test_route_split.py (149 tests).
21/21 regression tests (test_config_state.py) pass.
Monolith backup: bot/api_monolith_backup.py (revert: cp it to api.py).
2026-04-15 11:38:14 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post("/memory/toggle")
|
|
|
|
|
async def toggle_cat_integration(enabled: bool = Form(...)):
|
|
|
|
|
"""Toggle Cheshire Cat integration on/off."""
|
|
|
|
|
globals.USE_CHESHIRE_CAT = enabled
|
|
|
|
|
logger.info(f"🐱 Cheshire Cat integration {'ENABLED' if enabled else 'DISABLED'}")
|
|
|
|
|
|
|
|
|
|
# Persist so it survives restarts
|
|
|
|
|
try:
|
|
|
|
|
from config_manager import config_manager
|
|
|
|
|
config_manager.set("memory.use_cheshire_cat", enabled, persist=True)
|
|
|
|
|
except Exception:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
"success": True,
|
|
|
|
|
"enabled": globals.USE_CHESHIRE_CAT,
|
|
|
|
|
"message": f"Cheshire Cat {'enabled' if enabled else 'disabled'}"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/memory/stats")
|
|
|
|
|
async def get_memory_stats():
|
|
|
|
|
"""Get memory collection statistics from Cheshire Cat (point counts per collection)."""
|
|
|
|
|
from utils.cat_client import cat_adapter
|
|
|
|
|
stats = await cat_adapter.get_memory_stats()
|
|
|
|
|
if stats is None:
|
2026-04-15 15:43:18 +03:00
|
|
|
return JSONResponse(status_code=502, content={"success": False, "error": "Could not reach Cheshire Cat"})
|
refactor: split api.py monolith into 19 route modules (Phase B)
Split 3,598-line api.py into thin orchestrator (128 lines) + 19 route
modules in bot/routes/:
core.py (7 routes), mood.py (10), language.py (3), evil_mode.py (6),
bipolar_mode.py (9), gpu.py (2), bot_actions.py (4), autonomous.py (13),
profile_picture.py (26), manual_send.py (3), servers.py (6),
figurines.py (5), dms.py (18), image_generation.py (4), chat.py (1),
config.py (7), logging_config.py (9), voice.py (3), memory.py (10)
All 146 routes verified present via test_route_split.py (149 tests).
21/21 regression tests (test_config_state.py) pass.
Monolith backup: bot/api_monolith_backup.py (revert: cp it to api.py).
2026-04-15 11:38:14 +03:00
|
|
|
return {"success": True, "collections": stats.get("collections", [])}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/memory/facts")
|
|
|
|
|
async def get_memory_facts():
|
|
|
|
|
"""Get all declarative memory facts (learned knowledge about users)."""
|
|
|
|
|
from utils.cat_client import cat_adapter
|
|
|
|
|
facts = await cat_adapter.get_all_facts()
|
|
|
|
|
return {"success": True, "facts": facts, "count": len(facts)}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/memory/episodic")
|
|
|
|
|
async def get_episodic_memories():
|
|
|
|
|
"""Get all episodic memories (conversation snippets)."""
|
|
|
|
|
from utils.cat_client import cat_adapter
|
|
|
|
|
result = await cat_adapter.get_memory_points(collection="episodic", limit=100)
|
|
|
|
|
if result is None:
|
2026-04-15 15:43:18 +03:00
|
|
|
return JSONResponse(status_code=502, content={"success": False, "error": "Could not reach Cheshire Cat"})
|
refactor: split api.py monolith into 19 route modules (Phase B)
Split 3,598-line api.py into thin orchestrator (128 lines) + 19 route
modules in bot/routes/:
core.py (7 routes), mood.py (10), language.py (3), evil_mode.py (6),
bipolar_mode.py (9), gpu.py (2), bot_actions.py (4), autonomous.py (13),
profile_picture.py (26), manual_send.py (3), servers.py (6),
figurines.py (5), dms.py (18), image_generation.py (4), chat.py (1),
config.py (7), logging_config.py (9), voice.py (3), memory.py (10)
All 146 routes verified present via test_route_split.py (149 tests).
21/21 regression tests (test_config_state.py) pass.
Monolith backup: bot/api_monolith_backup.py (revert: cp it to api.py).
2026-04-15 11:38:14 +03:00
|
|
|
|
|
|
|
|
memories = []
|
|
|
|
|
for point in result.get("points", []):
|
|
|
|
|
payload = point.get("payload", {})
|
|
|
|
|
memories.append({
|
|
|
|
|
"id": point.get("id"),
|
|
|
|
|
"content": payload.get("page_content", ""),
|
|
|
|
|
"metadata": payload.get("metadata", {}),
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return {"success": True, "memories": memories, "count": len(memories)}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post("/memory/consolidate")
|
|
|
|
|
async def trigger_memory_consolidation():
|
2026-05-17 11:31:26 +03:00
|
|
|
"""
|
|
|
|
|
Trigger memory consolidation as a background task.
|
|
|
|
|
|
|
|
|
|
Returns immediately — the Web UI should poll /memory/status
|
|
|
|
|
to see when consolidation completes and view the result.
|
|
|
|
|
"""
|
refactor: split api.py monolith into 19 route modules (Phase B)
Split 3,598-line api.py into thin orchestrator (128 lines) + 19 route
modules in bot/routes/:
core.py (7 routes), mood.py (10), language.py (3), evil_mode.py (6),
bipolar_mode.py (9), gpu.py (2), bot_actions.py (4), autonomous.py (13),
profile_picture.py (26), manual_send.py (3), servers.py (6),
figurines.py (5), dms.py (18), image_generation.py (4), chat.py (1),
config.py (7), logging_config.py (9), voice.py (3), memory.py (10)
All 146 routes verified present via test_route_split.py (149 tests).
21/21 regression tests (test_config_state.py) pass.
Monolith backup: bot/api_monolith_backup.py (revert: cp it to api.py).
2026-04-15 11:38:14 +03:00
|
|
|
from utils.cat_client import cat_adapter
|
2026-05-17 11:31:26 +03:00
|
|
|
from utils.consolidation_scheduler import get_consolidation_status
|
|
|
|
|
|
|
|
|
|
# Check if already running
|
|
|
|
|
status = get_consolidation_status()
|
|
|
|
|
if status.get('is_running'):
|
|
|
|
|
return {"success": True, "message": "Consolidation is already running", "status": status}
|
|
|
|
|
|
|
|
|
|
logger.info("🌙 Manual memory consolidation triggered via API (background)...")
|
|
|
|
|
|
|
|
|
|
# Launch consolidation as a background task so the API returns immediately.
|
|
|
|
|
# The result is tracked via consolidation_scheduler's _last_consolidation state.
|
|
|
|
|
asyncio.create_task(_run_consolidation_background())
|
|
|
|
|
|
|
|
|
|
return {"success": True, "message": "Consolidation started in background. Check status via /memory/status"}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def _run_consolidation_background():
|
|
|
|
|
"""
|
|
|
|
|
Run consolidation as a background task, updating the scheduler state.
|
|
|
|
|
This prevents the API from blocking for minutes.
|
|
|
|
|
"""
|
|
|
|
|
from utils.cat_client import cat_adapter
|
|
|
|
|
from utils.consolidation_scheduler import _last_consolidation
|
|
|
|
|
|
|
|
|
|
_last_consolidation['is_running'] = True
|
|
|
|
|
_last_consolidation['last_run'] = datetime.now().isoformat()
|
|
|
|
|
_last_consolidation['total_runs'] += 1
|
|
|
|
|
start_time = time.time()
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
# Wait briefly for Cat to be ready if it was just started
|
|
|
|
|
if not await cat_adapter.health_check():
|
|
|
|
|
_last_consolidation['last_error'] = 'Cat health check failed'
|
|
|
|
|
_last_consolidation['is_running'] = False
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
result = await cat_adapter.trigger_consolidation(timeout=600)
|
|
|
|
|
elapsed = time.time() - start_time
|
|
|
|
|
|
|
|
|
|
if result:
|
|
|
|
|
logger.info(f"🌙 Manual consolidation completed in {elapsed:.1f}s: {result[:200]}")
|
|
|
|
|
_last_consolidation['last_result'] = result
|
|
|
|
|
_last_consolidation['last_error'] = None
|
|
|
|
|
_last_consolidation['successful_runs'] += 1
|
|
|
|
|
else:
|
|
|
|
|
logger.error(f"🌙 Manual consolidation returned no result after {elapsed:.1f}s")
|
|
|
|
|
_last_consolidation['last_error'] = f'No result returned after {elapsed:.1f}s (timeout or connection error)'
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
elapsed = time.time() - start_time
|
|
|
|
|
logger.error(f"🌙 Manual consolidation failed after {elapsed:.1f}s: {e}")
|
|
|
|
|
_last_consolidation['last_error'] = str(e)
|
|
|
|
|
|
|
|
|
|
finally:
|
|
|
|
|
_last_consolidation['is_running'] = False
|
refactor: split api.py monolith into 19 route modules (Phase B)
Split 3,598-line api.py into thin orchestrator (128 lines) + 19 route
modules in bot/routes/:
core.py (7 routes), mood.py (10), language.py (3), evil_mode.py (6),
bipolar_mode.py (9), gpu.py (2), bot_actions.py (4), autonomous.py (13),
profile_picture.py (26), manual_send.py (3), servers.py (6),
figurines.py (5), dms.py (18), image_generation.py (4), chat.py (1),
config.py (7), logging_config.py (9), voice.py (3), memory.py (10)
All 146 routes verified present via test_route_split.py (149 tests).
21/21 regression tests (test_config_state.py) pass.
Monolith backup: bot/api_monolith_backup.py (revert: cp it to api.py).
2026-04-15 11:38:14 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post("/memory/delete")
|
|
|
|
|
async def delete_all_memories(request: MemoryDeleteRequest):
|
|
|
|
|
"""
|
|
|
|
|
Delete ALL of Miku's memories. Requires exact confirmation string.
|
|
|
|
|
|
|
|
|
|
The confirmation field must be exactly:
|
|
|
|
|
"Yes, I am deleting Miku's memories fully."
|
|
|
|
|
|
|
|
|
|
This is destructive and irreversible.
|
|
|
|
|
"""
|
|
|
|
|
REQUIRED_CONFIRMATION = "Yes, I am deleting Miku's memories fully."
|
|
|
|
|
|
|
|
|
|
if request.confirmation != REQUIRED_CONFIRMATION:
|
|
|
|
|
logger.warning(f"Memory deletion rejected: wrong confirmation string")
|
2026-04-15 15:43:18 +03:00
|
|
|
return JSONResponse(status_code=400, content={
|
refactor: split api.py monolith into 19 route modules (Phase B)
Split 3,598-line api.py into thin orchestrator (128 lines) + 19 route
modules in bot/routes/:
core.py (7 routes), mood.py (10), language.py (3), evil_mode.py (6),
bipolar_mode.py (9), gpu.py (2), bot_actions.py (4), autonomous.py (13),
profile_picture.py (26), manual_send.py (3), servers.py (6),
figurines.py (5), dms.py (18), image_generation.py (4), chat.py (1),
config.py (7), logging_config.py (9), voice.py (3), memory.py (10)
All 146 routes verified present via test_route_split.py (149 tests).
21/21 regression tests (test_config_state.py) pass.
Monolith backup: bot/api_monolith_backup.py (revert: cp it to api.py).
2026-04-15 11:38:14 +03:00
|
|
|
"success": False,
|
|
|
|
|
"error": "Confirmation string does not match. "
|
|
|
|
|
f"Expected exactly: \"{REQUIRED_CONFIRMATION}\""
|
2026-04-15 15:43:18 +03:00
|
|
|
})
|
refactor: split api.py monolith into 19 route modules (Phase B)
Split 3,598-line api.py into thin orchestrator (128 lines) + 19 route
modules in bot/routes/:
core.py (7 routes), mood.py (10), language.py (3), evil_mode.py (6),
bipolar_mode.py (9), gpu.py (2), bot_actions.py (4), autonomous.py (13),
profile_picture.py (26), manual_send.py (3), servers.py (6),
figurines.py (5), dms.py (18), image_generation.py (4), chat.py (1),
config.py (7), logging_config.py (9), voice.py (3), memory.py (10)
All 146 routes verified present via test_route_split.py (149 tests).
21/21 regression tests (test_config_state.py) pass.
Monolith backup: bot/api_monolith_backup.py (revert: cp it to api.py).
2026-04-15 11:38:14 +03:00
|
|
|
|
|
|
|
|
from utils.cat_client import cat_adapter
|
|
|
|
|
logger.warning("⚠️ MEMORY DELETION CONFIRMED — wiping all memories!")
|
|
|
|
|
|
|
|
|
|
# Wipe vector memories (episodic + declarative)
|
|
|
|
|
wipe_success = await cat_adapter.wipe_all_memories()
|
|
|
|
|
|
|
|
|
|
# Also clear conversation history
|
|
|
|
|
history_success = await cat_adapter.wipe_conversation_history()
|
|
|
|
|
|
|
|
|
|
if wipe_success:
|
|
|
|
|
logger.warning("🗑️ All Miku memories have been deleted.")
|
|
|
|
|
return {
|
|
|
|
|
"success": True,
|
|
|
|
|
"message": "All memories have been permanently deleted.",
|
|
|
|
|
"vector_memory_wiped": wipe_success,
|
|
|
|
|
"conversation_history_cleared": history_success
|
|
|
|
|
}
|
|
|
|
|
else:
|
2026-04-15 15:43:18 +03:00
|
|
|
return JSONResponse(status_code=500, content={
|
refactor: split api.py monolith into 19 route modules (Phase B)
Split 3,598-line api.py into thin orchestrator (128 lines) + 19 route
modules in bot/routes/:
core.py (7 routes), mood.py (10), language.py (3), evil_mode.py (6),
bipolar_mode.py (9), gpu.py (2), bot_actions.py (4), autonomous.py (13),
profile_picture.py (26), manual_send.py (3), servers.py (6),
figurines.py (5), dms.py (18), image_generation.py (4), chat.py (1),
config.py (7), logging_config.py (9), voice.py (3), memory.py (10)
All 146 routes verified present via test_route_split.py (149 tests).
21/21 regression tests (test_config_state.py) pass.
Monolith backup: bot/api_monolith_backup.py (revert: cp it to api.py).
2026-04-15 11:38:14 +03:00
|
|
|
"success": False,
|
|
|
|
|
"error": "Failed to wipe memory collections. Check Cat connection."
|
2026-04-15 15:43:18 +03:00
|
|
|
})
|
refactor: split api.py monolith into 19 route modules (Phase B)
Split 3,598-line api.py into thin orchestrator (128 lines) + 19 route
modules in bot/routes/:
core.py (7 routes), mood.py (10), language.py (3), evil_mode.py (6),
bipolar_mode.py (9), gpu.py (2), bot_actions.py (4), autonomous.py (13),
profile_picture.py (26), manual_send.py (3), servers.py (6),
figurines.py (5), dms.py (18), image_generation.py (4), chat.py (1),
config.py (7), logging_config.py (9), voice.py (3), memory.py (10)
All 146 routes verified present via test_route_split.py (149 tests).
21/21 regression tests (test_config_state.py) pass.
Monolith backup: bot/api_monolith_backup.py (revert: cp it to api.py).
2026-04-15 11:38:14 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.delete("/memory/point/{collection}/{point_id}")
|
|
|
|
|
async def delete_single_memory_point(collection: str, point_id: str):
|
|
|
|
|
"""Delete a single memory point by collection and ID."""
|
|
|
|
|
from utils.cat_client import cat_adapter
|
|
|
|
|
success = await cat_adapter.delete_memory_point(collection, point_id)
|
|
|
|
|
if success:
|
|
|
|
|
return {"success": True, "deleted": point_id}
|
|
|
|
|
else:
|
2026-04-15 15:43:18 +03:00
|
|
|
return JSONResponse(status_code=500, content={"success": False, "error": f"Failed to delete point {point_id}"})
|
refactor: split api.py monolith into 19 route modules (Phase B)
Split 3,598-line api.py into thin orchestrator (128 lines) + 19 route
modules in bot/routes/:
core.py (7 routes), mood.py (10), language.py (3), evil_mode.py (6),
bipolar_mode.py (9), gpu.py (2), bot_actions.py (4), autonomous.py (13),
profile_picture.py (26), manual_send.py (3), servers.py (6),
figurines.py (5), dms.py (18), image_generation.py (4), chat.py (1),
config.py (7), logging_config.py (9), voice.py (3), memory.py (10)
All 146 routes verified present via test_route_split.py (149 tests).
21/21 regression tests (test_config_state.py) pass.
Monolith backup: bot/api_monolith_backup.py (revert: cp it to api.py).
2026-04-15 11:38:14 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.put("/memory/point/{collection}/{point_id}")
|
|
|
|
|
async def edit_memory_point(collection: str, point_id: str, request: MemoryEditRequest):
|
|
|
|
|
"""Edit an existing memory point's content and/or metadata."""
|
|
|
|
|
from utils.cat_client import cat_adapter
|
|
|
|
|
success = await cat_adapter.update_memory_point(
|
|
|
|
|
collection=collection,
|
|
|
|
|
point_id=point_id,
|
|
|
|
|
content=request.content,
|
|
|
|
|
metadata=request.metadata
|
|
|
|
|
)
|
|
|
|
|
if success:
|
|
|
|
|
return {"success": True, "updated": point_id}
|
|
|
|
|
else:
|
2026-04-15 15:43:18 +03:00
|
|
|
return JSONResponse(status_code=500, content={"success": False, "error": f"Failed to update point {point_id}"})
|
refactor: split api.py monolith into 19 route modules (Phase B)
Split 3,598-line api.py into thin orchestrator (128 lines) + 19 route
modules in bot/routes/:
core.py (7 routes), mood.py (10), language.py (3), evil_mode.py (6),
bipolar_mode.py (9), gpu.py (2), bot_actions.py (4), autonomous.py (13),
profile_picture.py (26), manual_send.py (3), servers.py (6),
figurines.py (5), dms.py (18), image_generation.py (4), chat.py (1),
config.py (7), logging_config.py (9), voice.py (3), memory.py (10)
All 146 routes verified present via test_route_split.py (149 tests).
21/21 regression tests (test_config_state.py) pass.
Monolith backup: bot/api_monolith_backup.py (revert: cp it to api.py).
2026-04-15 11:38:14 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post("/memory/create")
|
|
|
|
|
async def create_memory_point(request: MemoryCreateRequest):
|
|
|
|
|
"""
|
|
|
|
|
Manually create a new memory (declarative fact or episodic memory).
|
|
|
|
|
|
|
|
|
|
For declarative facts, this allows you to teach Miku new knowledge.
|
|
|
|
|
For episodic memories, this allows you to inject conversation context.
|
|
|
|
|
"""
|
|
|
|
|
from utils.cat_client import cat_adapter
|
|
|
|
|
|
|
|
|
|
if request.collection not in ['declarative', 'episodic']:
|
2026-04-15 15:43:18 +03:00
|
|
|
return JSONResponse(status_code=400, content={"success": False, "error": "Collection must be 'declarative' or 'episodic'"})
|
refactor: split api.py monolith into 19 route modules (Phase B)
Split 3,598-line api.py into thin orchestrator (128 lines) + 19 route
modules in bot/routes/:
core.py (7 routes), mood.py (10), language.py (3), evil_mode.py (6),
bipolar_mode.py (9), gpu.py (2), bot_actions.py (4), autonomous.py (13),
profile_picture.py (26), manual_send.py (3), servers.py (6),
figurines.py (5), dms.py (18), image_generation.py (4), chat.py (1),
config.py (7), logging_config.py (9), voice.py (3), memory.py (10)
All 146 routes verified present via test_route_split.py (149 tests).
21/21 regression tests (test_config_state.py) pass.
Monolith backup: bot/api_monolith_backup.py (revert: cp it to api.py).
2026-04-15 11:38:14 +03:00
|
|
|
|
|
|
|
|
# Create the memory point
|
|
|
|
|
result = await cat_adapter.create_memory_point(
|
|
|
|
|
collection=request.collection,
|
|
|
|
|
content=request.content,
|
|
|
|
|
user_id=request.user_id or "manual_admin",
|
|
|
|
|
source=request.source or "manual_web_ui",
|
|
|
|
|
metadata=request.metadata or {}
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if result:
|
|
|
|
|
return {"success": True, "point_id": result, "collection": request.collection}
|
|
|
|
|
else:
|
2026-04-15 15:43:18 +03:00
|
|
|
return JSONResponse(status_code=500, content={"success": False, "error": "Failed to create memory point"})
|