import subprocess import sys import threading import json import socket import os import logging # ========================================== # ZONE 1: AUTO-INSTALLER & LOG SILENCER # ========================================== def bootstrap(): """Checks for required libraries and installs them if missing.""" required = ["flask", "requests", "markdown"] installed_any = False for lib in required: try: __import__(lib) except ImportError: installed_any = True print(f"--- [SETUP] {lib} not found. Installing... ---") subprocess.check_call([sys.executable, "-m", "pip", "install", lib]) # Only clear the screen if we actually did a messy install if installed_any: os.system('cls' if os.name == 'nt' else 'clear') bootstrap() # Now import the libraries we just verified from flask import Flask, render_template_string, request, redirect, url_for, jsonify import requests import markdown # Silence the Flask "Development Server" warnings and request logs log = logging.getLogger('werkzeug') log.setLevel(logging.ERROR) #os.environ['WERKZEUG_RUN_MAIN'] = 'true' # ========================================== # ZONE 2: APP LOGIC & MODEL MANAGEMENT # ========================================== app = Flask(__name__) chat_history = [] stream_state = {"text": "", "done": True} current_model = "llama3.1" def get_local_ip(): """Detects the computer's local IP for the Kobo to connect to.""" s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: s.connect(('10.255.255.255', 1)) IP = s.getsockname()[0] except Exception: IP = '127.0.0.1' finally: s.close() return IP def print_dashboard(ollama_status): """Refreshes the terminal UI with current server info.""" my_ip = get_local_ip() my_port = 5001 os.system('cls' if os.name == 'nt' else 'clear') print("\n" + "╔" + "═"*48 + "╗") print(f"║ {'INKWELL AI SERVER':^46} ║") print("╠" + "═"*48 + "╣") print(f"║ IP: http://{my_ip}:{my_port:<21} ║") print(f"║ AI: {ollama_status:<38} ║") print(f"║ MODEL: {current_model:<37} ║") print("╚" + "═"*48 + "╝") print(" [Press CTRL+C to stop the server]\n") def get_available_models(): """Fetches the list of downloaded models from Ollama.""" try: r = requests.get("http://localhost:11434/api/tags", timeout=2) if r.status_code == 200: return [m['name'] for m in r.json().get('models', [])] except: return [] return [] def generate_ai_response(prompt, user_ip): """Streams response from Ollama in a separate thread.""" global stream_state, chat_history, current_model stream_state["text"] = "" stream_state["done"] = False try: r = requests.post("http://localhost:11434/api/generate", json={"model": current_model, "prompt": prompt, "stream": True}, stream=True) r.raise_for_status() for line in r.iter_lines(): if line: chunk = json.loads(line) stream_state["text"] += chunk.get("response", "") except Exception as e: stream_state["text"] = f"Connection Error: {e}" stream_state["done"] = True chat_history.append({"role": f"AI ({current_model})", "content": markdown.markdown(stream_state["text"])}) HTML_PAGE = """
/// THINKING... ///
Connection Successful!
Your model library is empty. Please pull a model on your laptop to begin.
Example: ollama pull llama3.1
Ollama is NOT running!
Please start Ollama on your computer.