|
1 | | -#V06092026 |
| 1 | +#V06212026 |
2 | 2 | # ============================================================================= |
3 | 3 | # CAIOS Web Bridge — Flask server that connects caios_chat_ui.html to the existing orchestrator/caios_chat.py stack. |
4 | 4 | # |
|
17 | 17 | import hashlib |
18 | 18 | import tempfile |
19 | 19 | import pathlib |
| 20 | +import subprocess |
| 21 | +import platform |
| 22 | +import atexit |
20 | 23 | from datetime import datetime, timezone |
21 | 24 | from typing import Dict, Any |
22 | 25 |
|
@@ -86,6 +89,88 @@ def _bootstrap_shared_memory() -> Dict[str, Any]: |
86 | 89 | UPLOAD_DIR = pathlib.Path(tempfile.gettempdir()) / 'caios_uploads' |
87 | 90 | UPLOAD_DIR.mkdir(exist_ok=True) |
88 | 91 |
|
| 92 | +# ============================================================================= |
| 93 | +# Service Startup — Ollama, MCP filesystem server, windows-mcp |
| 94 | +# |
| 95 | +# Moved here from run_caios.bat/.sh so that BOTH launch paths documented in |
| 96 | +# SETUP.md ("run run_caios.bat" and "run python caios_bridge.py directly") |
| 97 | +# actually bring the same services up. run_caios.bat now only handles |
| 98 | +# one-time environment setup (deps, model pull, first-boot identity) and |
| 99 | +# hands off to this on every launch. |
| 100 | +# |
| 101 | +# Safe to call repeatedly — each service is skipped if already reachable, |
| 102 | +# so it's harmless if ollama is already running as a background service, |
| 103 | +# or if you start the bridge a second time. |
| 104 | +# ============================================================================= |
| 105 | + |
| 106 | +_spawned_procs = [] |
| 107 | + |
| 108 | +def _wait_until_ready(check_fn, timeout=20, interval=0.5) -> bool: |
| 109 | + deadline = time.time() + timeout |
| 110 | + while time.time() < deadline: |
| 111 | + try: |
| 112 | + if check_fn(): |
| 113 | + return True |
| 114 | + except Exception: |
| 115 | + pass |
| 116 | + time.sleep(interval) |
| 117 | + return False |
| 118 | + |
| 119 | +def _start_service(name: str, cmd: str, check_fn, timeout: int = 20) -> None: |
| 120 | + try: |
| 121 | + if check_fn(): |
| 122 | + print(f'[BRIDGE] {name} already running') |
| 123 | + return |
| 124 | + except Exception: |
| 125 | + pass # treat a check failure as "not running yet" and try to start it |
| 126 | + |
| 127 | + print(f'[BRIDGE] Starting {name}...') |
| 128 | + proc = subprocess.Popen( |
| 129 | + cmd, shell=True, |
| 130 | + stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL |
| 131 | + ) |
| 132 | + _spawned_procs.append(proc) |
| 133 | + |
| 134 | + if _wait_until_ready(check_fn, timeout=timeout): |
| 135 | + print(f'[BRIDGE] {name} ready') |
| 136 | + else: |
| 137 | + print(f'[BRIDGE] WARNING: {name} did not become ready within {timeout}s ' |
| 138 | + f'— continuing anyway, related features will degrade gracefully') |
| 139 | + |
| 140 | +def start_services() -> None: |
| 141 | + """Bring up Ollama + MCP servers if they aren't already reachable.""" |
| 142 | + try: |
| 143 | + import ollama_config |
| 144 | + _start_service('Ollama', 'ollama serve', ollama_config.check_ollama_available) |
| 145 | + except ImportError: |
| 146 | + print('[BRIDGE] ollama_config not found — skipping Ollama auto-start') |
| 147 | + |
| 148 | + if MCP_AVAILABLE: |
| 149 | + client = get_mcp_client() |
| 150 | + _start_service( |
| 151 | + 'MCP filesystem server', |
| 152 | + f'npx @modelcontextprotocol/server-filesystem --port 3000 "{os.getcwd()}"', |
| 153 | + client.fs_available |
| 154 | + ) |
| 155 | + if platform.system() == 'Windows': |
| 156 | + _start_service( |
| 157 | + 'windows-mcp', |
| 158 | + 'windows-mcp serve --transport sse --host localhost --port 8000', |
| 159 | + client.win_available |
| 160 | + ) |
| 161 | + else: |
| 162 | + print('[BRIDGE] caios_mcp_client.py not found — MCP servers not auto-started') |
| 163 | + |
| 164 | +@atexit.register |
| 165 | +def _cleanup_services() -> None: |
| 166 | + for p in _spawned_procs: |
| 167 | + try: |
| 168 | + p.terminate() |
| 169 | + except Exception: |
| 170 | + pass |
| 171 | + if _spawned_procs: |
| 172 | + print('[BRIDGE] Spawned services terminated') |
| 173 | + |
89 | 174 | # ============================================================================= |
90 | 175 | # Helpers |
91 | 176 | # ============================================================================= |
@@ -558,4 +643,5 @@ def api_mcp(): |
558 | 643 | print(' Open http://localhost:5000 in your browser') |
559 | 644 | print(' Ctrl+C to stop') |
560 | 645 | print('=' * 60) |
| 646 | + start_services() |
561 | 647 | app.run(host='0.0.0.0', port=5000, debug=False) |
0 commit comments