์ฝ˜ํ…์ธ ๋กœ ์ด๋™
OmniRoute source

๐Ÿ“– Setup Guide โ€” OmniRoute (ํ•œ๊ตญ์–ด)

ํ„ฐ๋ฏธ๋„ ์ฐฝ
npm install -g omniroute
omniroute

๋Œ€์‹œ๋ณด๋“œ๋Š” http://localhost:20128์—์„œ ์—ด๋ฆฌ๋ฉฐ API ๊ธฐ๋ณธ URL์€ http://localhost:20128/v1์ž…๋‹ˆ๋‹ค.

ํ„ฐ๋ฏธ๋„ ์ฐฝ
pnpm add -g omniroute@latest --allow-build=better-sqlite3 --allow-build=@swc/core
omniroute

pnpm ์‚ฌ์šฉ์ž: better-sqlite3 ๋ฐ @swc/core์˜ ๋„ค์ดํ‹ฐ๋ธŒ ๋นŒ๋“œ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ํ™œ์„ฑํ™”ํ•˜๋ ค๋ฉด --allow-build ํ”Œ๋ž˜๊ทธ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. pnpm v11์˜ ์ „์—ญ ์„ค์น˜์—์„œ๋Š” pnpm approve-builds -g ๋ช…๋ น์ด ์ง€์›๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

ํ„ฐ๋ฏธ๋„ ์ฐฝ
yay -S omniroute-bin
systemctl --user enable --now omniroute.service

AUR ํŒจํ‚ค์ง€๋Š” OmniRoute๋ฅผ ์„ค์น˜ํ•˜๊ณ  systemd ์‚ฌ์šฉ์ž ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

ํ„ฐ๋ฏธ๋„ ์ฐฝ
npm install
PORT=20128 DASHBOARD_PORT=20129 NEXT_PUBLIC_BASE_URL=http://localhost:20129 npm run dev

Windows ์ฐธ๊ณ : ๊ธฐ๋ณธ์ ์œผ๋กœ OmniRoute๋Š” ๊ธฐ์กด %USERPROFILE%\.omniroute ๋””๋ ‰ํ„ฐ๋ฆฌ๊ฐ€ ์—†์„ ๋•Œ %APPDATA%\omniroute๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ ๋””๋ ‰ํ„ฐ๋ฆฌ ์œ„์น˜๋ฅผ ์„ ํƒํ•˜๋ ค๋ฉด DATA_DIR์„ ์„ค์ •ํ•˜์„ธ์š”.

์ฐธ๊ณ : npm install์€ ์ฒ˜์Œ ์‹คํ–‰ํ•  ๋•Œ .env.example์—์„œ .env๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ดํ›„ ์„ค์น˜์—์„œ๋Š” ๊ธฐ์กด .env๋ฅผ ๋ฎ์–ด์“ฐ์ง€ ์•Š์œผ๋ฏ€๋กœ ์‚ฌ์šฉ์ž ์ง€์ • ์„ค์ •์ด ์œ ์ง€๋ฉ๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ดˆ๊ธฐํ™”ํ•˜๋ ค๋ฉด ์žฌ์‹คํ–‰ํ•˜๊ธฐ ์ „์— .env๋ฅผ ์‚ญ์ œํ•˜์„ธ์š”.

Compose ํ”„๋กœํ•„๊ณผ Caddy HTTPS๋ฅผ ํฌํ•จํ•œ ์ „์ฒด Docker ์„ค์ •์€ Docker ๊ฐ€์ด๋“œ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

OmniRoute๋Š” Electron 41 + electron-builder 26.10์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์ถ•๋œ ๋ฐ์Šคํฌํ†ฑ ๋ž˜ํผ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์Šคํฌ๋ฆฝํŠธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค(์›Œํฌ์ŠคํŽ˜์ด์Šค ๋ฃจํŠธ).

ํ„ฐ๋ฏธ๋„ ์ฐฝ
npm run electron:dev # ํ•ซ ๋ฆฌ๋กœ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์Šคํฌํ†ฑ ์‹คํ–‰
npm run electron:build # ํ˜„์žฌ OS์šฉ ๋นŒ๋“œ(์ž๋™ ๊ฐ์ง€)
npm run electron:build:win # Windows ์„ค์น˜ ํ”„๋กœ๊ทธ๋žจ(NSIS + ํฌํ„ฐ๋ธ”)
npm run electron:build:mac # macOS(dmg + zip, arm64+x64)
npm run electron:build:linux # Linux(AppImage + deb + rpm)
npm run electron:smoke:packaged # ํŒจํ‚ค์ง•๋œ ๋นŒ๋“œ ์Šค๋ชจํฌ ํ…Œ์ŠคํŠธ

