| | #!/bin/bash |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | set -e |
| |
|
| | |
| |
|
| | HF_TOKEN="${HF_TOKEN:-}" |
| |
|
| | if [[ -z "$HF_TOKEN" ]]; then |
| | HF_TOKEN=$(python3 -c "from huggingface_hub.utils import get_token; print(get_token() or '', end='')" 2>/dev/null) |
| | fi |
| |
|
| | if [[ -z "$HF_TOKEN" ]]; then |
| | echo "Error: Not logged in. Run 'hf auth login' or export HF_TOKEN." >&2 |
| | exit 1 |
| | fi |
| |
|
| | |
| |
|
| | usage() { |
| | cat >&2 << 'EOF' |
| | Usage: hf tool run launch [agent] [options] [-- extra-args...] |
| |
|
| | Agents: claude, opencode |
| |
|
| | Options: |
| | --model <id> Model ID (e.g. Qwen/Qwen3-235B-A22B) |
| | --provider <name> Inference provider (e.g. fireworks-ai). Default: auto |
| | -h, --help Show this help |
| |
|
| | Examples: |
| | hf tool run launch |
| | hf tool run launch claude |
| | hf tool run launch claude --model Qwen/Qwen3-235B-A22B |
| | hf tool run launch claude --model Qwen/Qwen3-235B-A22B --provider fireworks-ai |
| | hf tool run launch opencode |
| | EOF |
| | exit 1 |
| | } |
| |
|
| | |
| |
|
| | AGENT="" |
| | MODEL="" |
| | PROVIDER="" |
| | EXTRA_ARGS=() |
| |
|
| | case "${1:-}" in |
| | -h|--help) usage ;; |
| | --) shift; EXTRA_ARGS=("$@") ;; |
| | "") ;; |
| | -*) ;; |
| | *) AGENT="$1"; shift ;; |
| | esac |
| |
|
| | while [[ $# -gt 0 ]]; do |
| | case "$1" in |
| | --model) MODEL="$2"; shift 2 ;; |
| | --provider) PROVIDER="$2"; shift 2 ;; |
| | -h|--help) usage ;; |
| | --) shift; EXTRA_ARGS=("$@"); break ;; |
| | *) EXTRA_ARGS+=("$1"); shift ;; |
| | esac |
| | done |
| |
|
| | |
| |
|
| | if [[ -z "$MODEL" ]]; then |
| | MODEL_DATA=$(curl -s "https://router.huggingface.co/v1/models" \ |
| | -H "Authorization: Bearer $HF_TOKEN" 2>/dev/null) |
| |
|
| | MODEL=$(echo "$MODEL_DATA" | jq -r '.data[].id' | fzf --prompt="HF Model: " \ |
| | --height=50% \ |
| | --reverse \ |
| | --header="HuggingFace Router - Select Model" \ |
| | --preview='echo {}' \ |
| | --preview-window=up:1) |
| |
|
| | if [[ -z "$MODEL" ]]; then |
| | echo "No model selected" >&2 |
| | exit 1 |
| | fi |
| |
|
| | PROVIDER=$( (echo "auto"; echo "$MODEL_DATA" | jq -r --arg model "$MODEL" \ |
| | '.data[] | select(.id == $model) | .providers[].provider') \ |
| | | fzf --prompt="Provider: " \ |
| | --height=20% \ |
| | --reverse \ |
| | --header="Select Provider for $MODEL (auto = no suffix)") |
| |
|
| | if [[ -z "$PROVIDER" ]]; then |
| | echo "No provider selected" >&2 |
| | exit 1 |
| | fi |
| | fi |
| |
|
| | |
| |
|
| | if [[ -z "$AGENT" ]]; then |
| | AGENT=$(printf "claude\nopencode" | fzf --prompt="CLI: " \ |
| | --height=10% \ |
| | --reverse \ |
| | --header="Select CLI") |
| |
|
| | if [[ -z "$AGENT" ]]; then |
| | echo "No CLI selected" >&2 |
| | exit 1 |
| | fi |
| | fi |
| |
|
| | case "$AGENT" in |
| | claude|opencode) ;; |
| | *) echo "Error: Unknown agent '$AGENT'. Choose: claude, opencode" >&2; exit 1 ;; |
| | esac |
| |
|
| | |
| |
|
| | if [[ "$PROVIDER" == "auto" || -z "$PROVIDER" ]]; then |
| | MODEL_STRING="$MODEL" |
| | else |
| | MODEL_STRING="${MODEL}:${PROVIDER}" |
| | fi |
| |
|
| | echo "→ $AGENT @ $MODEL_STRING" >&2 |
| |
|
| | |
| |
|
| | case "$AGENT" in |
| | claude) |
| | export ANTHROPIC_API_KEY="$HF_TOKEN" |
| | export ANTHROPIC_AUTH_TOKEN="$HF_TOKEN" |
| | export ANTHROPIC_BASE_URL="https://router.huggingface.co" |
| | export ANTHROPIC_DEFAULT_SONNET_MODEL="$MODEL_STRING" |
| | export ANTHROPIC_DEFAULT_HAIKU_MODEL="$MODEL_STRING" |
| | export ANTHROPIC_DEFAULT_OPUS_MODEL="$MODEL_STRING" |
| | exec claude --model "$MODEL_STRING" "${EXTRA_ARGS[@]}" |
| | ;; |
| | opencode) |
| | exec opencode -m "huggingface/$MODEL_STRING" "${EXTRA_ARGS[@]}" |
| | ;; |
| | esac |
| |
|