|
import os |
|
import sys |
|
import argparse |
|
import importlib.util |
|
import signal |
|
import logging |
|
|
|
|
|
|
|
PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__)) |
|
|
|
def add_path(path): |
|
if path not in sys.path: |
|
sys.path.insert(0, path) |
|
|
|
add_path(PROJECT_ROOT) |
|
|
|
logging.basicConfig( |
|
filename=os.path.join(PROJECT_ROOT, 'codette_bootstrap.log'), |
|
level=logging.INFO, |
|
format='%(asctime)s %(levelname)s %(message)s' |
|
) |
|
logging.info("Codette Bootstrap - Starting up.") |
|
|
|
|
|
|
|
def check_exists(rel_path, required=True): |
|
abs_path = os.path.join(PROJECT_ROOT, rel_path) |
|
if not os.path.exists(abs_path): |
|
if required: |
|
logging.error(f"Required file '{rel_path}' not found!") |
|
raise FileNotFoundError(f"Required file '{rel_path}' not found!") |
|
else: |
|
logging.warning(f"Optional file '{rel_path}' not found.") |
|
else: |
|
logging.info(f"Located: {rel_path}") |
|
return abs_path |
|
|
|
|
|
|
|
def launch_tkinter_gui(): |
|
from codette_desktop import CodetteApp |
|
logging.info("Launching Codette Tkinter GUI...") |
|
app = CodetteApp() |
|
app.mainloop() |
|
|
|
def launch_fastapi_server(): |
|
from api_server import app as fastapi_app |
|
import uvicorn |
|
logging.info("Spawning Codette FastAPI server...") |
|
uvicorn.run(fastapi_app, host="127.0.0.1", port=8000, log_level="info") |
|
|
|
def test_cognitive_stack(): |
|
|
|
from universal_reasoning_local import UniversalReasoning, load_json_config |
|
try: |
|
config_path = check_exists("config.json") |
|
config = load_json_config(config_path) |
|
ur = UniversalReasoning(config) |
|
import asyncio |
|
print("Running self-test: 'What is the meaning of life?'") |
|
result = asyncio.run(ur.generate_response("What is the meaning of life?")) |
|
print("Codette:", result) |
|
return True |
|
except Exception as e: |
|
logging.error(f"Stack self-test failed: {e}") |
|
print(f"Error: {e}") |
|
return False |
|
|
|
def banner(): |
|
print("CODDETTE / PIDETTE β Universal Reasoning Bootstrap") |
|
print("Raiffs Bits LLC β Jonathan Harrison (2024)\n") |
|
|
|
|
|
|
|
def main(): |
|
banner() |
|
parser = argparse.ArgumentParser(description="Codette Multi-Agent AI Bootstrapper") |
|
parser.add_argument('--gui', action="store_true", help="Launch the Tkinter GUI application") |
|
parser.add_argument('--api', action="store_true", help="Launch FastAPI backend") |
|
parser.add_argument('--test', action="store_true", help="Run logic self-test (no UI)") |
|
args = parser.parse_args() |
|
|
|
|
|
_ = check_exists("config.json") |
|
_ = check_exists("universal_reasoning_local.py") |
|
_ = check_exists("codette_desktop.py") |
|
_ = check_exists("api_server.py") |
|
|
|
|
|
|
|
if args.test: |
|
ok = test_cognitive_stack() |
|
if not ok: |
|
sys.exit(1) |
|
return |
|
|
|
processes = [] |
|
|
|
if args.api: |
|
|
|
import multiprocessing |
|
p_api = multiprocessing.Process(target=launch_fastapi_server) |
|
p_api.daemon = True |
|
p_api.start() |
|
processes.append(p_api) |
|
|
|
if args.gui: |
|
launch_tkinter_gui() |
|
|
|
|
|
if not args.gui and not args.api and not args.test: |
|
parser.print_help() |
|
sys.exit(0) |
|
|
|
|
|
for p in processes: |
|
p.join() |
|
|
|
def handle_interrupt(sig, frame): |
|
print("Shutting down Codette...") |
|
sys.exit(0) |
|
|
|
signal.signal(signal.SIGINT, handle_interrupt) |
|
signal.signal(signal.SIGTERM, handle_interrupt) |
|
|
|
if __name__ == "__main__": |
|
main() |
|
|