๋ฐ์Šคํฌํ†ฑ ์„ค์น˜ ํ”„๋กœ๊ทธ๋žจ ๋ฆด๋ฆฌ์Šค๋Š” GitHub Releases์— ์ฒจ๋ถ€๋ฉ๋‹ˆ๋‹ค. ์„œ๋ช…, IPC ๋ธŒ๋ฆฌ์ง€, ๋ฐฐํฌํŒ ๋“ฑ Electron์— ๋Œ€ํ•œ ์ „์ฒด ์ƒ์„ธ ์„ค๋ช…์€ ELECTRON_GUIDE.md๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”. (์ถ”ํ›„ ๋‹จ๊ณ„์—์„œ ์ž‘์„ฑ๋จ).

๋ฌด์ธ ์„ค์ •(Docker, Kubernetes, CI)์˜ ๊ฒฝ์šฐ ๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜์„ธ์š”.

ํ„ฐ๋ฏธ๋„ ์ฐฝ
omniroute setup --non-interactive
omniroute providers test-batch

ํ™˜๊ฒฝ ๋ณ€์ˆ˜(INITIAL_PASSWORD, OMNIROUTE_WS_BRIDGE_SECRET ๋“ฑ)์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ฉด OmniRoute ์ธ์Šคํ„ด์Šค๋ฅผ ์™„์ „ํžˆ ์Šคํฌ๋ฆฝํŠธ ๋ฐฉ์‹์œผ๋กœ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ช…๋ น ์„ค๋ช…
omniroute ์„œ๋ฒ„ ์‹œ์ž‘(PORT=20128, ๋™์ผํ•œ ํฌํŠธ์—์„œ API ๋ฐ ๋Œ€์‹œ๋ณด๋“œ ์ œ๊ณต)
omniroute setup ๋น„๋ฐ€๋ฒˆํ˜ธ ๋ฐ ์ฒซ ๋ฒˆ์งธ ์ œ๊ณต์ž๋ฅผ ์œ„ํ•œ ์•ˆ๋‚ด์‹ CLI ์˜จ๋ณด๋”ฉ
omniroute doctor ์„œ๋ฒ„๋ฅผ ์‹œ์ž‘ํ•˜์ง€ ์•Š๊ณ  ๋กœ์ปฌ ์ƒํƒœ ๊ฒ€์‚ฌ ์‹คํ–‰
omniroute providers CLI์—์„œ ์ œ๊ณต์ž ๊ฒ€์ƒ‰, ๋ชฉ๋ก ์กฐํšŒ, ๊ฒ€์ฆ ๋ฐ ํ…Œ์ŠคํŠธ
omniroute config CLI ๋„๊ตฌ ๊ตฌ์„ฑ โ€” ๊ตฌ์„ฑ ๋ชฉ๋ก ์กฐํšŒ, ๊ฐ€์ ธ์˜ค๊ธฐ, ์„ค์ • ๋ฐ ๊ฒ€์ฆ
omniroute status ์˜คํ”„๋ผ์ธ ์ƒํƒœ ๋Œ€์‹œ๋ณด๋“œ โ€” ๋ฒ„์ „, DB, ๋„๊ตฌ, ๊ตฌ์„ฑ
omniroute logs API์˜ ์‚ฌ์šฉ ๋กœ๊ทธ ์ŠคํŠธ๋ฆฌ๋ฐ(--follow ์ง€์›)
omniroute update OmniRoute ์—…๋ฐ์ดํŠธ ํ™•์ธ ๋˜๋Š” ์ ์šฉ
omniroute provider ์ œ๊ณต์ž ์—ฐ๊ฒฐ ๊ด€๋ฆฌ โ€” ์ถ”๊ฐ€, ๋ชฉ๋ก ์กฐํšŒ, ์ œ๊ฑฐ, ํ…Œ์ŠคํŠธ, ๊ธฐ๋ณธ๊ฐ’ ์„ค์ •
omniroute --port 3000 ํ‘œ์ค€/API ํฌํŠธ๋ฅผ 3000์œผ๋กœ ์„ค์ •
omniroute --mcp MCP ์„œ๋ฒ„ ์‹œ์ž‘(stdio ์ „์†ก ๋ฐฉ์‹)
omniroute --no-open ๋ธŒ๋ผ์šฐ์ €๋ฅผ ์ž๋™์œผ๋กœ ์—ด์ง€ ์•Š์Œ
omniroute --help ๋„์›€๋ง ํ‘œ์‹œ

