personal memory agent
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Refactor port allocation: supervisor discovers port, convey requires it

Move dynamic port discovery from convey CLI to supervisor so the port
is known before launching convey. Supervisor now prints the Convey URL
on startup. Convey CLI requires --port (no default), and `sol start`
accepts optional port argument (0 = auto-select).

- supervisor.py: find available port, pass to convey, print URL
- convey/cli.py: require --port, remove port discovery logic
- convey/screenshot.py: make port required parameter
- convey/__init__.py: remove unused run_service export
- docs/INSTALL.md: update to reference dynamic port
- think/mcp.py: clarify cortex uses dynamic port in help text

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

+46 -22
-2
convey/__init__.py
··· 17 17 from . import state 18 18 from .apps import register_app_context 19 19 from .bridge import emit, register_websocket 20 - from .cli import run_service 21 20 from .config import bp as config_bp 22 21 from .root import bp as root_bp 23 22 24 23 __all__ = [ 25 24 "create_app", 26 25 "emit", 27 - "run_service", 28 26 ] 29 27 30 28
+6 -10
convey/cli.py
··· 34 34 app: Flask, 35 35 *, 36 36 host: str = "0.0.0.0", 37 - port: int = 8000, 37 + port: int, 38 38 debug: bool = False, 39 39 start_watcher: bool = True, 40 40 ) -> None: ··· 66 66 from pathlib import Path 67 67 68 68 from think.utils import ( 69 - find_available_port, 70 69 get_journal, 71 70 setup_cli, 72 71 write_service_port, ··· 79 78 parser.add_argument( 80 79 "--port", 81 80 type=int, 82 - default=0, 83 - help="Port to serve on (0 = auto-select available port)", 81 + required=True, 82 + help="Port to serve on", 84 83 ) 85 84 parser.add_argument( 86 85 "--skip-maint", ··· 105 104 "No password configured - add to config/journal.json to enable authentication" 106 105 ) 107 106 108 - # Determine port: use specified port or find an available one 109 - port = args.port if args.port != 0 else find_available_port() 110 - 111 107 # Write port to health directory for discovery by other tools 112 - write_service_port("convey", port) 113 - logger.info(f"Convey starting on port {port}") 108 + write_service_port("convey", args.port) 109 + logger.info(f"Convey starting on port {args.port}") 114 110 115 - run_service(app, host="0.0.0.0", port=port, debug=args.debug) 111 + run_service(app, host="0.0.0.0", port=args.port, debug=args.debug)
+2 -2
convey/screenshot.py
··· 26 26 27 27 def screenshot( 28 28 route: str, 29 + port: int, 29 30 output_path: str = "logs/screenshot.png", 30 31 host: str = "localhost", 31 - port: int = 8000, 32 32 width: int = 1440, 33 33 height: int = 900, 34 34 script: str | None = None, ··· 40 40 41 41 Args: 42 42 route: The route to screenshot (e.g., "/", "/facets") 43 + port: Server port 43 44 output_path: Where to save the screenshot (default: logs/screenshot.png) 44 45 host: Server host (default: localhost) 45 - port: Server port (default: 8000) 46 46 width: Viewport width (default: 1440) 47 47 height: Viewport height (default: 900) 48 48 script: Optional JavaScript to execute before taking screenshot
+1 -1
docs/INSTALL.md
··· 195 195 196 196 ### Access the Interface 197 197 198 - Open http://localhost:8000/ in your browser and log in with your password. 198 + Open the Convey URL shown in the terminal (port is dynamically assigned) and log in with your password. 199 199 200 200 ### Configure Your Identity 201 201
+1 -1
think/mcp.py
··· 208 208 "--port", 209 209 type=int, 210 210 default=6270, 211 - help="Port to bind to for HTTP transport (default: 6270)", 211 + help="Port to bind to for HTTP transport (default: 6270; cortex uses dynamic port)", 212 212 ) 213 213 parser.add_argument( 214 214 "--path", default="/mcp", help="HTTP path for MCP endpoints (default: /mcp)"
+36 -6
think/supervisor.py
··· 20 20 from observe.sync import check_remote_health 21 21 from think.callosum import CallosumConnection, CallosumServer 22 22 from think.runner import ManagedProcess as RunnerManagedProcess 23 - from think.utils import get_journal, get_journal_info, now_ms, setup_cli 23 + from think.utils import ( 24 + find_available_port, 25 + get_journal, 26 + get_journal_info, 27 + now_ms, 28 + setup_cli, 29 + ) 24 30 25 31 DEFAULT_THRESHOLD = 60 26 32 CHECK_INTERVAL = 30 ··· 787 793 return _launch_process("cortex", cmd, restart=True) 788 794 789 795 790 - def start_convey_server(verbose: bool, debug: bool = False) -> ManagedProcess: 791 - """Launch the Convey web application with optional verbose and debug logging.""" 796 + def start_convey_server( 797 + verbose: bool, debug: bool = False, port: int = 0 798 + ) -> tuple[ManagedProcess, int]: 799 + """Launch the Convey web application with optional verbose and debug logging. 800 + 801 + Returns: 802 + Tuple of (ManagedProcess, resolved_port) where resolved_port is the 803 + actual port being used (auto-selected if port was 0). 804 + """ 805 + # Resolve port 0 to an available port before launching 806 + resolved_port = port if port != 0 else find_available_port() 792 807 793 - cmd = ["sol", "convey"] 808 + cmd = ["sol", "convey", "--port", str(resolved_port)] 794 809 if debug: 795 810 cmd.append("-d") 796 811 elif verbose: 797 812 cmd.append("-v") 798 - return _launch_process("convey", cmd, restart=True) 813 + return _launch_process("convey", cmd, restart=True), resolved_port 799 814 800 815 801 816 def check_runner_exits(procs: list[ManagedProcess]) -> list[ManagedProcess]: ··· 1190 1205 def parse_args() -> argparse.ArgumentParser: 1191 1206 parser = argparse.ArgumentParser(description="Monitor journaling health") 1192 1207 parser.add_argument( 1208 + "port", 1209 + nargs="?", 1210 + type=int, 1211 + default=0, 1212 + help="Convey port (0 = auto-select available port)", 1213 + ) 1214 + parser.add_argument( 1193 1215 "--threshold", 1194 1216 type=int, 1195 1217 default=DEFAULT_THRESHOLD, ··· 1331 1353 if not args.no_observers: 1332 1354 procs.append(start_observer()) 1333 1355 # Cortex and Convey only run in local mode (remote has no data to serve) 1356 + convey_port = None 1334 1357 if not _is_remote_mode and not args.no_cortex: 1335 1358 procs.append(start_cortex_server()) 1336 1359 if not _is_remote_mode and not args.no_convey: 1337 - procs.append(start_convey_server(verbose=args.verbose, debug=args.debug)) 1360 + proc, convey_port = start_convey_server( 1361 + verbose=args.verbose, debug=args.debug, port=args.port 1362 + ) 1363 + procs.append(proc) 1338 1364 1339 1365 # Make procs accessible to restart handler 1340 1366 _managed_procs = procs 1341 1367 1342 1368 # Initialize daily state to today - dream only triggers at midnight when day changes 1343 1369 _daily_state["last_day"] = datetime.now().date() 1370 + 1371 + # Show Convey URL if running 1372 + if convey_port: 1373 + print(f"Convey: http://localhost:{convey_port}/") 1344 1374 1345 1375 logging.info(f"Started {len(procs)} processes, entering supervision loop") 1346 1376 daily_enabled = not args.no_daily and not _is_remote_mode