Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,4 @@ test/
data/*
!data/seeds/
server/data/
onnxruntime-*/
24 changes: 23 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: help build build-admin build-voice dev dev-admin dev-voice clean download-model swagger docker-build docker-buildx docker-push postgres redis ollama infra infra-stop infra-clean
.PHONY: help build build-admin build-voice dev dev-admin dev-voice clean download-model swagger docker-build docker-buildx docker-push postgres redis ollama infra infra-stop infra-clean docs docs-stop

CONFIG ?= config.yaml

Expand All @@ -15,6 +15,8 @@ help:
@echo " dev-admin Start admin UI dev server (Vite, port 5173)"
@echo " dev-voice Start voice UI dev server (Vite, port 5174)"
@echo " swagger Regenerate Swagger docs from annotations"
@echo " docs Start documentation site (Hugo, port 1313)"
@echo " docs-stop Stop documentation site"
@echo " clean Remove generated files"
@echo ""
@echo "Models:"
Expand Down Expand Up @@ -102,6 +104,26 @@ docker-push:
@docker buildx build -f docker/build/Dockerfile --platform $(DOCKER_PLATFORMS) -t $(IMAGE_NAME):$(IMAGE_TAG) --push .
@echo "Image pushed: $(IMAGE_NAME):$(IMAGE_TAG) [$(DOCKER_PLATFORMS)]"

# Documentation (Docker)

HUGO_VERSION ?= 0.147.1
DOCS_PORT ?= 1313

docs:
@echo "Starting documentation site on http://localhost:$(DOCS_PORT) ..."
@docker run -d --name magec-docs \
-p $(DOCS_PORT):1313 \
-v $(CURDIR)/website:/src \
hugomods/hugo:$(HUGO_VERSION) \
hugo server --bind 0.0.0.0 --baseURL http://localhost:$(DOCS_PORT) --disableFastRender
@echo "Documentation site running at http://localhost:$(DOCS_PORT)"
@echo "Stop with: make docs-stop"

docs-stop:
@docker stop magec-docs 2>/dev/null || true
@docker rm magec-docs 2>/dev/null || true
@echo "Documentation site stopped"

# Infrastructure (Docker)

postgres:
Expand Down
10 changes: 10 additions & 0 deletions docker/compose/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,18 @@ services:
- REQUIRE_API_KEY=False
restart: unless-stopped

cliproxyapi:
image: eceasy/cli-proxy-api:latest
ports:
- "54545:54545" # OAuth callback (required for login only)
volumes:
- ./cliproxyapi/config.yaml:/CLIProxyAPI/config.yaml
- cliproxyapi_auth:/CLIProxyAPI/auth
restart: unless-stopped

volumes:
magec_data:
redis_data:
postgres_data:
ollama_data:
cliproxyapi_auth:
146 changes: 145 additions & 1 deletion scripts/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,42 @@ choose \

LLM_CHOICE="$REPLY"

# ── CLIProxyAPI (use provider subscription as API) ───────────────────────

WANT_CLIPROXYAPI=false

if [[ "$LLM_CHOICE" == "2" || "$LLM_CHOICE" == "3" ]]; then
echo
box_top
box_empty
box_line " Use Your Subscription Instead of an API Key?" "$BOLD" "center"
box_empty
box_sep
box_empty
box_line " Some AI providers offer paid subscriptions"
box_line " (e.g., Claude Max/Pro, ChatGPT Plus) that are"
box_line " separate from their API billing."
box_empty
box_line " CLIProxyAPI is a local proxy that lets you"
box_line " use your existing subscription with Magec"
box_line " instead of paying separately for API access."
box_line " You log in once and Magec can use the models"
box_line " from your subscription."
box_empty
box_line " ${DIM}You can still add a regular API key later${NC}"
box_line " ${DIM}if you prefer.${NC}"
box_empty
box_bottom
echo

if ask_yn "Enable subscription proxy (CLIProxyAPI)?" "n"; then
WANT_CLIPROXYAPI=true
ok "CLIProxyAPI will be configured"
else
info "Skipped — you can set it up later"
fi
fi