ํ—ค๋“œ๋ฆฌ์Šค ์„ค์ •์€ ํ”Œ๋ž˜๊ทธ ๋˜๋Š” ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด ์Šคํฌ๋ฆฝํŠธ๋กœ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ„ฐ๋ฏธ๋„ ์ฐฝ
omniroute setup --non-interactive --password "$OMNIROUTE_PASSWORD"
omniroute setup --non-interactive --add-provider --provider openai --api-key "$OPENAI_API_KEY"
omniroute setup --non-interactive --add-provider --provider openai --api-key "$OPENAI_API_KEY" --test-provider

๋Œ€์‹œ๋ณด๋“œ๋ฅผ ์—ด์ง€ ์•Š๊ณ  ๋กœ์ปฌ ์ง„๋‹จ์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

ํ„ฐ๋ฏธ๋„ ์ฐฝ
omniroute doctor
omniroute doctor --json
omniroute doctor --no-liveness

๋Œ€์‹œ๋ณด๋“œ๋ฅผ ์—ด์ง€ ์•Š๊ณ  SSH ๋˜๋Š” ์Šคํฌ๋ฆฝํŠธ์—์„œ ์ œ๊ณต์ž๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

ํ„ฐ๋ฏธ๋„ ์ฐฝ
omniroute providers available
omniroute providers available --search openai
omniroute providers available --category api-key
omniroute providers list
omniroute providers test <id-or-name>
omniroute providers test-all
omniroute providers validate

  1. Dashboard โ†’ Providers๋ฅผ ์—ด๊ณ  ํ•˜๋‚˜ ์ด์ƒ์˜ ์ œ๊ณต์—…์ฒด๋ฅผ ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค(OAuth ๋˜๋Š” API ํ‚ค).
  2. Dashboard โ†’ Endpoints๋ฅผ ์—ด๊ณ  API ํ‚ค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  3. (์„ ํƒ ์‚ฌํ•ญ) Dashboard โ†’ Combos๋ฅผ ์—ด๊ณ  ํด๋ฐฑ ์ฒด์ธ์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
๊ธฐ๋ณธ URL: http://localhost:20128/v1
API ํ‚ค: [Endpoint ํŽ˜์ด์ง€์—์„œ ๋ณต์‚ฌ]
๋ชจ๋ธ: if/qwen3.8-max-preview (๋˜๋Š” ์ž„์˜์˜ ์ œ๊ณต์—…์ฒด/๋ชจ๋ธ ์ ‘๋‘์‚ฌ)

ํŽธ์ง‘๊ธฐ์—์„œ Authorization: Bearer ...๋ฅผ ์ „์†กํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ์—๋Š” ํ† ํฐ์ด ํฌํ•จ๋œ ํ˜ธํ™˜์„ฑ ๊ธฐ๋ณธ URL์„ ๋Œ€์‹  ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๊ธฐ๋ณธ URL: http://localhost:20128/api/v1/vscode/YOUR_KEY/
๋ชจ๋ธ URL: http://localhost:20128/api/v1/vscode/YOUR_KEY/models
์ฑ„ํŒ… URL: http://localhost:20128/api/v1/vscode/YOUR_KEY/chat/completions
Ollama ํƒœ๊ทธ URL: http://localhost:20128/api/v1/vscode/YOUR_KEY/api/tags

Claude Code, Codex CLI, Cursor, Cline, OpenClaw, OpenCode ๋ฐ OpenAI ํ˜ธํ™˜ SDK์—์„œ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

๊ธฐ๋ณธ URL๊ณผ ํ‚ค๋ฅผ ์ง์ ‘ ๋ถ™์—ฌ ๋„ฃ๋Š” ๋Œ€์‹ , OmniRoute๊ฐ€ ์‹ค์‹œ๊ฐ„ ๋ชจ๋ธ ์นดํƒˆ๋กœ๊ทธ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๊ฐ ๋„๊ตฌ์˜ ์ž์ฒด ๊ตฌ์„ฑ์„ ์ž‘์„ฑํ•˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋„๊ตฌ๋ณ„๋กœ ํ•˜๋‚˜์˜ ๋ช…๋ น์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

