2025-11-04 05:17:27 +01:00
|
|
|
import json
|
2025-11-04 07:52:36 +01:00
|
|
|
import time
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-06 15:15:06 +01:00
|
|
|
from pr.commands.multiplexer_commands import MULTIPLEXER_COMMANDS
|
2025-11-04 08:09:12 +01:00
|
|
|
from pr.autonomous import run_autonomous_mode
|
|
|
|
|
from pr.core.api import list_models
|
2025-11-04 05:17:27 +01:00
|
|
|
from pr.tools import read_file
|
|
|
|
|
from pr.tools.base import get_tools_definition
|
2025-11-04 08:09:12 +01:00
|
|
|
from pr.ui import Colors
|
2025-11-05 15:34:23 +01:00
|
|
|
from pr.editor import RPEditor
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-04 05:17:27 +01:00
|
|
|
|
|
|
|
|
def handle_command(assistant, command):
|
|
|
|
|
command_parts = command.strip().split(maxsplit=1)
|
|
|
|
|
cmd = command_parts[0].lower()
|
|
|
|
|
|
2025-11-06 15:15:06 +01:00
|
|
|
if cmd in MULTIPLEXER_COMMANDS:
|
|
|
|
|
# Pass the assistant object and the remaining arguments to the multiplexer command
|
|
|
|
|
return MULTIPLEXER_COMMANDS[cmd](
|
|
|
|
|
assistant, command_parts[1:] if len(command_parts) > 1 else []
|
|
|
|
|
)
|
|
|
|
|
|
2025-11-05 15:34:23 +01:00
|
|
|
if cmd == "/edit":
|
|
|
|
|
rp_editor = RPEditor(command_parts[1] if len(command_parts) > 1 else None)
|
|
|
|
|
rp_editor.start()
|
|
|
|
|
rp_editor.thread.join()
|
|
|
|
|
task = str(rp_editor.get_text())
|
|
|
|
|
rp_editor.stop()
|
|
|
|
|
rp_editor = None
|
|
|
|
|
if task:
|
|
|
|
|
run_autonomous_mode(assistant, task)
|
|
|
|
|
|
2025-11-06 15:15:06 +01:00
|
|
|
elif cmd == "/prompt":
|
|
|
|
|
rp_editor = RPEditor(command_parts[1] if len(command_parts) > 1 else None)
|
|
|
|
|
rp_editor.start()
|
|
|
|
|
rp_editor.thread.join()
|
|
|
|
|
prompt_text = str(rp_editor.get_text())
|
|
|
|
|
rp_editor.stop()
|
|
|
|
|
rp_editor = None
|
|
|
|
|
if prompt_text.strip():
|
|
|
|
|
from pr.core.assistant import process_message
|
|
|
|
|
|
|
|
|
|
process_message(assistant, prompt_text)
|
|
|
|
|
|
2025-11-05 15:34:23 +01:00
|
|
|
elif cmd == "/auto":
|
2025-11-04 05:17:27 +01:00
|
|
|
if len(command_parts) < 2:
|
|
|
|
|
print(f"{Colors.RED}Usage: /auto [task description]{Colors.RESET}")
|
2025-11-04 08:09:12 +01:00
|
|
|
print(
|
|
|
|
|
f"{Colors.GRAY}Example: /auto Create a Python web scraper for news sites{Colors.RESET}"
|
|
|
|
|
)
|
2025-11-04 05:17:27 +01:00
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
task = command_parts[1]
|
|
|
|
|
run_autonomous_mode(assistant, task)
|
|
|
|
|
return True
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
if cmd in ["exit", "quit", "q"]:
|
2025-11-04 05:17:27 +01:00
|
|
|
return False
|
|
|
|
|
|
2025-11-05 15:34:23 +01:00
|
|
|
elif cmd == "/help" or cmd == "help":
|
|
|
|
|
from pr.commands.help_docs import (
|
|
|
|
|
get_agent_help,
|
|
|
|
|
get_background_help,
|
|
|
|
|
get_cache_help,
|
|
|
|
|
get_full_help,
|
|
|
|
|
get_knowledge_help,
|
|
|
|
|
get_workflow_help,
|
2025-11-04 08:09:12 +01:00
|
|
|
)
|
2025-11-04 05:17:27 +01:00
|
|
|
|
2025-11-05 15:34:23 +01:00
|
|
|
if len(command_parts) > 1:
|
|
|
|
|
topic = command_parts[1].lower()
|
|
|
|
|
if topic == "workflows":
|
|
|
|
|
print(get_workflow_help())
|
|
|
|
|
elif topic == "agents":
|
|
|
|
|
print(get_agent_help())
|
|
|
|
|
elif topic == "knowledge":
|
|
|
|
|
print(get_knowledge_help())
|
|
|
|
|
elif topic == "cache":
|
|
|
|
|
print(get_cache_help())
|
|
|
|
|
elif topic == "background":
|
|
|
|
|
print(get_background_help())
|
|
|
|
|
else:
|
|
|
|
|
print(f"{Colors.RED}Unknown help topic: {topic}{Colors.RESET}")
|
|
|
|
|
print(
|
|
|
|
|
f"{Colors.GRAY}Available topics: workflows, agents, knowledge, cache, background{Colors.RESET}"
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
print(get_full_help())
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
elif cmd == "/reset":
|
2025-11-04 05:17:27 +01:00
|
|
|
assistant.messages = assistant.messages[:1]
|
|
|
|
|
print(f"{Colors.GREEN}Message history cleared{Colors.RESET}")
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
elif cmd == "/dump":
|
2025-11-04 05:17:27 +01:00
|
|
|
print(json.dumps(assistant.messages, indent=2))
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
elif cmd == "/verbose":
|
2025-11-04 05:17:27 +01:00
|
|
|
assistant.verbose = not assistant.verbose
|
2025-11-04 08:09:12 +01:00
|
|
|
print(
|
|
|
|
|
f"Verbose mode: {Colors.GREEN if assistant.verbose else Colors.RED}{'ON' if assistant.verbose else 'OFF'}{Colors.RESET}"
|
|
|
|
|
)
|
2025-11-04 05:17:27 +01:00
|
|
|
|
2025-11-05 15:34:23 +01:00
|
|
|
elif cmd == "/model":
|
2025-11-04 05:17:27 +01:00
|
|
|
if len(command_parts) < 2:
|
|
|
|
|
print("Current model: " + Colors.GREEN + assistant.model + Colors.RESET)
|
|
|
|
|
else:
|
|
|
|
|
assistant.model = command_parts[1]
|
|
|
|
|
print(f"Model set to: {Colors.GREEN}{assistant.model}{Colors.RESET}")
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
elif cmd == "/models":
|
2025-11-04 05:17:27 +01:00
|
|
|
models = list_models(assistant.model_list_url, assistant.api_key)
|
2025-11-04 08:09:12 +01:00
|
|
|
if isinstance(models, dict) and "error" in models:
|
2025-11-04 05:17:27 +01:00
|
|
|
print(f"{Colors.RED}Error fetching models: {models['error']}{Colors.RESET}")
|
|
|
|
|
else:
|
|
|
|
|
print(f"{Colors.BOLD}Available Models:{Colors.RESET}")
|
|
|
|
|
for model in models:
|
|
|
|
|
print(f" • {Colors.CYAN}{model['id']}{Colors.RESET}")
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
elif cmd == "/tools":
|
2025-11-04 05:17:27 +01:00
|
|
|
print(f"{Colors.BOLD}Available Tools:{Colors.RESET}")
|
|
|
|
|
for tool in get_tools_definition():
|
2025-11-04 08:09:12 +01:00
|
|
|
func = tool["function"]
|
2025-11-04 08:10:37 +01:00
|
|
|
print(f" • {Colors.CYAN}{func['name']}{Colors.RESET}: {func['description']}")
|
2025-11-04 05:17:27 +01:00
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
elif cmd == "/review" and len(command_parts) > 1:
|
2025-11-04 05:17:27 +01:00
|
|
|
filename = command_parts[1]
|
|
|
|
|
review_file(assistant, filename)
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
elif cmd == "/refactor" and len(command_parts) > 1:
|
2025-11-04 05:17:27 +01:00
|
|
|
filename = command_parts[1]
|
|
|
|
|
refactor_file(assistant, filename)
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
elif cmd == "/obfuscate" and len(command_parts) > 1:
|
2025-11-04 05:17:27 +01:00
|
|
|
filename = command_parts[1]
|
|
|
|
|
obfuscate_file(assistant, filename)
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
elif cmd == "/workflows":
|
2025-11-04 05:17:27 +01:00
|
|
|
show_workflows(assistant)
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
elif cmd == "/workflow" and len(command_parts) > 1:
|
2025-11-04 05:17:27 +01:00
|
|
|
workflow_name = command_parts[1]
|
|
|
|
|
execute_workflow_command(assistant, workflow_name)
|
|
|
|
|
|
2025-11-05 15:34:23 +01:00
|
|
|
elif cmd == "/agent":
|
|
|
|
|
if len(command_parts) < 2:
|
|
|
|
|
print(f"{Colors.RED}Usage: /agent <role> <task>{Colors.RESET}")
|
|
|
|
|
print(
|
|
|
|
|
f"{Colors.GRAY}Available roles: coding, research, data_analysis, planning, testing, documentation{Colors.RESET}"
|
|
|
|
|
)
|
|
|
|
|
return True
|
|
|
|
|
|
2025-11-04 05:17:27 +01:00
|
|
|
args = command_parts[1].split(maxsplit=1)
|
|
|
|
|
if len(args) < 2:
|
|
|
|
|
print(f"{Colors.RED}Usage: /agent <role> <task>{Colors.RESET}")
|
2025-11-04 08:09:12 +01:00
|
|
|
print(
|
|
|
|
|
f"{Colors.GRAY}Available roles: coding, research, data_analysis, planning, testing, documentation{Colors.RESET}"
|
|
|
|
|
)
|
2025-11-05 15:34:23 +01:00
|
|
|
return True
|
2025-11-04 05:17:27 +01:00
|
|
|
|
2025-11-05 15:34:23 +01:00
|
|
|
role, task = args[0], args[1]
|
|
|
|
|
execute_agent_task(assistant, role, task)
|
2025-11-04 08:09:12 +01:00
|
|
|
elif cmd == "/agents":
|
2025-11-04 05:17:27 +01:00
|
|
|
show_agents(assistant)
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
elif cmd == "/collaborate" and len(command_parts) > 1:
|
2025-11-04 05:17:27 +01:00
|
|
|
task = command_parts[1]
|
|
|
|
|
collaborate_agents_command(assistant, task)
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
elif cmd == "/knowledge" and len(command_parts) > 1:
|
2025-11-04 05:17:27 +01:00
|
|
|
query = command_parts[1]
|
|
|
|
|
search_knowledge(assistant, query)
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
elif cmd == "/remember" and len(command_parts) > 1:
|
2025-11-04 05:17:27 +01:00
|
|
|
content = command_parts[1]
|
|
|
|
|
store_knowledge(assistant, content)
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
elif cmd == "/history":
|
2025-11-04 05:17:27 +01:00
|
|
|
show_conversation_history(assistant)
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
elif cmd == "/cache":
|
|
|
|
|
if len(command_parts) > 1 and command_parts[1].lower() == "clear":
|
2025-11-04 05:17:27 +01:00
|
|
|
clear_caches(assistant)
|
|
|
|
|
else:
|
|
|
|
|
show_cache_stats(assistant)
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
elif cmd == "/stats":
|
2025-11-04 05:17:27 +01:00
|
|
|
show_system_stats(assistant)
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
elif cmd.startswith("/bg"):
|
2025-11-04 07:52:36 +01:00
|
|
|
handle_background_command(assistant, command)
|
|
|
|
|
|
2025-11-04 05:17:27 +01:00
|
|
|
else:
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-04 05:17:27 +01:00
|
|
|
def review_file(assistant, filename):
|
|
|
|
|
result = read_file(filename)
|
2025-11-04 08:09:12 +01:00
|
|
|
if result["status"] == "success":
|
2025-11-04 08:10:37 +01:00
|
|
|
message = f"Please review this file and provide feedback:\n\n{result['content']}"
|
2025-11-04 05:17:27 +01:00
|
|
|
from pr.core.assistant import process_message
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-04 05:17:27 +01:00
|
|
|
process_message(assistant, message)
|
|
|
|
|
else:
|
|
|
|
|
print(f"{Colors.RED}Error reading file: {result['error']}{Colors.RESET}")
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-04 05:17:27 +01:00
|
|
|
def refactor_file(assistant, filename):
|
|
|
|
|
result = read_file(filename)
|
2025-11-04 08:09:12 +01:00
|
|
|
if result["status"] == "success":
|
2025-11-04 08:10:37 +01:00
|
|
|
message = f"Please refactor this code to improve its quality:\n\n{result['content']}"
|
2025-11-04 05:17:27 +01:00
|
|
|
from pr.core.assistant import process_message
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-04 05:17:27 +01:00
|
|
|
process_message(assistant, message)
|
|
|
|
|
else:
|
|
|
|
|
print(f"{Colors.RED}Error reading file: {result['error']}{Colors.RESET}")
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-04 05:17:27 +01:00
|
|
|
def obfuscate_file(assistant, filename):
|
|
|
|
|
result = read_file(filename)
|
2025-11-04 08:09:12 +01:00
|
|
|
if result["status"] == "success":
|
2025-11-04 05:17:27 +01:00
|
|
|
message = f"Please obfuscate this code:\n\n{result['content']}"
|
|
|
|
|
from pr.core.assistant import process_message
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-04 05:17:27 +01:00
|
|
|
process_message(assistant, message)
|
|
|
|
|
else:
|
|
|
|
|
print(f"{Colors.RED}Error reading file: {result['error']}{Colors.RESET}")
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-04 05:17:27 +01:00
|
|
|
def show_workflows(assistant):
|
2025-11-04 08:09:12 +01:00
|
|
|
if not hasattr(assistant, "enhanced"):
|
2025-11-04 05:17:27 +01:00
|
|
|
print(f"{Colors.YELLOW}Enhanced features not initialized{Colors.RESET}")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
workflows = assistant.enhanced.get_workflow_list()
|
|
|
|
|
if not workflows:
|
|
|
|
|
print(f"{Colors.YELLOW}No workflows found{Colors.RESET}")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
print(f"\n{Colors.BOLD}Available Workflows:{Colors.RESET}")
|
|
|
|
|
for wf in workflows:
|
|
|
|
|
print(f" • {Colors.CYAN}{wf['name']}{Colors.RESET}: {wf['description']}")
|
|
|
|
|
print(f" Executions: {wf['execution_count']}")
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-04 05:17:27 +01:00
|
|
|
def execute_workflow_command(assistant, workflow_name):
|
2025-11-04 08:09:12 +01:00
|
|
|
if not hasattr(assistant, "enhanced"):
|
2025-11-04 05:17:27 +01:00
|
|
|
print(f"{Colors.YELLOW}Enhanced features not initialized{Colors.RESET}")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
print(f"{Colors.YELLOW}Executing workflow: {workflow_name}...{Colors.RESET}")
|
|
|
|
|
result = assistant.enhanced.execute_workflow(workflow_name)
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
if "error" in result:
|
2025-11-04 05:17:27 +01:00
|
|
|
print(f"{Colors.RED}Error: {result['error']}{Colors.RESET}")
|
|
|
|
|
else:
|
|
|
|
|
print(f"{Colors.GREEN}Workflow completed successfully{Colors.RESET}")
|
|
|
|
|
print(f"Execution ID: {result['execution_id']}")
|
|
|
|
|
print(f"Results: {json.dumps(result['results'], indent=2)}")
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-04 05:17:27 +01:00
|
|
|
def execute_agent_task(assistant, role, task):
|
2025-11-04 08:09:12 +01:00
|
|
|
if not hasattr(assistant, "enhanced"):
|
2025-11-04 05:17:27 +01:00
|
|
|
print(f"{Colors.YELLOW}Enhanced features not initialized{Colors.RESET}")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
print(f"{Colors.YELLOW}Creating {role} agent...{Colors.RESET}")
|
|
|
|
|
agent_id = assistant.enhanced.create_agent(role)
|
|
|
|
|
print(f"{Colors.GREEN}Agent created: {agent_id}{Colors.RESET}")
|
|
|
|
|
|
|
|
|
|
print(f"{Colors.YELLOW}Executing task...{Colors.RESET}")
|
|
|
|
|
result = assistant.enhanced.agent_task(agent_id, task)
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
if "error" in result:
|
2025-11-04 05:17:27 +01:00
|
|
|
print(f"{Colors.RED}Error: {result['error']}{Colors.RESET}")
|
|
|
|
|
else:
|
|
|
|
|
print(f"\n{Colors.GREEN}{role.capitalize()} Agent Response:{Colors.RESET}")
|
2025-11-04 08:09:12 +01:00
|
|
|
print(result["response"])
|
|
|
|
|
|
2025-11-04 05:17:27 +01:00
|
|
|
|
|
|
|
|
def show_agents(assistant):
|
2025-11-04 08:09:12 +01:00
|
|
|
if not hasattr(assistant, "enhanced"):
|
2025-11-04 05:17:27 +01:00
|
|
|
print(f"{Colors.YELLOW}Enhanced features not initialized{Colors.RESET}")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
summary = assistant.enhanced.get_agent_summary()
|
|
|
|
|
print(f"\n{Colors.BOLD}Agent Session Summary:{Colors.RESET}")
|
|
|
|
|
print(f"Active agents: {summary['active_agents']}")
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
if summary["agents"]:
|
|
|
|
|
for agent in summary["agents"]:
|
2025-11-04 05:17:27 +01:00
|
|
|
print(f"\n • {Colors.CYAN}{agent['agent_id']}{Colors.RESET}")
|
|
|
|
|
print(f" Role: {agent['role']}")
|
|
|
|
|
print(f" Tasks completed: {agent['task_count']}")
|
|
|
|
|
print(f" Messages: {agent['message_count']}")
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-04 05:17:27 +01:00
|
|
|
def collaborate_agents_command(assistant, task):
|
2025-11-04 08:09:12 +01:00
|
|
|
if not hasattr(assistant, "enhanced"):
|
2025-11-04 05:17:27 +01:00
|
|
|
print(f"{Colors.YELLOW}Enhanced features not initialized{Colors.RESET}")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
print(f"{Colors.YELLOW}Initiating agent collaboration...{Colors.RESET}")
|
2025-11-04 08:09:12 +01:00
|
|
|
roles = ["coding", "research", "planning"]
|
2025-11-04 05:17:27 +01:00
|
|
|
|
|
|
|
|
result = assistant.enhanced.collaborate_agents(task, roles)
|
|
|
|
|
|
|
|
|
|
print(f"\n{Colors.GREEN}Collaboration completed{Colors.RESET}")
|
|
|
|
|
print(f"\nOrchestrator response:")
|
2025-11-04 08:09:12 +01:00
|
|
|
if "orchestrator" in result and "response" in result["orchestrator"]:
|
|
|
|
|
print(result["orchestrator"]["response"])
|
2025-11-04 05:17:27 +01:00
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
if result.get("agents"):
|
2025-11-04 05:17:27 +01:00
|
|
|
print(f"\n{Colors.BOLD}Agent Results:{Colors.RESET}")
|
2025-11-04 08:09:12 +01:00
|
|
|
for agent_result in result["agents"]:
|
|
|
|
|
if "role" in agent_result:
|
2025-11-04 05:17:27 +01:00
|
|
|
print(f"\n{Colors.CYAN}{agent_result['role']}:{Colors.RESET}")
|
2025-11-04 08:09:12 +01:00
|
|
|
print(agent_result.get("response", "No response"))
|
|
|
|
|
|
2025-11-04 05:17:27 +01:00
|
|
|
|
|
|
|
|
def search_knowledge(assistant, query):
|
2025-11-04 08:09:12 +01:00
|
|
|
if not hasattr(assistant, "enhanced"):
|
2025-11-04 05:17:27 +01:00
|
|
|
print(f"{Colors.YELLOW}Enhanced features not initialized{Colors.RESET}")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
results = assistant.enhanced.search_knowledge(query)
|
|
|
|
|
|
|
|
|
|
if not results:
|
|
|
|
|
print(f"{Colors.YELLOW}No knowledge entries found for: {query}{Colors.RESET}")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
print(f"\n{Colors.BOLD}Knowledge Search Results:{Colors.RESET}")
|
|
|
|
|
for entry in results:
|
|
|
|
|
print(f"\n • {Colors.CYAN}[{entry.category}]{Colors.RESET}")
|
|
|
|
|
print(f" {entry.content[:200]}...")
|
|
|
|
|
print(f" Accessed: {entry.access_count} times")
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-04 05:17:27 +01:00
|
|
|
def store_knowledge(assistant, content):
|
2025-11-04 08:09:12 +01:00
|
|
|
if not hasattr(assistant, "enhanced"):
|
2025-11-04 05:17:27 +01:00
|
|
|
print(f"{Colors.YELLOW}Enhanced features not initialized{Colors.RESET}")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
import time
|
2025-11-04 08:09:12 +01:00
|
|
|
import uuid
|
|
|
|
|
|
2025-11-04 05:17:27 +01:00
|
|
|
from pr.memory import KnowledgeEntry
|
|
|
|
|
|
|
|
|
|
categories = assistant.enhanced.fact_extractor.categorize_content(content)
|
|
|
|
|
entry_id = str(uuid.uuid4())[:16]
|
|
|
|
|
|
|
|
|
|
entry = KnowledgeEntry(
|
|
|
|
|
entry_id=entry_id,
|
2025-11-04 08:09:12 +01:00
|
|
|
category=categories[0] if categories else "general",
|
2025-11-04 05:17:27 +01:00
|
|
|
content=content,
|
2025-11-04 08:09:12 +01:00
|
|
|
metadata={"manual_entry": True},
|
2025-11-04 05:17:27 +01:00
|
|
|
created_at=time.time(),
|
2025-11-04 08:09:12 +01:00
|
|
|
updated_at=time.time(),
|
2025-11-04 05:17:27 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
assistant.enhanced.knowledge_store.add_entry(entry)
|
|
|
|
|
print(f"{Colors.GREEN}Knowledge stored successfully{Colors.RESET}")
|
|
|
|
|
print(f"Entry ID: {entry_id}")
|
|
|
|
|
print(f"Category: {entry.category}")
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-04 05:17:27 +01:00
|
|
|
def show_conversation_history(assistant):
|
2025-11-04 08:09:12 +01:00
|
|
|
if not hasattr(assistant, "enhanced"):
|
2025-11-04 05:17:27 +01:00
|
|
|
print(f"{Colors.YELLOW}Enhanced features not initialized{Colors.RESET}")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
history = assistant.enhanced.get_conversation_history(limit=10)
|
|
|
|
|
|
|
|
|
|
if not history:
|
|
|
|
|
print(f"{Colors.YELLOW}No conversation history found{Colors.RESET}")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
print(f"\n{Colors.BOLD}Recent Conversations:{Colors.RESET}")
|
|
|
|
|
for conv in history:
|
|
|
|
|
import datetime
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-04 08:10:37 +01:00
|
|
|
started = datetime.datetime.fromtimestamp(conv["started_at"]).strftime("%Y-%m-%d %H:%M")
|
2025-11-04 05:17:27 +01:00
|
|
|
print(f"\n • {Colors.CYAN}{conv['conversation_id']}{Colors.RESET}")
|
|
|
|
|
print(f" Started: {started}")
|
|
|
|
|
print(f" Messages: {conv['message_count']}")
|
2025-11-04 08:09:12 +01:00
|
|
|
if conv.get("summary"):
|
2025-11-04 05:17:27 +01:00
|
|
|
print(f" Summary: {conv['summary'][:100]}...")
|
2025-11-04 08:09:12 +01:00
|
|
|
if conv.get("topics"):
|
2025-11-04 05:17:27 +01:00
|
|
|
print(f" Topics: {', '.join(conv['topics'])}")
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-04 05:17:27 +01:00
|
|
|
def show_cache_stats(assistant):
|
2025-11-04 08:09:12 +01:00
|
|
|
if not hasattr(assistant, "enhanced"):
|
2025-11-04 05:17:27 +01:00
|
|
|
print(f"{Colors.YELLOW}Enhanced features not initialized{Colors.RESET}")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
stats = assistant.enhanced.get_cache_statistics()
|
|
|
|
|
|
|
|
|
|
print(f"\n{Colors.BOLD}Cache Statistics:{Colors.RESET}")
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
if "api_cache" in stats:
|
|
|
|
|
api_stats = stats["api_cache"]
|
2025-11-04 05:17:27 +01:00
|
|
|
print(f"\n{Colors.CYAN}API Cache:{Colors.RESET}")
|
|
|
|
|
print(f" Total entries: {api_stats['total_entries']}")
|
|
|
|
|
print(f" Valid entries: {api_stats['valid_entries']}")
|
|
|
|
|
print(f" Expired entries: {api_stats['expired_entries']}")
|
|
|
|
|
print(f" Cached tokens: {api_stats['total_cached_tokens']}")
|
2025-11-05 15:34:23 +01:00
|
|
|
print(f" Total cache hits: {api_stats['total_cache_hits']}")
|
2025-11-04 05:17:27 +01:00
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
if "tool_cache" in stats:
|
|
|
|
|
tool_stats = stats["tool_cache"]
|
2025-11-04 05:17:27 +01:00
|
|
|
print(f"\n{Colors.CYAN}Tool Cache:{Colors.RESET}")
|
|
|
|
|
print(f" Total entries: {tool_stats['total_entries']}")
|
|
|
|
|
print(f" Valid entries: {tool_stats['valid_entries']}")
|
|
|
|
|
print(f" Total cache hits: {tool_stats['total_cache_hits']}")
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
if tool_stats.get("by_tool"):
|
2025-11-04 05:17:27 +01:00
|
|
|
print(f"\n Per-tool statistics:")
|
2025-11-04 08:09:12 +01:00
|
|
|
for tool_name, tool_stat in tool_stats["by_tool"].items():
|
|
|
|
|
print(
|
|
|
|
|
f" {tool_name}: {tool_stat['cached_entries']} entries, {tool_stat['total_hits']} hits"
|
|
|
|
|
)
|
|
|
|
|
|
2025-11-04 05:17:27 +01:00
|
|
|
|
|
|
|
|
def clear_caches(assistant):
|
2025-11-04 08:09:12 +01:00
|
|
|
if not hasattr(assistant, "enhanced"):
|
2025-11-04 05:17:27 +01:00
|
|
|
print(f"{Colors.YELLOW}Enhanced features not initialized{Colors.RESET}")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
assistant.enhanced.clear_caches()
|
|
|
|
|
print(f"{Colors.GREEN}All caches cleared successfully{Colors.RESET}")
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-04 05:17:27 +01:00
|
|
|
def show_system_stats(assistant):
|
2025-11-04 08:09:12 +01:00
|
|
|
if not hasattr(assistant, "enhanced"):
|
2025-11-04 05:17:27 +01:00
|
|
|
print(f"{Colors.YELLOW}Enhanced features not initialized{Colors.RESET}")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
print(f"\n{Colors.BOLD}System Statistics:{Colors.RESET}")
|
|
|
|
|
|
|
|
|
|
cache_stats = assistant.enhanced.get_cache_statistics()
|
|
|
|
|
knowledge_stats = assistant.enhanced.get_knowledge_statistics()
|
|
|
|
|
agent_summary = assistant.enhanced.get_agent_summary()
|
|
|
|
|
|
|
|
|
|
print(f"\n{Colors.CYAN}Knowledge Base:{Colors.RESET}")
|
|
|
|
|
print(f" Total entries: {knowledge_stats['total_entries']}")
|
|
|
|
|
print(f" Categories: {knowledge_stats['total_categories']}")
|
|
|
|
|
print(f" Total accesses: {knowledge_stats['total_accesses']}")
|
|
|
|
|
print(f" Vocabulary size: {knowledge_stats['vocabulary_size']}")
|
|
|
|
|
|
|
|
|
|
print(f"\n{Colors.CYAN}Active Agents:{Colors.RESET}")
|
|
|
|
|
print(f" Count: {agent_summary['active_agents']}")
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
if "api_cache" in cache_stats:
|
2025-11-04 05:17:27 +01:00
|
|
|
print(f"\n{Colors.CYAN}Caching:{Colors.RESET}")
|
|
|
|
|
print(f" API cache entries: {cache_stats['api_cache']['valid_entries']}")
|
2025-11-04 08:09:12 +01:00
|
|
|
if "tool_cache" in cache_stats:
|
2025-11-04 05:17:27 +01:00
|
|
|
print(f" Tool cache entries: {cache_stats['tool_cache']['valid_entries']}")
|
2025-11-04 07:52:36 +01:00
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-04 07:52:36 +01:00
|
|
|
def handle_background_command(assistant, command):
|
|
|
|
|
"""Handle background multiplexer commands."""
|
|
|
|
|
parts = command.strip().split(maxsplit=2)
|
|
|
|
|
if len(parts) < 2:
|
|
|
|
|
print(f"{Colors.RED}Usage: /bg <subcommand> [args]{Colors.RESET}")
|
2025-11-04 08:09:12 +01:00
|
|
|
print(
|
|
|
|
|
f"{Colors.GRAY}Available subcommands: start, list, status, output, input, kill, events{Colors.RESET}"
|
|
|
|
|
)
|
2025-11-04 07:52:36 +01:00
|
|
|
return
|
|
|
|
|
|
|
|
|
|
subcmd = parts[1].lower()
|
|
|
|
|
|
|
|
|
|
try:
|
2025-11-04 08:09:12 +01:00
|
|
|
if subcmd == "start" and len(parts) >= 3:
|
2025-11-04 07:52:36 +01:00
|
|
|
session_name = f"bg_{len(parts[2].split())}_{int(time.time())}"
|
|
|
|
|
start_background_session(assistant, session_name, parts[2])
|
2025-11-04 08:09:12 +01:00
|
|
|
elif subcmd == "list":
|
2025-11-04 07:52:36 +01:00
|
|
|
list_background_sessions(assistant)
|
2025-11-04 08:09:12 +01:00
|
|
|
elif subcmd == "status" and len(parts) >= 3:
|
2025-11-04 07:52:36 +01:00
|
|
|
show_session_status(assistant, parts[2])
|
2025-11-04 08:09:12 +01:00
|
|
|
elif subcmd == "output" and len(parts) >= 3:
|
2025-11-04 07:52:36 +01:00
|
|
|
show_session_output(assistant, parts[2])
|
2025-11-04 08:09:12 +01:00
|
|
|
elif subcmd == "input" and len(parts) >= 4:
|
2025-11-04 07:52:36 +01:00
|
|
|
send_session_input(assistant, parts[2], parts[3])
|
2025-11-04 08:09:12 +01:00
|
|
|
elif subcmd == "kill" and len(parts) >= 3:
|
2025-11-04 07:52:36 +01:00
|
|
|
kill_background_session(assistant, parts[2])
|
2025-11-04 08:09:12 +01:00
|
|
|
elif subcmd == "events":
|
2025-11-04 07:52:36 +01:00
|
|
|
show_background_events(assistant)
|
|
|
|
|
else:
|
|
|
|
|
print(f"{Colors.RED}Unknown background command: {subcmd}{Colors.RESET}")
|
2025-11-04 08:09:12 +01:00
|
|
|
print(
|
|
|
|
|
f"{Colors.GRAY}Available: start, list, status, output, input, kill, events{Colors.RESET}"
|
|
|
|
|
)
|
2025-11-04 07:52:36 +01:00
|
|
|
except Exception as e:
|
|
|
|
|
print(f"{Colors.RED}Error executing background command: {e}{Colors.RESET}")
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-04 07:52:36 +01:00
|
|
|
def start_background_session(assistant, session_name, command):
|
|
|
|
|
"""Start a command in background."""
|
|
|
|
|
try:
|
|
|
|
|
from pr.multiplexer import start_background_process
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-04 07:52:36 +01:00
|
|
|
result = start_background_process(session_name, command)
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
if result["status"] == "success":
|
|
|
|
|
print(
|
|
|
|
|
f"{Colors.GREEN}Started background session '{session_name}' with PID {result['pid']}{Colors.RESET}"
|
|
|
|
|
)
|
2025-11-04 07:52:36 +01:00
|
|
|
else:
|
2025-11-04 08:09:12 +01:00
|
|
|
print(
|
|
|
|
|
f"{Colors.RED}Failed to start background session: {result.get('error', 'Unknown error')}{Colors.RESET}"
|
|
|
|
|
)
|
2025-11-04 07:52:36 +01:00
|
|
|
except Exception as e:
|
|
|
|
|
print(f"{Colors.RED}Error starting background session: {e}{Colors.RESET}")
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-04 07:52:36 +01:00
|
|
|
def list_background_sessions(assistant):
|
|
|
|
|
"""List all background sessions."""
|
|
|
|
|
try:
|
|
|
|
|
from pr.multiplexer import get_all_sessions
|
2025-11-04 08:09:12 +01:00
|
|
|
from pr.ui.display import display_multiplexer_status
|
2025-11-04 07:52:36 +01:00
|
|
|
|
|
|
|
|
sessions = get_all_sessions()
|
|
|
|
|
display_multiplexer_status(sessions)
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"{Colors.RED}Error listing background sessions: {e}{Colors.RESET}")
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-04 07:52:36 +01:00
|
|
|
def show_session_status(assistant, session_name):
|
|
|
|
|
"""Show status of a specific session."""
|
|
|
|
|
try:
|
|
|
|
|
from pr.multiplexer import get_session_info
|
|
|
|
|
|
|
|
|
|
info = get_session_info(session_name)
|
|
|
|
|
if info:
|
|
|
|
|
print(f"{Colors.BOLD}Session '{session_name}':{Colors.RESET}")
|
|
|
|
|
print(f" Status: {info.get('status', 'unknown')}")
|
|
|
|
|
print(f" PID: {info.get('pid', 'N/A')}")
|
|
|
|
|
print(f" Command: {info.get('command', 'N/A')}")
|
2025-11-04 08:09:12 +01:00
|
|
|
if "start_time" in info:
|
2025-11-04 07:52:36 +01:00
|
|
|
import time
|
2025-11-04 08:09:12 +01:00
|
|
|
|
|
|
|
|
elapsed = time.time() - info["start_time"]
|
2025-11-04 07:52:36 +01:00
|
|
|
print(f" Running for: {elapsed:.1f}s")
|
|
|
|
|
else:
|
|
|
|
|
print(f"{Colors.YELLOW}Session '{session_name}' not found{Colors.RESET}")
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"{Colors.RED}Error getting session status: {e}{Colors.RESET}")
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-04 07:52:36 +01:00
|
|
|
def show_session_output(assistant, session_name):
|
|
|
|
|
"""Show output of a specific session."""
|
|
|
|
|
try:
|
|
|
|
|
from pr.multiplexer import get_session_output
|
|
|
|
|
|
|
|
|
|
output = get_session_output(session_name, lines=50)
|
|
|
|
|
if output:
|
|
|
|
|
print(f"{Colors.BOLD}Recent output from '{session_name}':{Colors.RESET}")
|
|
|
|
|
print(f"{Colors.GRAY}{'─' * 60}{Colors.RESET}")
|
|
|
|
|
for line in output:
|
|
|
|
|
print(line)
|
|
|
|
|
else:
|
2025-11-04 08:10:37 +01:00
|
|
|
print(f"{Colors.YELLOW}No output available for session '{session_name}'{Colors.RESET}")
|
2025-11-04 07:52:36 +01:00
|
|
|
except Exception as e:
|
|
|
|
|
print(f"{Colors.RED}Error getting session output: {e}{Colors.RESET}")
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-04 07:52:36 +01:00
|
|
|
def send_session_input(assistant, session_name, input_text):
|
|
|
|
|
"""Send input to a background session."""
|
|
|
|
|
try:
|
|
|
|
|
from pr.multiplexer import send_input_to_session
|
|
|
|
|
|
|
|
|
|
result = send_input_to_session(session_name, input_text)
|
2025-11-04 08:09:12 +01:00
|
|
|
if result["status"] == "success":
|
2025-11-04 07:52:36 +01:00
|
|
|
print(f"{Colors.GREEN}Input sent to session '{session_name}'{Colors.RESET}")
|
|
|
|
|
else:
|
2025-11-04 08:09:12 +01:00
|
|
|
print(
|
|
|
|
|
f"{Colors.RED}Failed to send input: {result.get('error', 'Unknown error')}{Colors.RESET}"
|
|
|
|
|
)
|
2025-11-04 07:52:36 +01:00
|
|
|
except Exception as e:
|
|
|
|
|
print(f"{Colors.RED}Error sending input: {e}{Colors.RESET}")
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-04 07:52:36 +01:00
|
|
|
def kill_background_session(assistant, session_name):
|
|
|
|
|
"""Kill a background session."""
|
|
|
|
|
try:
|
|
|
|
|
from pr.multiplexer import kill_session
|
|
|
|
|
|
|
|
|
|
result = kill_session(session_name)
|
2025-11-04 08:09:12 +01:00
|
|
|
if result["status"] == "success":
|
2025-11-04 07:52:36 +01:00
|
|
|
print(f"{Colors.GREEN}Session '{session_name}' terminated{Colors.RESET}")
|
|
|
|
|
else:
|
2025-11-04 08:09:12 +01:00
|
|
|
print(
|
|
|
|
|
f"{Colors.RED}Failed to kill session: {result.get('error', 'Unknown error')}{Colors.RESET}"
|
|
|
|
|
)
|
2025-11-04 07:52:36 +01:00
|
|
|
except Exception as e:
|
|
|
|
|
print(f"{Colors.RED}Error killing session: {e}{Colors.RESET}")
|
|
|
|
|
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-04 07:52:36 +01:00
|
|
|
def show_background_events(assistant):
|
|
|
|
|
"""Show recent background events."""
|
|
|
|
|
try:
|
|
|
|
|
from pr.core.background_monitor import get_global_monitor
|
|
|
|
|
|
|
|
|
|
monitor = get_global_monitor()
|
|
|
|
|
events = monitor.get_pending_events()
|
|
|
|
|
|
|
|
|
|
if events:
|
|
|
|
|
print(f"{Colors.BOLD}Recent Background Events:{Colors.RESET}")
|
|
|
|
|
print(f"{Colors.GRAY}{'─' * 60}{Colors.RESET}")
|
|
|
|
|
|
|
|
|
|
for event in events[-10:]: # Show last 10 events
|
|
|
|
|
from pr.ui.display import display_background_event
|
2025-11-04 08:09:12 +01:00
|
|
|
|
2025-11-04 07:52:36 +01:00
|
|
|
display_background_event(event)
|
|
|
|
|
else:
|
|
|
|
|
print(f"{Colors.GRAY}No recent background events{Colors.RESET}")
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"{Colors.RED}Error getting background events: {e}{Colors.RESET}")
|