# ═══════════════════════════════════════════════════════════════════════════
# STEP 3 — MEMORY
# ═══════════════════════════════════════════════════════════════════════════
Expand Down Expand Up @@ -727,6 +763,9 @@ box_empty
box_line " ${BOLD}Install method:${NC} $method_label"
box_line " ${BOLD}System:${NC} ${os_label} (${arch_label})"
box_line " ${BOLD}AI models:${NC} $llm_label"
if $WANT_CLIPROXYAPI; then
box_line " ${BOLD}Subscription proxy:${NC} Enabled (CLIProxyAPI)"
fi
box_line " ${BOLD}Conversation memory:${NC} $($WANT_REDIS && echo "Yes" || echo "No")"
box_line " ${BOLD}Long-term memory:${NC} $($WANT_POSTGRES && echo "Yes" || echo "No")"
box_line " ${BOLD}Voice:${NC} $voice_label"
Expand Down Expand Up @@ -1314,6 +1353,54 @@ install_binary() {
install_onnx_runtime
fi

# ── CLIProxyAPI setup (binary) ───────────────────────────────────────

if $WANT_CLIPROXYAPI; then
cls
echo
printf " $(badge " SETUP " "$BG_YELLOW" "$FG_BLACK") ${BOLD}Subscription proxy (CLIProxyAPI)${NC}\n"
printf " ${DIM}$(hline '─' "$BOX_W")${NC}\n"
echo

box_top
box_empty
box_line " CLIProxyAPI runs as a separate service."
box_line " You can run it via Docker or download the"
box_line " binary from GitHub."
box_empty
box_sep
box_empty
box_line " ${BOLD}Option A — Docker (recommended):${NC}"
box_empty
box_line " ${CYAN}docker run -d -p 8317:8317 -p 54545:54545 \\${NC}"
box_line " ${CYAN} -v \$(pwd)/cliproxyapi/config.yaml:\\${NC}"
box_line " ${CYAN} /CLIProxyAPI/config.yaml \\${NC}"
box_line " ${CYAN} -v cliproxyapi_auth:/CLIProxyAPI/auth \\${NC}"
box_line " ${CYAN} --name magec-cliproxyapi \\${NC}"
box_line " ${CYAN} eceasy/cli-proxy-api:latest${NC}"
box_empty
box_sep
box_empty
box_line " ${BOLD}Option B — Binary:${NC}"
box_empty
box_line " ${CYAN}https://github.com/router-for-me/CLIProxyAPI/releases${NC}"
box_empty
box_sep
box_empty
box_line " ${BOLD}After starting, log in to your provider.${NC}"
box_line " ${BOLD}See the guide for supported providers:${NC}"
box_empty
box_line " ${CYAN}https://magec.dev/docs/subscription-proxy/${NC}"
box_empty
box_bottom
echo

printf " ${DIM}Press Enter to continue...${NC}"
read -r < /dev/tty

generate_cliproxyapi_config
fi

# ── Generate config ─────────────────────────────────────────────────

echo
Expand Down Expand Up @@ -1458,6 +1545,9 @@ install_containers() {

info "Creating configuration files..."
generate_docker_compose
if $WANT_CLIPROXYAPI; then
generate_cliproxyapi_config
fi
if ! $SKIP_CONFIG; then
generate_config_yaml
else
Expand Down Expand Up @@ -1485,6 +1575,18 @@ install_containers() {
# CONFIGURATION GENERATORS
# ═══════════════════════════════════════════════════════════════════════════

generate_cliproxyapi_config() {
mkdir -p cliproxyapi
cat > cliproxyapi/config.yaml <<'CLIPROXY'
host: "0.0.0.0"
port: 8317
auth-dir: "/CLIProxyAPI/auth"
api-keys:
- "sk-magec-local"
CLIPROXY
ok "cliproxyapi/config.yaml"
}

generate_config_yaml() {
local voice_enabled="true"
[[ "$WANT_VOICE" != true ]] && voice_enabled="false"
Expand Down Expand Up @@ -1533,6 +1635,7 @@ generate_store_json() {
local openai_backend_id="$(gen_uuid)"
local anthropic_backend_id="$(gen_uuid)"
local gemini_backend_id="$(gen_uuid)"
local cliproxyapi_backend_id="$(gen_uuid)"
local parakeet_backend_id="$(gen_uuid)"
local tts_backend_id="$(gen_uuid)"

Expand All @@ -1548,6 +1651,12 @@ generate_store_json() {
backend_entries+=("{\"id\":\"${gemini_backend_id}\",\"name\":\"Gemini\",\"type\":\"gemini\",\"url\":\"\",\"apiKey\":\"\"}")
fi

if $WANT_CLIPROXYAPI; then
local cliproxyapi_url="http://localhost:8317"
[[ "$INSTALL_METHOD" == "2" ]] && cliproxyapi_url="http://cliproxyapi:8317"
backend_entries+=("{\"id\":\"${cliproxyapi_backend_id}\",\"name\":\"Subscription Proxy\",\"type\":\"anthropic\",\"url\":\"${cliproxyapi_url}\",\"apiKey\":\"sk-magec-local\"}")
fi

if [[ "$WANT_VOICE" == true ]]; then
local parakeet_url="http://localhost:5092"
local tts_url="http://localhost:5050"
Expand Down Expand Up @@ -1601,6 +1710,9 @@ generate_store_json() {
if [[ "$LLM_CHOICE" == "1" || "$LLM_CHOICE" == "3" ]]; then
llm_backend_id="$ollama_backend_id"
llm_model="qwen3:8b"
elif [[ "$LLM_CHOICE" == "2" ]] && $WANT_CLIPROXYAPI; then
llm_backend_id="$cliproxyapi_backend_id"
llm_model="claude-sonnet-4-20250514"
elif [[ "$LLM_CHOICE" == "2" ]]; then
llm_backend_id="$anthropic_backend_id"
llm_model="claude-sonnet-4-20250514"
Expand Down Expand Up @@ -1771,6 +1883,18 @@ generate_docker_compose() {
services+=" restart: unless-stopped\n"
fi

if $WANT_CLIPROXYAPI; then
services+="\n cliproxyapi:\n"
services+=" image: eceasy/cli-proxy-api:latest\n"
services+=" ports:\n"
services+=" - \"54545:54545\"\n"
services+=" volumes:\n"
services+=" - ./cliproxyapi/config.yaml:/CLIProxyAPI/config.yaml\n"
services+=" - cliproxyapi_auth:/CLIProxyAPI/auth\n"
services+=" restart: unless-stopped\n"
volumes+=" cliproxyapi_auth:\n"
fi

printf "services:\n" > docker-compose.yaml
printf '%b' "$services" >> docker-compose.yaml
printf "\nvolumes:\n" >> docker-compose.yaml
Expand Down Expand Up @@ -1908,12 +2032,32 @@ EOF
fi
box_empty

if [[ "$LLM_CHOICE" == "2" || "$LLM_CHOICE" == "3" ]]; then
if $WANT_CLIPROXYAPI; then
box_sep
box_empty
box_line " ${YELLOW}Action needed:${NC} Log in to your provider."
box_line " See the subscription proxy guide for login"
box_line " commands for each supported provider:"
box_empty
box_line " ${CYAN}https://magec.dev/docs/subscription-proxy/${NC}"
box_empty
box_line " A subscription proxy backend has been"
box_line " pre-configured. After login, it's ready to use."
box_empty
fi

if [[ "$LLM_CHOICE" == "2" || "$LLM_CHOICE" == "3" ]] && ! $WANT_CLIPROXYAPI; then
box_sep
box_empty
box_line " ${YELLOW}Remember:${NC} Cloud AI providers need API keys."
box_line " Add them in Admin Panel → Backends."
box_empty
elif [[ "$LLM_CHOICE" == "2" || "$LLM_CHOICE" == "3" ]] && $WANT_CLIPROXYAPI; then
box_sep
box_empty
box_line " ${DIM}Other cloud providers (OpenAI, Gemini) still${NC}"
box_line " ${DIM}need API keys — add them in Admin Panel → Backends.${NC}"
box_empty
fi

if [[ "$INSTALL_METHOD" == "2" ]] && { [[ "$LLM_CHOICE" == "1" || "$LLM_CHOICE" == "3" ]] || $WANT_POSTGRES; }; then
Expand Down
1 change: 1 addition & 0 deletions server/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@ func createLLM(ctx context.Context, backend store.BackendDefinition, llmRef stor
case config.BackendTypeAnthropic:
return genaianthro.New(genaianthro.Config{
APIKey: backend.APIKey,
BaseURL: backend.URL,
ModelName: llmRef.Model,
HTTPOptions: genaianthro.HTTPOptions{
Headers: headers,
Expand Down
7 changes: 6 additions & 1 deletion website/content/docs/backends.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ Every agent references a backend for its LLM. Optionally, an agent can also refe
{{< screenshot src="img/screenshots/admin-backends.png" alt="Admin UI — Backends" >}}
</div>

{{< callout type="info" >}}
Have a paid subscription with a provider (e.g., Claude Max/Pro, ChatGPT Plus)? You can use it instead of an API key. See the **[Using a subscription proxy](/docs/subscription-proxy/)** guide.
{{< /callout >}}

## Backend types

Click **+ New Backend** to create one. All types share the same dialog:
Expand Down Expand Up @@ -63,7 +67,8 @@ For Anthropic's Claude models. Uses the official Anthropic API protocol, which i
| Field | Required | Description |
|-------|----------|-------------|
| `name` | Yes | Display name |
| `apiKey` | Yes | Anthropic API key (starts with `sk-ant-`) |
| `url` | No | API base URL. Defaults to `https://api.anthropic.com`. Set this when using [a proxy](https://github.com/router-for-me/CLIProxyAPI). |
| `apiKey` | Yes | Anthropic API key (starts with `sk-ant-`) or proxy API key |

Anthropic doesn't offer STT, TTS, or embedding APIs, so this backend type is used only for LLM inference. For voice and embeddings, add a separate `openai`-type backend pointing at a local service.

Expand Down
6 changes: 6 additions & 0 deletions website/content/docs/install-compose-local.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ docker compose up -d
| **ollama-setup** | Downloads Ollama models on first start, then exits | — |
| **parakeet** | Speech-to-text (NVIDIA Parakeet) | 5092 |
| **tts** | Text-to-speech (OpenAI Edge TTS) | 5050 |
| **cliproxyapi** | Claude subscription proxy ([CLIProxyAPI](https://github.com/router-for-me/CLIProxyAPI)) | 8317 |

## Set up your first agent

Expand Down Expand Up @@ -189,6 +190,10 @@ These providers only offer LLM — STT, TTS, and embeddings stay local. Create t
| Anthropic | `anthropic` | `claude-sonnet-4-20250514` |
| Gemini | `gemini` | `gemini-2.0-flash` |

### Provider subscription (no API key)

If you have a paid subscription with a provider (e.g., Claude Max/Pro, ChatGPT Plus), the included CLIProxyAPI service lets you use their models without a separate API key. See the full **[Using a subscription proxy](/docs/subscription-proxy/)** guide for setup instructions.

## Managing the deployment

```bash
Expand All @@ -215,6 +220,7 @@ All data is stored in Docker volumes:
| `redis_data` | Session memory |
| `postgres_data` | Long-term memory (pgvector) |
| `ollama_data` | Downloaded AI models |
| `cliproxyapi_auth` | CLIProxyAPI OAuth credentials (Claude subscription login) |

Your data survives `docker compose down/up`, image updates, and container recreation. To back up your Magec configuration, copy `data/store.json` from the `magec_data` volume.

Expand Down
Loading