ํ„ฐ๋ฏธ๋„ ์ฐฝ
omniroute setup-codex # ~/.codex/<name>.config.toml ํ”„๋กœํ•„
omniroute setup-claude # ~/.claude/profiles/<name>/settings.json
omniroute setup-opencode # ~/.config/opencode/opencode.json (OpenAI ํ˜ธํ™˜)
omniroute setup-cline # Cline CLI + VS Code ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ ์„ค์ •
omniroute setup-kilo # Kilo Code
omniroute setup-continue # ~/.continue/config.yaml (Continue / cn)
omniroute setup-cursor # Cursor์˜ ์•ฑ ๋‚ด ์„ค์ • ์ ˆ์ฐจ ์ถœ๋ ฅ
omniroute setup-roo # Roo Code ๊ฐ€์ ธ์˜ค๊ธฐ + autoImport ํฌ์ธํ„ฐ
omniroute setup-crush # ~/.config/crush/crush.json
omniroute setup-goose # ~/.config/goose/config.yaml
omniroute setup-aider # ~/.aider.conf.yml
omniroute setup-qwen # ~/.qwen/settings.json + ~/.qwen/.env

๊ฐ ๋ช…๋ น์€ ์›๊ฒฉ OmniRoute์— ๋กœ์ปฌ ๋„๊ตฌ๋ฅผ ์—ฐ๊ฒฐํ•˜๋„๋ก ๊ตฌ์„ฑํ•˜๋Š” --remote <url> --api-key <key>์™€ ๋ฏธ๋ฆฌ๋ณด๊ธฐ๋ฅผ ์œ„ํ•œ --dry-run์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์˜ฌ๋ฐ”๋ฅธ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์ฃผ์ž…ํ•˜๋ฉด์„œ ๊ตฌ์„ฑ ํŒŒ์ผ์„ ์ „ํ˜€ ์ž‘์„ฑํ•˜์ง€ ์•Š๊ณ  CLI๋ฅผ ์‹คํ–‰ํ•˜๋ ค๋ฉด ๋ฒ”์šฉ ์‹คํ–‰ ๋ช…๋ น์ธ omniroute run <target>(claude, codex, aider, goose, opencode, qwen, gemini)์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ์กด ๋„๊ตฌ๋ณ„ ์‹คํ–‰ ๋ช…๋ น์ธ omniroute launch(Claude Code)์™€ omniroute launch-codex(Codex)๋„ ๊ณ„์† ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ „์ฒด ํ‘œ(๊ฐ ๋ช…๋ น์ด ์ž‘์„ฑํ•˜๋Š” ํ•ญ๋ชฉ, ๋ชจ๋“  ํ”Œ๋ž˜๊ทธ, ๋กœ์ปฌ๊ณผ ์›๊ฒฉ์˜ ์ฐจ์ด, ๊ธฐ๋ณธ URL์˜ /v1 ๊ทœ์น™)๋Š” **CLI ํ†ตํ•ฉ**์„ ์ฐธ์กฐํ•˜์„ธ์š”.

๋„๊ตฌ๋ณ„ ์ƒ์„ธ ๊ตฌ์„ฑ(Claude Code, Codex CLI, Cursor, Cline, OpenClaw, Kilo Code, Copilot ๋“ฑ)์€ ์ „์šฉ **CLI ๋„๊ตฌ ๊ฐ€์ด๋“œ**๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.


stdio ๋ชจ๋“œ์—์„œ MCP ์ „์†ก์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.

ํ„ฐ๋ฏธ๋„ ์ฐฝ
omniroute --mcp

๊ถŒ์žฅ ๊ฒ€์ฆ ์ ˆ์ฐจ:

ํ„ฐ๋ฏธ๋„ ์ฐฝ
# 1. MCP ์„œ๋ฒ„ ์‹œ์ž‘
omniroute --mcp
# 2. MCP ํด๋ผ์ด์–ธํŠธ์—์„œ ๋‹ค์Œ์„ ํ˜ธ์ถœ:
omniroute_get_health # ์‹œ์Šคํ…œ ์ƒํƒœ๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•จ
omniroute_list_combos # ํ™œ์„ฑ ์ฝค๋ณด๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•จ
# 3. ๋˜๋Š” ์ „์ฒด E2E ์ œํ’ˆ๊ตฐ ์‹คํ–‰:
npm run test:protocols:e2e

Claude Code:

ํ„ฐ๋ฏธ๋„ ์ฐฝ
claude mcp add-server omniroute --type http --url http://localhost:20128/api/mcp/stream

Cursor / Cline:

MCP ์„ค์ •์— ๋‹ค์Œ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

{
"mcpServers": {
"omniroute": {
"command": "omniroute",
"args": ["--mcp"],
"env": {}
}
}
}

์ „์ฒด MCP ๋ฌธ์„œ: MCP ์„œ๋ฒ„ README โ€” ๋„๊ตฌ 110๊ฐœ, IDE ๊ตฌ์„ฑ, Python/TS/Go ํด๋ผ์ด์–ธํŠธ.

