mirror of
https://github.com/MervinPraison/PraisonAIUI.git
synced 2026-11-07 05:56:17 -10:00
* feat: implement SessionGovernor for bounded session memory management (fixes #67) - Add SessionGovernor with configurable max_turns/max_sessions limits - Replace unbounded _contexts dict in example 03 with SessionGovernor - Fix resource churn in examples 25/26 by reusing AsyncOpenAI client - Implement documented --datastore json flag in example 04 - Export SessionGovernor in praisonaiui.__init__ for public API - Enforce context window caps and LRU eviction policies - Prevent OOM conditions in production deployments Co-authored-by: Mervin Praison <[email protected]> * fix: critical bugs in SessionGovernor memory management Fixes two production-critical bugs in session_governor.py: 1. Line 199: Fixed eviction loop condition (>= → >) to prevent: - KeyError crashes when active session gets evicted - Unnecessary eviction when at limit - Double eviction causing under-capacity 2. Line 89-90: Fixed slicing logic for non-positive keep_count: - Added guard to prevent messages[-0:] returning all messages - Ensures proper memory governance when system messages exceed turn limits 🤖 Generated with [Claude Code](https://claude.ai/code) Co-authored-by: Mervin Praison <[email protected]> --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Mervin Praison <[email protected]> Co-authored-by: Mervin Praison <[email protected]>
94 lines
2.9 KiB
Python
94 lines
2.9 KiB
Python
"""Clean Chat — Dashboard chat without the sidebar navigation.
|
|
|
|
What's New (vs 18-full-chat/):
|
|
• aiui.set_dashboard(sidebar=False) — hides the left nav panel
|
|
• Uses the dashboard style for the rich chat UI (session list, agents)
|
|
• But without the sidebar clutter (Chat, Channels, Agents, Skills, etc.)
|
|
• Protocol-driven: all config flows through /ui-config.json
|
|
|
|
This gives you the dashboard chat experience in a cleaner layout.
|
|
|
|
Requires: pip install openai (or pip install praisonai)
|
|
Set OPENAI_API_KEY before running.
|
|
|
|
Run:
|
|
aiui run app.py
|
|
"""
|
|
|
|
import os
|
|
|
|
import praisonaiui as aiui
|
|
|
|
try:
|
|
from openai import AsyncOpenAI
|
|
except ImportError:
|
|
AsyncOpenAI = None
|
|
|
|
# Reuse client to prevent resource churn
|
|
_client = None
|
|
|
|
def _get_client():
|
|
global _client
|
|
if _client is None and AsyncOpenAI is not None:
|
|
api_key = os.getenv("OPENAI_API_KEY")
|
|
if api_key:
|
|
_client = AsyncOpenAI(api_key=api_key)
|
|
return _client
|
|
|
|
# ── Dashboard style, but no sidebar navigation ─────────────
|
|
aiui.set_style("dashboard")
|
|
aiui.set_dashboard(sidebar=False, page_header=False)
|
|
aiui.set_branding(title="AI Chat", logo="💬")
|
|
aiui.set_theme(preset="blue", dark_mode=True, radius="lg")
|
|
aiui.set_pages(["chat"]) # Only show the chat page
|
|
|
|
|
|
@aiui.starters
|
|
async def get_starters():
|
|
"""Suggest conversation starters."""
|
|
return [
|
|
{"label": "Explain something", "message": "Explain quantum computing in simple terms", "icon": "🔬"},
|
|
{"label": "Write code", "message": "Write a Python function to reverse a linked list", "icon": "💻"},
|
|
{"label": "Creative writing", "message": "Write a haiku about coding at midnight", "icon": "✍️"},
|
|
{"label": "Brainstorm", "message": "Give me 5 startup ideas using AI agents", "icon": "💡"},
|
|
]
|
|
|
|
|
|
@aiui.welcome
|
|
async def on_welcome():
|
|
"""Greet the user."""
|
|
await aiui.say("👋 Hi! Ask me anything — I'm ready to help.")
|
|
|
|
|
|
@aiui.reply
|
|
async def on_message(message: str):
|
|
"""Stream a response from OpenAI."""
|
|
await aiui.think("Thinking...")
|
|
|
|
client = _get_client()
|
|
if client is None:
|
|
if AsyncOpenAI is None:
|
|
await aiui.say("❌ Please install openai: `pip install openai`")
|
|
else:
|
|
await aiui.say("❌ Please set OPENAI_API_KEY environment variable.")
|
|
return
|
|
|
|
stream = await client.chat.completions.create(
|
|
model=os.getenv("PRAISONAI_MODEL", "gpt-4o-mini"),
|
|
messages=[
|
|
{"role": "system", "content": "You are a helpful, concise assistant. Use markdown for formatting."},
|
|
{"role": "user", "content": str(message)},
|
|
],
|
|
stream=True,
|
|
)
|
|
|
|
async for chunk in stream:
|
|
delta = chunk.choices[0].delta
|
|
if delta.content:
|
|
await aiui.stream_token(delta.content)
|
|
|
|
|
|
@aiui.cancel
|
|
async def on_cancel():
|
|
await aiui.say("⏹️ Stopped.")
|