Skip to content

Commit

Permalink
Add support for autolaunching the browser
Browse files Browse the repository at this point in the history
  • Loading branch information
geoffxy committed Nov 25, 2024
1 parent 23a4515 commit d70e794
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 11 deletions.
9 changes: 8 additions & 1 deletion src/conductor/cli/explorer.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,20 @@ def register_command(subparsers):
default=8000,
help="The port to listen on when serving the explorer.",
)
parser.add_argument(
"--no-browser",
action="store_true",
help="If set, do not automatically start the web browser.",
)
parser.set_defaults(func=main)


@cli_command
def main(args):
try:
start_explorer(host=args.host, port=args.port)
start_explorer(
host=args.host, port=args.port, launch_browser=not args.no_browser
)
except ConductorAbort:
# We ignore this exception because it is raised when the user hits
# Ctrl+C to shut down the server.
Expand Down
50 changes: 40 additions & 10 deletions src/conductor/explorer/explorer.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import time
import webbrowser
import threading
from conductor.errors import MissingExplorerSupport


def start_explorer(host: str, port: int) -> None:
def start_explorer(host: str, port: int, launch_browser: bool) -> None:
"""
Entrypoint to launching Conductor's explorer. This function will attempt to
start the explorer. If the user has not installed the necessary
Expand All @@ -12,14 +15,41 @@ def start_explorer(host: str, port: int) -> None:
# user has not installed Conductor's UI dependencies.
try:
import uvicorn

uvicorn_config = uvicorn.Config(
"conductor.explorer.routes:app",
host=host,
port=port,
log_level="info",
)
server = uvicorn.Server(uvicorn_config)
server.run()
except ImportError as ex:
raise MissingExplorerSupport() from ex

uvicorn_config = uvicorn.Config(
"conductor.explorer.routes:app",
host=host,
port=port,
log_level="info",
)
server = uvicorn.Server(uvicorn_config)

# Start the server and launch the browser if requested.
try:
if launch_browser:
launch_thread = threading.Thread(
target=_launch_browser, args=(host, port, 1)
)
launch_thread.start()
else:
launch_thread = None

server.run()
finally:
if launch_thread is not None:
launch_thread.join()


def _launch_browser(host: str, port: int, wait_s: int) -> None:
"""
Launches the user's default browser to the Conductor explorer's URL.
"""
# We want to start the web browser after the server has started.
# Unfortunately, uvicorn does not provide any nice "callback"-like
# mechanisms to know when it has started. So we use this heuristic approach
# of waiting for a few seconds. This is ugly, but keeps things simple
# without overengineering something meant to be cosmetic.
time.sleep(wait_s)
webbrowser.open(f"http://{host}:{port}")
6 changes: 6 additions & 0 deletions website/docs/cli/explorer.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ will be port 8000.
The host that Conductor's explorer tool will bind to. If unspecified, this will
be `localhost`. Generally, you will not need to modify this value.

### `--no-browser`

If set, Conductor will not automatically launch a web browser. By default, this
explorer command will start a web browser pointed at the explorer's web
interface.

### `-h` or `--help`

Prints a help message that provides details about how to use the `cond explorer`
Expand Down

0 comments on commit d70e794

Please sign in to comment.