Agent Card๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

ํ„ฐ๋ฏธ๋„ ์ฐฝ
curl http://localhost:20128/.well-known/agent.json

์ž‘์—…์„ ์ „์†กํ•ฉ๋‹ˆ๋‹ค.

ํ„ฐ๋ฏธ๋„ ์ฐฝ
curl -X POST http://localhost:20128/a2a \
-H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":"quickstart","method":"message/send","params":{"skill":"quota-management","messages":[{"role":"user","content":"Give me a short quota summary."}]}}'

์ „์ฒด A2A ๋ฌธ์„œ: A2A ์„œ๋ฒ„ README โ€” JSON-RPC 2.0, ์Šคํ‚ฌ, ์ŠคํŠธ๋ฆฌ๋ฐ, ์ž‘์—… ์ˆ˜๋ช… ์ฃผ๊ธฐ.


๋Œ€๋ถ€๋ถ„์˜ ๋ฐฐํฌ์—์„œ๋Š” ๋‹ค์Œ ๋‘ ๋ณ€์ˆ˜๋งŒ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

๋ณ€์ˆ˜ ๊ธฐ๋ณธ๊ฐ’ ์šฉ๋„
REQUEST_TIMEOUT_MS 600000 ์—…์ŠคํŠธ๋ฆผ ์‘๋‹ต ์‹œ์ž‘ ํƒ€์ž„์•„์›ƒ, ์ˆจ๊ฒจ์ง„ Undici ํƒ€์ž„์•„์›ƒ, TLS ์ง€๋ฌธ ์š”์ฒญ ๋ฐ API ๋ธŒ๋ฆฌ์ง€ ์š”์ฒญ/ํ”„๋ก์‹œ ํƒ€์ž„์•„์›ƒ์— ์‚ฌ์šฉ๋˜๋Š” ๊ณตํ†ต ๊ธฐ์ค€๊ฐ’
STREAM_IDLE_TIMEOUT_MS REQUEST_TIMEOUT_MS์—์„œ ์ƒ์† OmniRoute๊ฐ€ SSE ์ŠคํŠธ๋ฆผ์„ ์ค‘๋‹จํ•˜๊ธฐ ์ „๊นŒ์ง€ ํ—ˆ์šฉ๋˜๋Š” ์ŠคํŠธ๋ฆฌ๋ฐ ์ฒญํฌ ๊ฐ„ ์ตœ๋Œ€ ์‹œ๊ฐ„ ๊ฐ„๊ฒฉ

์ด์ „ ๋ฒ„์ „๊ณผ์˜ ํ˜ธํ™˜์„ฑ์€ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค. ๊ธฐ์กด FETCH_TIMEOUT_MS, API_BRIDGE_PROXY_TIMEOUT_MS ๋ฐ ๊ธฐํƒ€ ๊ณ„์ธต๋ณ„ ํƒ€์ž„์•„์›ƒ ๋ณ€์ˆ˜๋Š” ๊ณ„์† ์ž‘๋™ํ•˜๋ฉฐ ๊ณตํ†ต ๊ธฐ์ค€๊ฐ’๋ณด๋‹ค ์šฐ์„  ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.

Claude Code ํ˜ธํ™˜ ์—…์ŠคํŠธ๋ฆผ(anthropic-compatible-cc-*)์˜ ๊ฒฝ์šฐ, OmniRoute๋Š” ํ™•์ธ๋œ ๊ฐ€์ ธ์˜ค๊ธฐ ํƒ€์ž„์•„์›ƒ์—์„œ ์•„์›ƒ๋ฐ”์šด๋“œ X-Stainless-Timeout ํ—ค๋”๋ฅผ ๋„์ถœํ•˜์—ฌ ์ œ๊ณต์ž ์ธก ์ฝ๊ธฐ ํƒ€์ž„์•„์›ƒ์ด ํ™˜๊ฒฝ ๊ตฌ์„ฑ๊ณผ ์ผ์น˜ํ•˜๋„๋ก ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.

