From e007fc11aacf72e3e1943d796b366706e59105f1 Mon Sep 17 00:00:00 2001 From: diegosouzapw Date: Thu, 14 May 2026 21:39:57 -0300 Subject: [PATCH] docs(skills): publish 10 SKILL.md manifests for external AI agents MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds /skills/omniroute*/SKILL.md following the Anthropic skill manifest spec (frontmatter name/description + self-contained body): chat, image, tts, stt, embeddings, web-search, web-fetch, mcp, a2a + entry point. External agents (Claude Desktop, ChatGPT, Cursor, Cline) can fetch one raw GitHub URL to learn how to call OmniRoute — zero-friction onboarding. OmniRoute-specific differentiators (mcp + a2a skills) extend the 9router pattern with 2 extra manifests not present in the reference. Adds structural lint test (tests/unit/docs/skillManifestsLint.test.ts) enforcing frontmatter, env-var references, and trigger-phrase quality. Adds "AI Agent Skills" section to README.md root. Ref: 9router/skills/ pattern (adapted). --- README.md | 13 ++++ skills/README.md | 42 +++++++++++++ skills/omniroute-a2a/SKILL.md | 71 ++++++++++++++++++++++ skills/omniroute-chat/SKILL.md | 68 +++++++++++++++++++++ skills/omniroute-embeddings/SKILL.md | 45 ++++++++++++++ skills/omniroute-image/SKILL.md | 45 ++++++++++++++ skills/omniroute-mcp/SKILL.md | 71 ++++++++++++++++++++++ skills/omniroute-stt/SKILL.md | 42 +++++++++++++ skills/omniroute-tts/SKILL.md | 45 ++++++++++++++ skills/omniroute-web-fetch/SKILL.md | 47 ++++++++++++++ skills/omniroute-web-search/SKILL.md | 49 +++++++++++++++ skills/omniroute/SKILL.md | 63 +++++++++++++++++++ tests/unit/docs/skillManifestsLint.test.ts | 43 +++++++++++++ 13 files changed, 644 insertions(+) create mode 100644 skills/README.md create mode 100644 skills/omniroute-a2a/SKILL.md create mode 100644 skills/omniroute-chat/SKILL.md create mode 100644 skills/omniroute-embeddings/SKILL.md create mode 100644 skills/omniroute-image/SKILL.md create mode 100644 skills/omniroute-mcp/SKILL.md create mode 100644 skills/omniroute-stt/SKILL.md create mode 100644 skills/omniroute-tts/SKILL.md create mode 100644 skills/omniroute-web-fetch/SKILL.md create mode 100644 skills/omniroute-web-search/SKILL.md create mode 100644 skills/omniroute/SKILL.md create mode 100644 tests/unit/docs/skillManifestsLint.test.ts diff --git a/README.md b/README.md index e4b62a38a3..173d0a7a6c 100644 --- a/README.md +++ b/README.md @@ -460,6 +460,19 @@ Alibaba · Amazon Q · AssemblyAI · Baidu Qianfan · Baseten · Black Forest La --- +## 🤖 AI Agent Skills + +Drop-in markdown manifests that let any AI agent consume OmniRoute via one fetch. + +Tell your agent (Claude Desktop, ChatGPT, Cursor, Cline, etc.): + +> "Fetch this URL and use OmniRoute according to its instructions: +> `https://raw.githubusercontent.com/NomenAK/OmniRoute/main/skills/omniroute/SKILL.md`" + +10 skills available — see [skills/README.md](./skills/README.md). + +--- + ## 🔄 How It Works ``` diff --git a/skills/README.md b/skills/README.md new file mode 100644 index 0000000000..2ebb4272e9 --- /dev/null +++ b/skills/README.md @@ -0,0 +1,42 @@ +# OmniRoute AI Agent Skills + +Drop-in skills that let any AI agent (Claude Desktop, ChatGPT, Cursor, Cline, Continue, etc.) +consume OmniRoute via OpenAI-compatible REST in one fetch. + +## How agents use these + +``` +User to agent: "Use OmniRoute for code-gen. Fetch this URL and follow it: +https://raw.githubusercontent.com/NomenAK/OmniRoute/main/skills/omniroute/SKILL.md" +``` + +The agent retrieves the manifest, sees the setup + endpoints, and routes calls +through `$OMNIROUTE_URL/v1/...` with `Authorization: Bearer $OMNIROUTE_KEY`. + +## Skills index + +| Capability | Manifest | +| ------------------------ | -------------------------------------------------------------- | +| Entry point + setup | [omniroute/SKILL.md](omniroute/SKILL.md) | +| Chat / code-gen | [omniroute-chat/SKILL.md](omniroute-chat/SKILL.md) | +| Image generation | [omniroute-image/SKILL.md](omniroute-image/SKILL.md) | +| Text-to-speech | [omniroute-tts/SKILL.md](omniroute-tts/SKILL.md) | +| Speech-to-text | [omniroute-stt/SKILL.md](omniroute-stt/SKILL.md) | +| Embeddings | [omniroute-embeddings/SKILL.md](omniroute-embeddings/SKILL.md) | +| Web search | [omniroute-web-search/SKILL.md](omniroute-web-search/SKILL.md) | +| Web fetch (URL→markdown) | [omniroute-web-fetch/SKILL.md](omniroute-web-fetch/SKILL.md) | +| MCP server | [omniroute-mcp/SKILL.md](omniroute-mcp/SKILL.md) | +| A2A protocol | [omniroute-a2a/SKILL.md](omniroute-a2a/SKILL.md) | + +## Format + +Each `SKILL.md` follows the Anthropic skill manifest spec with YAML frontmatter +(`name`, `description`) and a self-contained markdown body: setup, endpoints, +examples, and error codes. Assume the reader is an agent with no prior context. + +## Differences from 9router skills + +OmniRoute extends the 9router pattern with two additional skills: + +- `omniroute-mcp` — exposes 37 MCP tools (memory, skills, providers, routing) over SSE/stdio/HTTP +- `omniroute-a2a` — exposes 5 A2A skills (smart-routing, quota, discovery, cost, health) diff --git a/skills/omniroute-a2a/SKILL.md b/skills/omniroute-a2a/SKILL.md new file mode 100644 index 0000000000..6c984810d5 --- /dev/null +++ b/skills/omniroute-a2a/SKILL.md @@ -0,0 +1,71 @@ +--- +name: omniroute-a2a +description: OmniRoute exposes an A2A (Agent-to-Agent) JSON-RPC 2.0 server with 5 skills (smart-routing, quota-management, provider-discovery, cost-analysis, health-report). Use when the user wants OmniRoute to act as an agent peer in an A2A network or multi-agent pipeline. +--- + +# OmniRoute — A2A Protocol + +Requires `OMNIROUTE_URL` and `OMNIROUTE_KEY`. See [entry-point SKILL](https://raw.githubusercontent.com/NomenAK/OmniRoute/main/skills/omniroute/SKILL.md) for setup. + +OmniRoute publishes an Agent Card at `/.well-known/agent.json` and accepts +JSON-RPC 2.0 calls at `/a2a`. + +## Discovery + +```bash +curl $OMNIROUTE_URL/.well-known/agent.json +``` + +Returns Agent Card with skills, endpoints, auth scheme. + +## Available skills + +| Skill | Purpose | +| -------------------- | ----------------------------------------------------------------------------------- | +| `smart-routing` | Given a prompt, recommends best provider/model combo | +| `quota-management` | Reports quota balance for given provider/account | +| `provider-discovery` | Lists providers matching capability filters (vision, JSON mode, tools, max-context) | +| `cost-analysis` | Estimates cost for a given request shape | +| `health-report` | Returns system health (circuit states, latencies, errors) | + +## Call example (JSON-RPC 2.0) + +```bash +curl -X POST $OMNIROUTE_URL/a2a \ + -H "Authorization: Bearer $OMNIROUTE_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "jsonrpc": "2.0", + "method": "tasks/send", + "params": { + "skillId": "smart-routing", + "input": { "prompt_length": 4000, "tools": true, "vision": false } + }, + "id": 1 + }' +``` + +## Response shape + +```json +{ + "jsonrpc": "2.0", + "result": { + "taskId": "...", + "status": "completed", + "output": { "recommended_combo": "...", "reasoning": "..." } + }, + "id": 1 +} +``` + +## Errors + +- `-32600` → invalid request (bad JSON-RPC envelope) +- `-32601` → method not found (check `method` field) +- `-32602` → invalid params (check `skillId` against Agent Card) +- `401` → missing/invalid `OMNIROUTE_KEY` + +## Reference + +Full docs: https://github.com/NomenAK/OmniRoute/blob/main/docs/frameworks/A2A-SERVER.md diff --git a/skills/omniroute-chat/SKILL.md b/skills/omniroute-chat/SKILL.md new file mode 100644 index 0000000000..c2ab1655cd --- /dev/null +++ b/skills/omniroute-chat/SKILL.md @@ -0,0 +1,68 @@ +--- +name: omniroute-chat +description: Chat / code generation via OmniRoute using OpenAI /v1/chat/completions or Anthropic /v1/messages format with SSE streaming, auto-fallback combos, RTK token saver, and 207+ providers. Use when the user wants to ask an LLM, generate code, summarize text, or run prompts through OmniRoute. +--- + +# OmniRoute — Chat + +Requires `OMNIROUTE_URL` and `OMNIROUTE_KEY`. See [entry-point SKILL](https://raw.githubusercontent.com/NomenAK/OmniRoute/main/skills/omniroute/SKILL.md) for setup. + +## Endpoints + +- `POST $OMNIROUTE_URL/v1/chat/completions` — OpenAI format +- `POST $OMNIROUTE_URL/v1/messages` — Anthropic Messages format +- `POST $OMNIROUTE_URL/v1/responses` — OpenAI Responses API + +## Discover + +```bash +curl $OMNIROUTE_URL/v1/models | jq '.data[].id' +``` + +Combos (e.g. `auto`, `cost-optimized`, `subscription`) auto-fallback through multiple providers. + +## OpenAI format example + +```bash +curl -X POST $OMNIROUTE_URL/v1/chat/completions \ + -H "Authorization: Bearer $OMNIROUTE_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "model": "claude-opus-4-7", + "messages": [{"role": "user", "content": "Refactor this function"}], + "stream": true + }' +``` + +## Anthropic format example + +```bash +curl -X POST $OMNIROUTE_URL/v1/messages \ + -H "Authorization: Bearer $OMNIROUTE_KEY" \ + -H "anthropic-version: 2023-06-01" \ + -H "Content-Type: application/json" \ + -d '{ + "model": "claude-opus-4-7", + "max_tokens": 4096, + "messages": [{"role": "user", "content": "Hi"}] + }' +``` + +## Tool use + +Supports OpenAI `tools` array and Anthropic `tools` block. Tool results +auto-compressed via RTK (47 filters: git-diff, grep, test-jest, terraform-plan, +docker-logs, etc.) — 20-40% token savings. Disable per-request with +`X-Omniroute-Rtk: off` header. + +## Reasoning / thinking + +Anthropic extended thinking and OpenAI Responses reasoning blocks are forwarded +verbatim. Cached automatically via reasoning cache. + +## Errors + +- `401` → invalid API key +- `400 invalid_model` → model not in registry; check `/v1/models` +- `503 circuit_open` → provider circuit breaker tripped; retry later or use combo +- `429 rate_limited` → honor `Retry-After`; consider using a combo for auto-fallback diff --git a/skills/omniroute-embeddings/SKILL.md b/skills/omniroute-embeddings/SKILL.md new file mode 100644 index 0000000000..f0e5c805bc --- /dev/null +++ b/skills/omniroute-embeddings/SKILL.md @@ -0,0 +1,45 @@ +--- +name: omniroute-embeddings +description: Embeddings via OmniRoute using OpenAI /v1/embeddings format with auto-fallback across text-embedding-3-large, Voyage, Cohere, Gemini embeddings, Jina. Use when the user needs vector embeddings for RAG, similarity search, or clustering. +--- + +# OmniRoute — Embeddings + +Requires `OMNIROUTE_URL` and `OMNIROUTE_KEY`. See [entry-point SKILL](https://raw.githubusercontent.com/NomenAK/OmniRoute/main/skills/omniroute/SKILL.md) for setup. + +## Endpoint + +- `POST $OMNIROUTE_URL/v1/embeddings` + +## Discover + +```bash +curl $OMNIROUTE_URL/v1/models/embedding | jq '.data[]' +``` + +Each entry: `{ id, owned_by, dimensions, max_input_tokens }`. + +## Example + +```bash +curl -X POST $OMNIROUTE_URL/v1/embeddings \ + -H "Authorization: Bearer $OMNIROUTE_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "model": "text-embedding-3-large", + "input": ["first text", "second text"], + "encoding_format": "float" + }' +``` + +Response: `{ data:[{ embedding:[...], index }], usage:{ prompt_tokens, total_tokens } }` + +## Batch input + +`input` accepts a string or array of strings (up to provider batch limit, typically 2048 items). + +## Errors + +- `400 input_too_long` → input exceeds `max_input_tokens` for this model +- `400 invalid_encoding_format` → use `float` or `base64` +- `503` → provider unavailable; try another model in `/v1/models/embedding` diff --git a/skills/omniroute-image/SKILL.md b/skills/omniroute-image/SKILL.md new file mode 100644 index 0000000000..ab94c316e3 --- /dev/null +++ b/skills/omniroute-image/SKILL.md @@ -0,0 +1,45 @@ +--- +name: omniroute-image +description: Image generation via OmniRoute using OpenAI /v1/images/generations format with auto-fallback across DALL-E, Stable Diffusion, Flux, Imagen providers. Use when the user wants to generate, edit, or vary images. +--- + +# OmniRoute — Image Generation + +Requires `OMNIROUTE_URL` and `OMNIROUTE_KEY`. See [entry-point SKILL](https://raw.githubusercontent.com/NomenAK/OmniRoute/main/skills/omniroute/SKILL.md) for setup. + +## Endpoints + +- `POST $OMNIROUTE_URL/v1/images/generations` — Text-to-image +- `POST $OMNIROUTE_URL/v1/images/edits` — Image edit (mask) +- `POST $OMNIROUTE_URL/v1/images/variations` — Variations + +## Discover + +```bash +curl $OMNIROUTE_URL/v1/models/image | jq '.data[]' +``` + +Returns `{ id, owned_by, sizes:[...], capabilities:[...] }` per model. + +## Generate example + +```bash +curl -X POST $OMNIROUTE_URL/v1/images/generations \ + -H "Authorization: Bearer $OMNIROUTE_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "model": "dall-e-3", + "prompt": "a red bicycle on a wet street, photoreal", + "n": 1, + "size": "1024x1024", + "response_format": "b64_json" + }' +``` + +Response: `{ created, data: [{ url? or b64_json, revised_prompt }] }` + +## Errors + +- `400 invalid_size` → not supported by this model; check `/v1/models/image` +- `400 content_policy_violation` → blocked by provider safety +- `503` → provider unavailable; try another model in `/v1/models/image` diff --git a/skills/omniroute-mcp/SKILL.md b/skills/omniroute-mcp/SKILL.md new file mode 100644 index 0000000000..bd21a9c1d6 --- /dev/null +++ b/skills/omniroute-mcp/SKILL.md @@ -0,0 +1,71 @@ +--- +name: omniroute-mcp +description: OmniRoute exposes a built-in MCP (Model Context Protocol) server with 37 tools (chat, embeddings, memory CRUD, skills, providers, routing, audit) over SSE/stdio/HTTP transports. Use when the user wants to add OmniRoute as an MCP server in Claude Desktop, Cursor, Cline, or any MCP-compatible client. +--- + +# OmniRoute — MCP Server + +Requires `OMNIROUTE_URL` and `OMNIROUTE_KEY`. See [entry-point SKILL](https://raw.githubusercontent.com/NomenAK/OmniRoute/main/skills/omniroute/SKILL.md) for setup. + +## Transports + +- **stdio** — local IPC, for Claude Desktop / VS Code extensions +- **SSE** — `GET $OMNIROUTE_URL/api/mcp/sse` +- **Streamable HTTP** — `POST $OMNIROUTE_URL/api/mcp/stream` + +## Claude Desktop config + +Add to `~/Library/Application Support/Claude/claude_desktop_config.json`: + +```json +{ + "mcpServers": { + "omniroute": { + "command": "npx", + "args": ["-y", "omniroute", "--mcp"], + "env": { "OMNIROUTE_KEY": "sk-..." } + } + } +} +``` + +## Cursor / VS Code config + +```json +{ + "mcp": { + "servers": { + "omniroute": { + "url": "http://localhost:20128/api/mcp/sse", + "headers": { "Authorization": "Bearer sk-..." } + } + } + } +} +``` + +## Available tools (37 total) + +| Scope | Tools | +| --------- | -------------------------------------------------------------------------------------------------- | +| health | `omniroute_get_health` | +| combos | `omniroute_list_combos`, `omniroute_get_combo_metrics`, `omniroute_switch_combo` | +| routing | `omniroute_simulate_route`, `omniroute_best_combo_for_task`, `omniroute_explain_route` | +| providers | `omniroute_get_provider_metrics`, `omniroute_check_quota`, `omniroute_route_request` | +| budget | `omniroute_set_budget_guard`, `omniroute_set_routing_strategy`, `omniroute_set_resilience_profile` | +| testing | `omniroute_test_combo` | +| memory | `memory_add`, `memory_search`, `memory_delete` | +| skills | `skill_invoke`, `skill_list`, `skill_describe`, `skill_register` | +| cache | `omniroute_cache_stats`, `omniroute_cache_flush` | +| admin | `omniroute_db_health_check`, `omniroute_sync_pricing`, `omniroute_get_session_snapshot` | + +Full list: `GET $OMNIROUTE_URL/api/mcp/tools` + +## Scopes + +Tools are grouped into 13 scopes (chat-only, memory-readonly, full-admin, etc.). +Pass scope name as `--scope` arg or via `X-Omniroute-Scope` header. + +## Reference + +Full docs: https://github.com/NomenAK/OmniRoute/blob/main/docs/frameworks/MCP-SERVER.md diff --git a/skills/omniroute-stt/SKILL.md b/skills/omniroute-stt/SKILL.md new file mode 100644 index 0000000000..b8b7a32376 --- /dev/null +++ b/skills/omniroute-stt/SKILL.md @@ -0,0 +1,42 @@ +--- +name: omniroute-stt +description: Speech-to-text via OmniRoute using OpenAI /v1/audio/transcriptions format with auto-fallback across Whisper, AssemblyAI, Deepgram, Azure STT. Use when the user wants transcription of audio files or real-time speech recognition. +--- + +# OmniRoute — Speech-to-Text + +Requires `OMNIROUTE_URL` and `OMNIROUTE_KEY`. See [entry-point SKILL](https://raw.githubusercontent.com/NomenAK/OmniRoute/main/skills/omniroute/SKILL.md) for setup. + +## Endpoints + +- `POST $OMNIROUTE_URL/v1/audio/transcriptions` — multipart upload, returns text +- `POST $OMNIROUTE_URL/v1/audio/translations` — transcribe + translate to English + +## Discover + +```bash +curl $OMNIROUTE_URL/v1/models/stt | jq '.data[]' +``` + +## Example + +```bash +curl -X POST $OMNIROUTE_URL/v1/audio/transcriptions \ + -H "Authorization: Bearer $OMNIROUTE_KEY" \ + -F "file=@audio.mp3" \ + -F "model=whisper-1" \ + -F "response_format=verbose_json" +``` + +Response: `{ text, language, duration, segments?:[{ start, end, text }] }` + +## Supported formats + +Audio: `mp3`, `mp4`, `mpeg`, `mpga`, `m4a`, `wav`, `webm`. +Response formats: `json`, `text`, `srt`, `verbose_json`, `vtt`. + +## Errors + +- `400 invalid_file_format` → unsupported audio format +- `400 file_too_large` → exceeds provider limit (usually 25MB) +- `503` → provider unavailable; try another model in `/v1/models/stt` diff --git a/skills/omniroute-tts/SKILL.md b/skills/omniroute-tts/SKILL.md new file mode 100644 index 0000000000..930f5c18fd --- /dev/null +++ b/skills/omniroute-tts/SKILL.md @@ -0,0 +1,45 @@ +--- +name: omniroute-tts +description: Text-to-speech via OmniRoute using OpenAI /v1/audio/speech format with auto-fallback across OpenAI TTS, ElevenLabs, Azure Neural, Google Cloud TTS. Use when the user wants spoken audio output from text. +--- + +# OmniRoute — Text-to-Speech + +Requires `OMNIROUTE_URL` and `OMNIROUTE_KEY`. See [entry-point SKILL](https://raw.githubusercontent.com/NomenAK/OmniRoute/main/skills/omniroute/SKILL.md) for setup. + +## Endpoint + +- `POST $OMNIROUTE_URL/v1/audio/speech` — returns binary audio (mp3/opus/wav/flac) + +## Discover + +```bash +curl $OMNIROUTE_URL/v1/models/tts | jq '.data[]' +``` + +Each entry includes `voices:[...]` for the available voice names per provider. + +## Example + +```bash +curl -X POST $OMNIROUTE_URL/v1/audio/speech \ + -H "Authorization: Bearer $OMNIROUTE_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "model": "tts-1", + "input": "Hello from OmniRoute.", + "voice": "alloy", + "response_format": "mp3" + }' --output speech.mp3 +``` + +## Voices + +Voice names vary by provider. Check `/v1/models/tts` — each entry has `voices:[...]`. +Common OpenAI voices: `alloy`, `echo`, `fable`, `onyx`, `nova`, `shimmer`. + +## Errors + +- `400 invalid_voice` → voice not supported by this model +- `400 input_too_long` → input exceeds model character limit +- `503` → provider unavailable; try another model in `/v1/models/tts` diff --git a/skills/omniroute-web-fetch/SKILL.md b/skills/omniroute-web-fetch/SKILL.md new file mode 100644 index 0000000000..e0f7f9dda1 --- /dev/null +++ b/skills/omniroute-web-fetch/SKILL.md @@ -0,0 +1,47 @@ +--- +name: omniroute-web-fetch +description: Fetch a URL and convert to clean markdown via OmniRoute proxying Jina Reader, Firecrawl, raw HTML strip. Use when the user wants to ingest a webpage as markdown for context in an LLM conversation. +--- + +# OmniRoute — Web Fetch + +Requires `OMNIROUTE_URL` and `OMNIROUTE_KEY`. See [entry-point SKILL](https://raw.githubusercontent.com/NomenAK/OmniRoute/main/skills/omniroute/SKILL.md) for setup. + +## Endpoint + +- `POST $OMNIROUTE_URL/v1/web/fetch` + +## Discover + +```bash +curl $OMNIROUTE_URL/v1/models/web | jq '.data[] | select(.kind == "webFetch")' +``` + +## Example + +```bash +curl -X POST $OMNIROUTE_URL/v1/web/fetch \ + -H "Authorization: Bearer $OMNIROUTE_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "model": "jina/reader", + "url": "https://anthropic.com", + "format": "markdown" + }' +``` + +Response: `{ url, title, markdown, links?:[...], images?:[...] }` + +## Parameters + +| Field | Type | Description | +| -------- | ------ | ----------------------------------------------------------------------- | +| `model` | string | Provider from `/v1/models/web` (e.g. `jina/reader`, `firecrawl/scrape`) | +| `url` | string | URL to fetch | +| `format` | string | `markdown` (default), `html`, `text` | + +## Errors + +- `400 invalid_url` → URL must be http/https +- `403 blocked` → provider blocked by target site; try a different model +- `503` → provider unavailable; try another model in `/v1/models/web` diff --git a/skills/omniroute-web-search/SKILL.md b/skills/omniroute-web-search/SKILL.md new file mode 100644 index 0000000000..a6cf173afc --- /dev/null +++ b/skills/omniroute-web-search/SKILL.md @@ -0,0 +1,49 @@ +--- +name: omniroute-web-search +description: Web search via OmniRoute proxying Tavily, Brave Search, SerpAPI, Exa with auto-fallback. Use when the user wants live web search results, current news, or facts that may be beyond the LLM training cutoff. +--- + +# OmniRoute — Web Search + +Requires `OMNIROUTE_URL` and `OMNIROUTE_KEY`. See [entry-point SKILL](https://raw.githubusercontent.com/NomenAK/OmniRoute/main/skills/omniroute/SKILL.md) for setup. + +## Endpoint + +- `POST $OMNIROUTE_URL/v1/web/search` — unified search format + +## Discover + +```bash +curl $OMNIROUTE_URL/v1/models/web | jq '.data[] | select(.kind == "webSearch")' +``` + +## Example + +```bash +curl -X POST $OMNIROUTE_URL/v1/web/search \ + -H "Authorization: Bearer $OMNIROUTE_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "model": "tavily/search", + "query": "OmniRoute github latest release", + "max_results": 5, + "include_answer": true + }' +``` + +Response: `{ answer?, results:[{ url, title, content, score }] }` + +## Parameters + +| Field | Type | Description | +| ---------------- | ------- | ------------------------------------ | +| `model` | string | Provider model from `/v1/models/web` | +| `query` | string | Search query | +| `max_results` | number | Max results (default: 5) | +| `include_answer` | boolean | Include AI-synthesized answer | +| `search_depth` | string | `basic` or `advanced` (Tavily) | + +## Errors + +- `400 query_too_long` → shorten the search query +- `503` → provider unavailable; try another model in `/v1/models/web` diff --git a/skills/omniroute/SKILL.md b/skills/omniroute/SKILL.md new file mode 100644 index 0000000000..749bfb892c --- /dev/null +++ b/skills/omniroute/SKILL.md @@ -0,0 +1,63 @@ +--- +name: omniroute +description: Entry point for OmniRoute — local/remote AI gateway with OpenAI-compatible REST for chat, image, TTS, STT, embeddings, web search, web fetch, MCP, A2A. Use when the user mentions OmniRoute, OMNIROUTE_URL, or wants AI without writing provider boilerplate. This skill covers setup + indexes capability skills; fetch the relevant capability SKILL.md from the URLs below when needed. +--- + +# OmniRoute + +Local/remote AI gateway exposing OpenAI-compatible REST. One key, 207+ providers, +auto-fallback, RTK token saver, MCP server, A2A agents. + +## Setup + +```bash +export OMNIROUTE_URL="http://localhost:20128" # or VPS / tunnel URL +export OMNIROUTE_KEY="sk-..." # from Dashboard → API Keys +``` + +All requests: `${OMNIROUTE_URL}/v1/...` with `Authorization: Bearer ${OMNIROUTE_KEY}`. + +Verify: `curl $OMNIROUTE_URL/api/health` → `{"ok":true}` + +## Discover models + +```bash +curl $OMNIROUTE_URL/v1/models # chat/LLM (default) +curl $OMNIROUTE_URL/v1/models/image # image-gen +curl $OMNIROUTE_URL/v1/models/tts # text-to-speech +curl $OMNIROUTE_URL/v1/models/embedding # embeddings +curl $OMNIROUTE_URL/v1/models/web # web search + fetch +curl $OMNIROUTE_URL/v1/models/stt # speech-to-text +``` + +Use `data[].id` as `model` field in requests. Combos appear with `owned_by:"combo"`. + +## Capability skills + +| Capability | Raw URL | +| ---------------- | --------------------------------------------------------------------------------------------- | +| Chat / code-gen | https://raw.githubusercontent.com/NomenAK/OmniRoute/main/skills/omniroute-chat/SKILL.md | +| Image generation | https://raw.githubusercontent.com/NomenAK/OmniRoute/main/skills/omniroute-image/SKILL.md | +| Text-to-speech | https://raw.githubusercontent.com/NomenAK/OmniRoute/main/skills/omniroute-tts/SKILL.md | +| Speech-to-text | https://raw.githubusercontent.com/NomenAK/OmniRoute/main/skills/omniroute-stt/SKILL.md | +| Embeddings | https://raw.githubusercontent.com/NomenAK/OmniRoute/main/skills/omniroute-embeddings/SKILL.md | +| Web search | https://raw.githubusercontent.com/NomenAK/OmniRoute/main/skills/omniroute-web-search/SKILL.md | +| Web fetch | https://raw.githubusercontent.com/NomenAK/OmniRoute/main/skills/omniroute-web-fetch/SKILL.md | +| MCP server | https://raw.githubusercontent.com/NomenAK/OmniRoute/main/skills/omniroute-mcp/SKILL.md | +| A2A protocol | https://raw.githubusercontent.com/NomenAK/OmniRoute/main/skills/omniroute-a2a/SKILL.md | + +## Errors + +- `401` → set/refresh `OMNIROUTE_KEY` (Dashboard → API Keys) +- `400 Invalid model format` → check `model` exists in `/v1/models/` +- `503 Provider circuit open` → upstream provider down; retry after `Retry-After` seconds +- `429` → rate limited; honor `Retry-After` + +## Differentiators vs OpenAI direct + +- **Auto-fallback** combos (14 strategies): never stop coding even if a provider rate-limits +- **RTK token saver**: tool_result compressed via 47 specialized filters (git-diff, test-jest, terraform-plan, docker-logs…) — 20-40% token reduction +- **Caveman mode**: optional terse system prompt injection (LITE/FULL/ULTRA) — 15-25% completion reduction +- **MCP + A2A** servers built-in (this is the only AI router that exposes both protocols) +- **Memory** with FTS5 + Qdrant for persistent agent context +- **Guardrails** for PII masking, prompt injection detection, vision policies diff --git a/tests/unit/docs/skillManifestsLint.test.ts b/tests/unit/docs/skillManifestsLint.test.ts new file mode 100644 index 0000000000..c421fc21c6 --- /dev/null +++ b/tests/unit/docs/skillManifestsLint.test.ts @@ -0,0 +1,43 @@ +import { test } from "node:test"; +import assert from "node:assert/strict"; +import { readdir, readFile } from "node:fs/promises"; +import { join } from "node:path"; + +const SKILLS_DIR = join(process.cwd(), "skills"); +const REQUIRED_FRONTMATTER = ["name:", "description:"]; + +async function listSkillDirs(): Promise { + const entries = await readdir(SKILLS_DIR, { withFileTypes: true }); + return entries + .filter((e) => e.isDirectory() && e.name.startsWith("omniroute")) + .map((e) => e.name); +} + +test("each skill dir has SKILL.md with frontmatter", async () => { + const dirs = await listSkillDirs(); + assert.ok(dirs.length >= 9, `Expected ≥9 skill dirs, got ${dirs.length}`); + for (const dir of dirs) { + const path = join(SKILLS_DIR, dir, "SKILL.md"); + const content = await readFile(path, "utf-8"); + assert.ok(content.startsWith("---\n"), `${dir}: missing opening frontmatter`); + for (const key of REQUIRED_FRONTMATTER) { + assert.ok(content.includes(key), `${dir}: missing frontmatter key ${key}`); + } + assert.ok( + content.includes("$OMNIROUTE_URL") || content.includes("OMNIROUTE_KEY"), + `${dir}: missing env-var references` + ); + } +}); + +test("description field is meaningful (≥50 chars, has 'Use when')", async () => { + const dirs = await listSkillDirs(); + for (const dir of dirs) { + const content = await readFile(join(SKILLS_DIR, dir, "SKILL.md"), "utf-8"); + const match = content.match(/^description:\s*(.+?)$/m); + assert.ok(match, `${dir}: no description field`); + const desc = match![1]; + assert.ok(desc.length >= 50, `${dir}: description too short (${desc.length})`); + assert.ok(/use when/i.test(desc), `${dir}: description missing "Use when" trigger phrase`); + } +});