From 064da1e20b87020c100ef8516740b5eaeba7401b Mon Sep 17 00:00:00 2001 From: Ivan Charapanau Date: Mon, 5 Aug 2024 02:24:29 +0200 Subject: [PATCH] feat: harbor qr - print service QR code in a terminal --- README.md | 5 +++ compose.qrgen.yml | 6 ++++ harbor.sh | 81 +++++++++++++++++++++++++++++++++++------- open-webui/config.json | 9 ----- qrgen/Dockerfile | 10 ++++++ qrgen/gen.ts | 12 +++++++ 6 files changed, 102 insertions(+), 21 deletions(-) create mode 100644 compose.qrgen.yml create mode 100644 qrgen/Dockerfile create mode 100644 qrgen/gen.ts diff --git a/README.md b/README.md index 64612b2..96ac4ca 100644 --- a/README.md +++ b/README.md @@ -77,12 +77,17 @@ harbor vllm model google/gemma-2-2b-it harbor aphrodite model google/gemma-2-2b-it harbor tabbyapi model google/gemma-2-2b-it-exl2 harbor mistralrs model google/gemma-2-2b-it +harbor opint model google/gemma-2-2b-it # Convenience tools for docker setup harbor logs llamacpp harbor exec llamacpp ./scripts/llama-bench --help harbor shell tabbyapi +# Tell your shell that you don't like it anymore, +# courtesy of Open Interpreter +harbor opint + # Access service CLIs without installing them harbor hf scan-cache harbor ollama list diff --git a/compose.qrgen.yml b/compose.qrgen.yml new file mode 100644 index 0000000..f1cd0d0 --- /dev/null +++ b/compose.qrgen.yml @@ -0,0 +1,6 @@ +services: + qrgen: + build: + context: ./qrgen + dockerfile: Dockerfile + diff --git a/harbor.sh b/harbor.sh index 86d3249..459169e 100755 --- a/harbor.sh +++ b/harbor.sh @@ -35,18 +35,23 @@ show_help() { echo " openai - Configure OpenAI API keys and URLs" echo " vllm - Configure VLLM service" echo " aphrodite - Configure Aphrodite service" - echo " parllama - Launch Parllama - TUI for chatting with Ollama models" + echo " tabbyapi - Configure TabbyAPI service" + echo " mistralrs - Configure mistral.rs service" echo - echo "Huggingface CLI:" - echo " hf [dl|parse-url|token] - Run the Harbor's Huggingface CLI. Expanded with a few additional commands." - echo " hf dl - HuggingFaceModelDownloader CLI" - echo " hf parse-url - Parse file URL from Hugging Face" - echo " hf token - Get/set the Hugging Face Hub token" - echo " hf * - Anything else is passed to the official Huggingface CLI" + echo "Service CLIs:" + echo " parllama - Launch Parllama - TUI for chatting with Ollama models" + echo " plandex - Launch Plandex CLI" + echo " interpreter|opint - Launch Open Interpreter CLI" + echo " hf - Run the Harbor's Huggingface CLI. Expanded with a few additional commands." + echo " hf dl - HuggingFaceModelDownloader CLI" + echo " hf parse-url - Parse file URL from Hugging Face" + echo " hf token - Get/set the Hugging Face Hub token" + echo " hf * - Anything else is passed to the official Huggingface CLI" echo echo "Harbor CLI Commands:" echo " open handle - Open a service in the default browser" echo " url - Get the URL for a service" + echo " qr - Print a QR code for a service" echo " config [get|set|ls] - Manage the Harbor environment configuration" echo " config ls - All config values in ENV format" echo " config get - Get a specific config value" @@ -263,7 +268,7 @@ unlink_cli() { fi } -get_service_url() { +get_service_port() { # Get list of running services services=$(docker ps --format "{{.Names}}") @@ -275,7 +280,7 @@ get_service_url() { # If no service name provided, default to webui if [ -z "$1" ]; then - get_service_url "$default_open" + get_service_port "$default_open" return 0 fi @@ -297,10 +302,39 @@ get_service_url() { return 1 fi - # Construct the URL - url="http://localhost:$port" + echo "$port" +} + +get_service_url() { + local service_name="$1" + local port=$(get_service_port "$service_name") - echo "$url" + if [ -z "$port" ]; then + return 1 + fi + + echo "http://localhost:$port" +} + +print_service_qr() { + local ip_address=$(get_ip) + local service_name="$1" + local port=$(get_service_port "$service_name") + + if [ -z "$port" ]; then + echo "Failed to get port for service '$service_name'." + return 1 + fi + + if [ -z "$ip_address" ]; then + echo "Failed to get IP address." + return 1 + fi + + local url="http://$ip_address:$port" + + echo "URL: $url" + $(compose_with_options "qrgen") run --rm qrgen "$url" } sys_info() { @@ -710,6 +744,25 @@ get_active_services() { docker compose ps --format "{{.Service}}" | tr '\n' ' ' } +get_ip() { + # Try ip command first + ip_cmd=$(which ip 2>/dev/null) + if [ -n "$ip_cmd" ]; then + ip route get 1 | awk '{print $7; exit}' + return + fi + + # Fallback to ifconfig + ifconfig_cmd=$(which ifconfig 2>/dev/null) + if [ -n "$ifconfig_cmd" ]; then + ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1' | head -n1 + return + fi + + # Last resort: hostname + hostname -I | awk '{print $1}' +} + # ======================================================================== # == Service CLIs # ======================================================================== @@ -1295,6 +1348,10 @@ case "$1" in shift get_service_url "$@" ;; + qr) + shift + print_service_qr "$@" + ;; version|--version|-v) shift show_version diff --git a/open-webui/config.json b/open-webui/config.json index b05f72f..2308a54 100644 --- a/open-webui/config.json +++ b/open-webui/config.json @@ -3,14 +3,5 @@ "base_urls": [ "http://ollama:11434" ] - }, - "openai": { - "api_base_urls": [ - "http://vllm:8000/v1" - ], - "api_keys": [ - "sk-vllm" - ], - "enabled": true } } \ No newline at end of file diff --git a/qrgen/Dockerfile b/qrgen/Dockerfile new file mode 100644 index 0000000..992f0db --- /dev/null +++ b/qrgen/Dockerfile @@ -0,0 +1,10 @@ +FROM pkgxdev/pkgx + +WORKDIR /app + +RUN pkgx +node@20 npm install qrcode-terminal +COPY ./gen.ts /app/gen.ts +# Activate pkgx env +RUN pkgx gen.ts test + +ENTRYPOINT [ "pkgx", "gen.ts" ] \ No newline at end of file diff --git a/qrgen/gen.ts b/qrgen/gen.ts new file mode 100644 index 0000000..db4ee3b --- /dev/null +++ b/qrgen/gen.ts @@ -0,0 +1,12 @@ +import qrcode from 'qrcode-terminal'; + +// Get the URL from the command line arguments +const url = Deno.args[0]; + +if (!url) { + console.log('Usage: node qrgen/gen.ts '); + Deno.exit(1); +} + +console.log('QR Code:'); +qrcode.generate(url); \ No newline at end of file