์„œ๋“œ ํŒŒํ‹ฐ Claude Code ํ˜ธํ™˜ ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ์˜ ๊ฒฝ์šฐ, OmniRoute๋Š” ๊ธฐ๋ณธ anthropic-beta ์ง‘ํ•ฉ์„ ๋ณด์ˆ˜์ ์œผ๋กœ ์œ ์ง€ํ•˜๋ฉฐ, Client Cache Control์ด Auto๋กœ ์„ค์ •๋˜์–ด ์žˆ์œผ๋ฉด ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ œ๊ณตํ•œ cache_control ๋งˆ์ปค๋งŒ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ์—…์ŠคํŠธ๋ฆผ์—์„œ ํŽธ์ง‘๋œ Claude ์‚ฌ๊ณ  ์ŠคํŠธ๋ฆผ์„ ๋ช…์‹œ์ ์œผ๋กœ ์š”๊ตฌํ•˜๋Š” ๊ฒฝ์šฐ์—๋งŒ ์—ฐ๊ฒฐ๋ณ„ โ€œEnable redact-thinking betaโ€ ํ† ๊ธ€์„ ํ™œ์„ฑํ™”ํ•˜์„ธ์š”.

๋ณ€์ˆ˜ ๊ธฐ๋ณธ๊ฐ’ ์šฉ๋„
FETCH_TIMEOUT_MS REQUEST_TIMEOUT_MS์—์„œ ์ƒ์† ์‘๋‹ต ํ—ค๋”๊ฐ€ ๋„์ฐฉํ•  ๋•Œ๊นŒ์ง€ ์‚ฌ์šฉ๋˜๋Š” ์—…์ŠคํŠธ๋ฆผ ์‘๋‹ต ์‹œ์ž‘ ํƒ€์ž„์•„์›ƒ
FETCH_HEADERS_TIMEOUT_MS FETCH_TIMEOUT_MS์—์„œ ์ƒ์† ์—…์ŠคํŠธ๋ฆผ ์‘๋‹ต ํ—ค๋” ์ˆ˜์‹ ์— ๋Œ€ํ•œ Undici ์ œํ•œ ์‹œ๊ฐ„
FETCH_BODY_TIMEOUT_MS FETCH_TIMEOUT_MS์—์„œ ์ƒ์† ์—…์ŠคํŠธ๋ฆผ ๋ณธ๋ฌธ ์ฒญํฌ ์‚ฌ์ด์˜ Undici ์ œํ•œ ์‹œ๊ฐ„(0์€ ๋น„ํ™œ์„ฑํ™”)
FETCH_CONNECT_TIMEOUT_MS 30000 Undici TCP ์—ฐ๊ฒฐ ํƒ€์ž„์•„์›ƒ
FETCH_KEEPALIVE_TIMEOUT_MS 4000 Undici ์œ ํœด keep-alive ์†Œ์ผ“ ํƒ€์ž„์•„์›ƒ
TLS_CLIENT_TIMEOUT_MS FETCH_TIMEOUT_MS์—์„œ ์ƒ์† wreq-js๋ฅผ ํ†ตํ•ด ์ด๋ฃจ์–ด์ง€๋Š” TLS ์ง€๋ฌธ ์š”์ฒญ์˜ ํƒ€์ž„์•„์›ƒ
API_BRIDGE_PROXY_TIMEOUT_MS REQUEST_TIMEOUT_MS์—์„œ ์ƒ์† ๋˜๋Š” 600000 API ํฌํŠธ์—์„œ ๋Œ€์‹œ๋ณด๋“œ ํฌํŠธ๋กœ ์ „๋‹ฌ๋˜๋Š” /v1 ํ”„๋ก์‹œ์˜ ํƒ€์ž„์•„์›ƒ
API_BRIDGE_SERVER_REQUEST_TIMEOUT_MS max(API_BRIDGE_PROXY_TIMEOUT_MS, 300000) API ๋ธŒ๋ฆฌ์ง€ ์„œ๋ฒ„์˜ ์ˆ˜์‹  ์š”์ฒญ ํƒ€์ž„์•„์›ƒ
API_BRIDGE_SERVER_HEADERS_TIMEOUT_MS 60000 API ๋ธŒ๋ฆฌ์ง€ ์„œ๋ฒ„์˜ ์ˆ˜์‹  ํ—ค๋” ํƒ€์ž„์•„์›ƒ
API_BRIDGE_SERVER_KEEPALIVE_TIMEOUT_MS 5000 API ๋ธŒ๋ฆฌ์ง€ ์„œ๋ฒ„์˜ keep-alive ํƒ€์ž„์•„์›ƒ
API_BRIDGE_SERVER_SOCKET_TIMEOUT_MS 0 API ๋ธŒ๋ฆฌ์ง€ ์„œ๋ฒ„์˜ ์†Œ์ผ“ ๋น„ํ™œ์„ฑ ํƒ€์ž„์•„์›ƒ(0์€ ๋น„ํ™œ์„ฑํ™”)

์ฐธ๊ณ : ์ŠคํŠธ๋ฆฌ๋ฐ ์š”์ฒญ์—์„œ FETCH_TIMEOUT_MS๋Š” ์—ฐ๊ฒฐ ์„ค์ • ๋ฐ ์ฒซ ๋ฒˆ์งธ ์—…์ŠคํŠธ๋ฆผ ์‘๋‹ต ๋Œ€๊ธฐ ์‹œ๊ฐ„์—๋งŒ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ŠคํŠธ๋ฆผ์ด ํ™œ์„ฑํ™”๋œ ์ดํ›„ OmniRoute๋Š” ์‹ค์ œ ์ค‘๋‹จ(STREAM_IDLE_TIMEOUT_MS) ๋˜๋Š” Undici ๋ณธ๋ฌธ ๋น„ํ™œ์„ฑ(FETCH_BODY_TIMEOUT_MS)์ด ๋ฐœ์ƒํ•œ ๊ฒฝ์šฐ์—๋งŒ ์ŠคํŠธ๋ฆผ์„ ์ค‘๋‹จํ•ฉ๋‹ˆ๋‹ค.

Nginx, Caddy, Cloudflare ๋˜๋Š” ๋‹ค๋ฅธ ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ ๋’ค์—์„œ OmniRoute๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ ํ”„๋ก์‹œ ํƒ€์ž„์•„์›ƒ๋„ OmniRoute์˜ ์ŠคํŠธ๋ฆผ/๊ฐ€์ ธ์˜ค๊ธฐ ํƒ€์ž„์•„์›ƒ๋ณด๋‹ค ๊ธธ๊ฒŒ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.


๊ณ ๊ธ‰ ์‹œ๋‚˜๋ฆฌ์˜ค(๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ, ์ปจํ…Œ์ด๋„ˆ ๋„คํŠธ์›Œํ‚น)๋ฅผ ์œ„ํ•ด API์™€ Dashboard๋ฅผ ๋ณ„๋„์˜ ํฌํŠธ์—์„œ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

20128/v1
PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129

Void Linux ์‚ฌ์šฉ์ž๋Š” xbps-src๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋„ค์ดํ‹ฐ๋ธŒ ํŒจํ‚ค์ง€๋ฅผ ๋นŒ๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ธ”๋ก์„ srcpkgs/omniroute/template๋กœ ์ €์žฅํ•˜์„ธ์š”.

ํ„ฐ๋ฏธ๋„ ์ฐฝ
# 'omniroute'์šฉ ํ…œํ”Œ๋ฆฟ ํŒŒ์ผ
pkgname=omniroute
version=3.8.0
revision=1
hostmakedepends="nodejs python3 make"
depends="openssl"
short_desc="์—ฌ๋Ÿฌ LLM ์ œ๊ณต์ž๋ฅผ ์œ„ํ•œ ์Šค๋งˆํŠธ ๋ผ์šฐํŒ… ๊ธฐ๋Šฅ์„ ๊ฐ–์ถ˜ ๋ฒ”์šฉ AI ๊ฒŒ์ดํŠธ์›จ์ด"
maintainer="zenobit <zenobit@disroot.org>"
license="MIT"
homepage="https://github.com/diegosouzapw/OmniRoute"
distfiles="https://github.com/diegosouzapw/OmniRoute/archive/refs/tags/v${version}.tar.gz"
# ๊ฐ ๋ฆด๋ฆฌ์Šค๋งˆ๋‹ค ๋‹ค์Œ ๋ช…๋ น์œผ๋กœ ์ฒดํฌ์„ฌ์„ ๋‹ค์‹œ ์ƒ์„ฑํ•˜์„ธ์š”:
# curl -L -o /tmp/omniroute.tar.gz "https://github.com/diegosouzapw/OmniRoute/archive/refs/tags/v${version}.tar.gz" && sha256sum /tmp/omniroute.tar.gz
checksum=PLACEHOLDER_REGENERATE_PER_RELEASE
system_accounts="_omniroute"
omniroute_homedir="/var/lib/omniroute"
export NODE_ENV=production
export npm_config_engine_strict=false
export npm_config_loglevel=error
export npm_config_fund=false
export npm_config_audit=false
do_build() {
local _gyp_arch
case "$XBPS_TARGET_MACHINE" in
aarch64*) _gyp_arch=arm64 ;;
armv7*|armv6*) _gyp_arch=arm ;;
i686*) _gyp_arch=ia32 ;;
*) _gyp_arch=x64 ;;
esac
NODE_ENV=development npm ci --ignore-scripts
npm run build
cp -r .next/static .next/standalone/.next/static
[ -d public ] && cp -r public .next/standalone/public || true
local _node_gyp=/usr/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js
(cd node_modules/better-sqlite3 && node "$_node_gyp" rebuild --arch="$_gyp_arch")
local _bs3_release=.next/standalone/node_modules/better-sqlite3/build/Release
mkdir -p "$_bs3_release"
cp node_modules/better-sqlite3/build/Release/better_sqlite3.node "$_bs3_release/"
rm -rf .next/standalone/node_modules/@img
for _mod in pino-abstract-transport split2 process-warning; do
cp -r "node_modules/$_mod" .next/standalone/node_modules/
done
}
do_check() {
npm run test:unit
}
do_install() {
vmkdir usr/lib/omniroute/.next
vcopy .next/standalone/. usr/lib/omniroute/.next/standalone
for _d in \
.next/standalone/.next/server/app/dashboard \
.next/standalone/.next/server/app/dashboard/settings \
.next/standalone/.next/server/app/dashboard/providers; do
touch "${DESTDIR}/usr/lib/omniroute/${_d}/.keep"
done
cat > "${WRKDIR}/omniroute" <<'EOF'
#!/bin/sh
export PORT="${PORT:-20128}"
export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}"
export APP_LOG_TO_FILE="${APP_LOG_TO_FILE:-false}"
mkdir -p "${DATA_DIR}"
exec node /usr/lib/omniroute/.next/standalone/server.js "$@"
EOF
vbin "${WRKDIR}/omniroute"
}
post_install() {
vlicense LICENSE
}

๋ช…๋ น ๋™์ž‘
npm run uninstall ์‹œ์Šคํ…œ ์•ฑ์„ ์ œ๊ฑฐํ•˜์ง€๋งŒ ~/.omniroute์˜ DB์™€ ๊ตฌ์„ฑ์€ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.
npm run uninstall:full ์•ฑ์„ ์ œ๊ฑฐํ•˜๊ณ  ๋ชจ๋“  ๊ตฌ์„ฑ, ํ‚ค ๋ฐ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์˜๊ตฌ์ ์œผ๋กœ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.

๋ชจ๋“  ์„ค์น˜ ๋ฐฉ์‹์— ๋Œ€ํ•œ ์ž์„ธํ•œ ์ œ๊ฑฐ ์ง€์นจ์€ UNINSTALL.md๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.


OmniRoute ์†Œ์Šค ์ฝ”๋“œ (a58000c7685f)

HagiCode

HagiCode๋Š” ๊ตฌ์กฐํ™”๋œ ์›Œํฌํ”Œ๋กœ, ๋‹ค์ค‘ ์—์ด์ „ํŠธ ์‹คํ–‰, Hero Dungeon ๋ทฐ๋ฅผ ๊ฐ–์ถ˜ ์—์ด์ „ํŠธ ์ฝ”๋”ฉ ์ž‘์—… ๊ณต๊ฐ„์ž…๋‹ˆ๋‹ค.

๋” ์Šค๋งˆํŠธํ•˜๊ณ  ๋น ๋ฅด๋ฉฐ ์ฆ๊ฑฐ์šด ์—์ด์ „ํŠธ ์›Œํฌํ”Œ๋กœ๋กœ ์œ ์šฉํ•œ ์†Œํ”„ํŠธ์›จ์–ด๋ฅผ ๋งŒ๋“œ์„ธ์š”.

HagiCode ๋ผ์ดํŠธ ํ…Œ๋งˆ ๋ฉ”์ธ ํ™”๋ฉด
  • Smart๊ตฌ์กฐํ™”๋œ ์›Œํฌํ”Œ๋กœ๋Š” ์˜๋„๋ฅผ ์•„์ด๋””์–ด๋ถ€ํ„ฐ ๋ฐฐํฌ๊นŒ์ง€ ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ๊ฒฝ๋กœ๋กœ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.
  • Efficient๋‹ค์ค‘ ์—์ด์ „ํŠธ ์›Œํฌํ”Œ๋กœ๋กœ ์กฐ์‚ฌ, ๊ตฌํ˜„, ๊ฒ€ํ† ๋ฅผ ๋ณ‘๋ ฌ๋กœ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  • FunHero Dungeon์€ ๊ธด ์ฝ”๋”ฉ ์„ธ์…˜์„ ์‹œ๊ฐ์ ์ด๊ณ  ํ˜‘์—…์ ์ธ ๊ฒฝํ—˜์œผ๋กœ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
HagiCode ๋ฐฉ๋ฌธ