{"_id":"@dtmirizzi/pi-openrouter-multimodal","_rev":"5-e712aa6b95337abb333e786f68169381","name":"@dtmirizzi/pi-openrouter-multimodal","dist-tags":{"latest":"1.7.1"},"versions":{"1.5.2":{"name":"@dtmirizzi/pi-openrouter-multimodal","version":"1.5.2","keywords":["pi-package"],"author":{"name":"dtmirizzi"},"license":"MIT","_id":"@dtmirizzi/pi-openrouter-multimodal@1.5.2","maintainers":[{"name":"dtizzal","email":"dtmirizzi@gmail.com"}],"homepage":"https://github.com/dtmirizzi/pi-openrouter-multimodal#readme","bugs":{"url":"https://github.com/dtmirizzi/pi-openrouter-multimodal/issues"},"pi":{"extensions":["./index.ts"]},"dist":{"shasum":"6d561e4c1d2a3dd02ecdee07a5ee91134e09e999","tarball":"https://registry.npmjs.org/@dtmirizzi/pi-openrouter-multimodal/-/pi-openrouter-multimodal-1.5.2.tgz","fileCount":6,"integrity":"sha512-jB451/WyAt0NUHjPCG9e95w2YNDMJfZArUVtt17CYtDijQ4YL47BheKe0Ica8DsDJ0RC4AHq3jLDqLCFJOXKkw==","signatures":[{"sig":"MEUCIQC94qn0Aqgw7dxhRMr8HFPwBrwY1NisPx3k9GIWPfvQHQIgZ23ep+IETGRO4acJh9qjVxXNwFWoXun3/atbaITZY9Y=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":70084},"type":"module","engines":{"node":">=18"},"gitHead":"8f22b7b66fd16a322eceb12fadda08d12072675c","release":{"plugins":["@semantic-release/commit-analyzer","@semantic-release/release-notes-generator","@semantic-release/changelog","@semantic-release/npm",["@semantic-release/git",{"assets":["package.json","CHANGELOG.md"],"message":"chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"}],"@semantic-release/github"],"branches":["main"]},"scripts":{"fmt":"biome format --write .","lint":"biome check --write .","test":"vitest run","check":"biome check --write .","check:ci":"biome ci .","fmt:check":"biome format .","test:unit":"vitest run test/unit","lint:check":"biome check .","semantic-release":"semantic-release","test:integration":"vitest run test/integration"},"_npmUser":{"name":"dtizzal","email":"dtmirizzi@gmail.com"},"repository":{"url":"git+https://github.com/dtmirizzi/pi-openrouter-multimodal.git","type":"git"},"_npmVersion":"10.9.8","description":"OpenRouter multimodal tools for Pi — search, fetch, image gen, vision, video, PDF, TTS, STT","directories":{},"_nodeVersion":"22.22.3","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.7","@biomejs/biome":"^2.4.16","semantic-release":"^24.0.0","@semantic-release/git":"^10.0.1","@semantic-release/npm":"^12.0.1","@semantic-release/github":"^11.0.1","@semantic-release/changelog":"^6.0.3"},"peerDependencies":{"typebox":"*","@earendil-works/pi-ai":"*","@earendil-works/pi-tui":"*","@earendil-works/pi-coding-agent":"*"},"_npmOperationalInternal":{"tmp":"tmp/pi-openrouter-multimodal_1.5.2_1780114621063_0.9446877320462566","host":"s3://npm-registry-packages-npm-production"}},"1.5.3":{"name":"@dtmirizzi/pi-openrouter-multimodal","version":"1.5.3","keywords":["pi-package"],"author":{"name":"dtmirizzi"},"license":"MIT","_id":"@dtmirizzi/pi-openrouter-multimodal@1.5.3","maintainers":[{"name":"dtizzal","email":"dtmirizzi@gmail.com"}],"homepage":"https://github.com/dtmirizzi/pi-openrouter-multimodal#readme","bugs":{"url":"https://github.com/dtmirizzi/pi-openrouter-multimodal/issues"},"pi":{"extensions":["./index.ts"]},"dist":{"shasum":"1f42f13067d290c0ac1521b22a008623174c2391","tarball":"https://registry.npmjs.org/@dtmirizzi/pi-openrouter-multimodal/-/pi-openrouter-multimodal-1.5.3.tgz","fileCount":6,"integrity":"sha512-DgJZydXqdKVIKocFDW0dYp04uZi9kKFXskhTNREDOPvGwiRvvL4e6fPYjkLacw8fkeysZTGbSso3Mfz8Bmas7g==","signatures":[{"sig":"MEUCIF1uUqu9A32kOULLu74uA+R1md6SUzXL6mC3/jFQWJWkAiEAoksEVoH1GGNuj2f8y/seXleUvZntWmRsZXcLuhkbT5A=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":70481},"type":"module","engines":{"node":">=18"},"gitHead":"9b8d0722b2a89497be894bec4a1038ca6b601888","release":{"plugins":["@semantic-release/commit-analyzer","@semantic-release/release-notes-generator","@semantic-release/changelog","@semantic-release/npm",["@semantic-release/git",{"assets":["package.json","CHANGELOG.md"],"message":"chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"}],"@semantic-release/github"],"branches":["main"]},"scripts":{"fmt":"biome format --write .","lint":"biome check --write .","test":"vitest run","check":"biome check --write .","check:ci":"biome ci .","fmt:check":"biome format .","test:unit":"vitest run test/unit","lint:check":"biome check .","semantic-release":"semantic-release","test:integration":"vitest run test/integration"},"_npmUser":{"name":"dtizzal","email":"dtmirizzi@gmail.com"},"repository":{"url":"git+https://github.com/dtmirizzi/pi-openrouter-multimodal.git","type":"git"},"_npmVersion":"10.9.8","description":"OpenRouter multimodal tools for Pi — search, fetch, image gen, vision, video, PDF, TTS, STT","directories":{},"_nodeVersion":"22.22.3","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.7","@biomejs/biome":"^2.4.16","semantic-release":"^24.0.0","@semantic-release/git":"^10.0.1","@semantic-release/npm":"^12.0.1","@semantic-release/github":"^11.0.1","@semantic-release/changelog":"^6.0.3"},"peerDependencies":{"typebox":"*","@earendil-works/pi-ai":"*","@earendil-works/pi-tui":"*","@earendil-works/pi-coding-agent":"*"},"_npmOperationalInternal":{"tmp":"tmp/pi-openrouter-multimodal_1.5.3_1780115442949_0.984085234292851","host":"s3://npm-registry-packages-npm-production"}},"1.6.0":{"name":"@dtmirizzi/pi-openrouter-multimodal","version":"1.6.0","keywords":["pi-package"],"author":{"name":"dtmirizzi"},"license":"MIT","_id":"@dtmirizzi/pi-openrouter-multimodal@1.6.0","maintainers":[{"name":"dtizzal","email":"dtmirizzi@gmail.com"}],"homepage":"https://github.com/dtmirizzi/pi-openrouter-multimodal#readme","bugs":{"url":"https://github.com/dtmirizzi/pi-openrouter-multimodal/issues"},"pi":{"extensions":["./index.ts"]},"dist":{"shasum":"2739e1f6d6f46d61570ee0d93b4435c206ee28ba","tarball":"https://registry.npmjs.org/@dtmirizzi/pi-openrouter-multimodal/-/pi-openrouter-multimodal-1.6.0.tgz","fileCount":6,"integrity":"sha512-vcL0rr3Vb8FBltERWvq8aWqkPn5RvBt9Pq+1w2XWgvc+HQO04SxxoQ/RoxJJ8n7BB8KGO8i6DQnC6ZzpNijNrw==","signatures":[{"sig":"MEQCID5Qw8QhBeIZHAKxNqTvSEdg8vdwyR3JxLWz4RzjisqfAiBuSQFnoo7wVHMXK4/DERyLWB8OYpGVQxmyMqNvhadrRg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":70736},"type":"module","engines":{"node":">=18"},"gitHead":"74be5f11873db42a81fe2b7641ed27f2dd5132a1","release":{"plugins":["@semantic-release/commit-analyzer","@semantic-release/release-notes-generator","@semantic-release/changelog","@semantic-release/npm",["@semantic-release/git",{"assets":["package.json","CHANGELOG.md"],"message":"chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"}],"@semantic-release/github"],"branches":["main"]},"scripts":{"fmt":"biome format --write .","lint":"biome check --write .","test":"vitest run","check":"biome check --write .","check:ci":"biome ci .","fmt:check":"biome format .","test:unit":"vitest run test/unit","lint:check":"biome check .","semantic-release":"semantic-release","test:integration":"vitest run test/integration"},"_npmUser":{"name":"dtizzal","email":"dtmirizzi@gmail.com"},"repository":{"url":"git+https://github.com/dtmirizzi/pi-openrouter-multimodal.git","type":"git"},"_npmVersion":"10.9.8","description":"OpenRouter multimodal tools for Pi — search, fetch, image gen, vision, video, PDF, TTS, STT","directories":{},"_nodeVersion":"22.22.3","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.7","@biomejs/biome":"^2.4.16","semantic-release":"^24.0.0","@semantic-release/git":"^10.0.1","@semantic-release/npm":"^12.0.1","@semantic-release/github":"^11.0.1","@semantic-release/changelog":"^6.0.3"},"peerDependencies":{"typebox":"*","@earendil-works/pi-ai":"*","@earendil-works/pi-tui":"*","@earendil-works/pi-coding-agent":"*"},"_npmOperationalInternal":{"tmp":"tmp/pi-openrouter-multimodal_1.6.0_1780116176591_0.36375871883884603","host":"s3://npm-registry-packages-npm-production"}},"1.7.0":{"name":"@dtmirizzi/pi-openrouter-multimodal","version":"1.7.0","keywords":["pi-package"],"author":{"name":"dtmirizzi"},"license":"MIT","_id":"@dtmirizzi/pi-openrouter-multimodal@1.7.0","maintainers":[{"name":"dtizzal","email":"dtmirizzi@gmail.com"}],"homepage":"https://github.com/dtmirizzi/pi-openrouter-multimodal#readme","bugs":{"url":"https://github.com/dtmirizzi/pi-openrouter-multimodal/issues"},"pi":{"image":"https://raw.githubusercontent.com/dtmirizzi/pi-openrouter-multimodal/main/assets/icon.svg","extensions":["./index.ts"]},"dist":{"shasum":"bb4b3ba98469de781abb5cd50d21d1aba6e32a87","tarball":"https://registry.npmjs.org/@dtmirizzi/pi-openrouter-multimodal/-/pi-openrouter-multimodal-1.7.0.tgz","fileCount":6,"integrity":"sha512-zsOltYfdnH21isfUyMztjAi6ver5bP2HgtF644fjY4FLsdlYAMtKR2BmeMdJ6CwfNEd4am/x7k9u069YcMvblw==","signatures":[{"sig":"MEUCIQC1lU8tMvCRgcAEMV8wAeTC2wdJEzpA2XW3Jq+9bXt1xgIgDlbA5VE1Bdo633hQ9RJ6DOhmkqU7qk8sGC0th6NuAlM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIHQEavk3xjKjA0CnIscfJG32l6y8bMfRmAB7pXtl4smLAiEA5FCVu9yIcLo6Bx5fqg/QtwLwcDnR/1etQ/7pfjq1GBE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":74871},"type":"module","engines":{"node":">=18"},"gitHead":"ca426bb8ddce35abd97f53307a1d6719f9cdddcb","release":{"plugins":["@semantic-release/commit-analyzer","@semantic-release/release-notes-generator","@semantic-release/changelog","@semantic-release/npm",["@semantic-release/git",{"assets":["package.json","CHANGELOG.md"],"message":"chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"}],"@semantic-release/github"],"branches":["main"]},"scripts":{"fmt":"biome format --write .","lint":"biome check --write .","test":"vitest run","check":"biome check --write .","check:ci":"biome ci .","fmt:check":"biome format .","test:unit":"vitest run test/unit","typecheck":"tsc --noEmit","lint:check":"biome check .","semantic-release":"semantic-release","test:integration":"vitest run test/integration"},"_npmUser":{"name":"dtizzal","email":"dtmirizzi@gmail.com"},"repository":{"url":"git+https://github.com/dtmirizzi/pi-openrouter-multimodal.git","type":"git"},"_npmVersion":"10.9.8","description":"OpenRouter multimodal tools for Pi — search, fetch, image gen, vision, video, PDF, TTS, STT","directories":{},"_nodeVersion":"22.23.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.7","typescript":"^6.0.3","@biomejs/biome":"^2.4.16","semantic-release":"^24.0.0","@semantic-release/git":"^10.0.1","@semantic-release/npm":"^12.0.1","@semantic-release/github":"^11.0.1","@semantic-release/changelog":"^6.0.3"},"peerDependencies":{"typebox":"*","@earendil-works/pi-ai":"*","@earendil-works/pi-tui":"*","@earendil-works/pi-coding-agent":"*"},"_npmOperationalInternal":{"tmp":"tmp/pi-openrouter-multimodal_1.7.0_1790286829344_0.1352090095259828","host":"s3://npm-registry-packages-npm-production"}},"1.7.1":{"pi":{"image":"https://raw.githubusercontent.com/dtmirizzi/pi-openrouter-multimodal/main/assets/logo.png","extensions":["./index.ts"]},"_id":"@dtmirizzi/pi-openrouter-multimodal@1.7.1","bugs":{"url":"https://github.com/dtmirizzi/pi-openrouter-multimodal/issues"},"dist":{"shasum":"f175165b0e490115d611233a1de47ac7375d01c6","tarball":"https://registry.npmjs.org/@dtmirizzi/pi-openrouter-multimodal/-/pi-openrouter-multimodal-1.7.1.tgz","fileCount":6,"integrity":"sha512-m99VyaWBHtRTamzzaQUfQ5YiO1X8ySA3wWY7R3XMXa+7FpaBOK1pwGmspPKU9/YGtKM1VtSjv2IaJ1l/sqtpJg==","signatures":[{"sig":"MEUCIEEZFTusyo/dJ3LDJOslg4o2sBDDegtrkjJaQwdQubCvAiEAkVbFqswf1KYlQ9YsUono/n8O6NS97qZiO+aBxvEEIbI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIFdpyEB8mP/gMkxxXoiBeXQBNBQGyyY+2GjtMJ+wPqeiAiAJCy02pOsJfjBNNiY1XL3E/57wlT8UcmmaZOxO5l7U1Q=="}],"unpackedSize":75146},"name":"@dtmirizzi/pi-openrouter-multimodal","type":"module","author":{"name":"dtmirizzi"},"engines":{"node":">=18"},"gitHead":"ce22708edd69e5428ec8a51e11a086e9f13738d6","license":"MIT","release":{"plugins":["@semantic-release/commit-analyzer","@semantic-release/release-notes-generator","@semantic-release/changelog","@semantic-release/npm",["@semantic-release/git",{"assets":["package.json","CHANGELOG.md"],"message":"chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"}],"@semantic-release/github"],"branches":["main"]},"scripts":{"fmt":"biome format --write .","lint":"biome check --write .","test":"vitest run","check":"biome check --write .","check:ci":"biome ci .","fmt:check":"biome format .","test:unit":"vitest run test/unit","typecheck":"tsc --noEmit","lint:check":"biome check .","semantic-release":"semantic-release","test:integration":"vitest run test/integration"},"version":"1.7.1","_npmUser":{"name":"dtizzal","email":"dtmirizzi@gmail.com"},"homepage":"https://github.com/dtmirizzi/pi-openrouter-multimodal#readme","keywords":["pi-package"],"repository":{"url":"git+https://github.com/dtmirizzi/pi-openrouter-multimodal.git","type":"git"},"_npmVersion":"10.9.8","description":"OpenRouter multimodal tools for Pi — search, fetch, image gen, vision, video, PDF, TTS, STT","directories":{},"maintainers":[{"name":"dtizzal","email":"dtmirizzi@gmail.com"}],"_nodeVersion":"22.23.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.7","typescript":"^6.0.3","@biomejs/biome":"^2.4.16","semantic-release":"^24.0.0","@semantic-release/git":"^10.0.1","@semantic-release/npm":"^12.0.1","@semantic-release/github":"^11.0.1","@semantic-release/changelog":"^6.0.3"},"peerDependencies":{"typebox":"*","@earendil-works/pi-ai":"*","@earendil-works/pi-tui":"*","@earendil-works/pi-coding-agent":"*"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/pi-openrouter-multimodal_1.7.1_1790288223887_0.5461876610729464"}}},"time":{"created":"2026-05-30T04:17:00.877Z","modified":"2026-09-24T22:17:04.158Z","1.5.2":"2026-05-30T04:17:01.231Z","1.5.3":"2026-05-30T04:30:43.091Z","1.6.0":"2026-05-30T04:42:56.728Z","1.7.0":"2026-09-24T21:53:49.423Z","1.7.1":"2026-09-24T22:17:03.976Z"},"bugs":{"url":"https://github.com/dtmirizzi/pi-openrouter-multimodal/issues"},"author":{"name":"dtmirizzi"},"license":"MIT","homepage":"https://github.com/dtmirizzi/pi-openrouter-multimodal#readme","keywords":["pi-package"],"repository":{"url":"git+https://github.com/dtmirizzi/pi-openrouter-multimodal.git","type":"git"},"description":"OpenRouter multimodal tools for Pi — search, fetch, image gen, vision, video, PDF, TTS, STT","maintainers":[{"name":"dtizzal","email":"dtmirizzi@gmail.com"}],"readme":"# @dtmirizzi/pi-openrouter-multimodal\n\n<p align=\"center\">\n  <img src=\"assets/logo.png\" width=\"256\" height=\"256\" alt=\"Logo\">\n</p>\n\nOpenRouter multimodal tool integration for [Pi](https://github.com/earendil-works/pi-coding-agent).\nProvides **8 independently toggleable tools** with per-modality model selection\nand session-persistent settings.\n\n| Tool | What it does |\n|------|-------------|\n| **`web_search`** | Server-side web search with real-time results |\n| **`web_fetch`** | Fetch page content from a URL (web, docs, PDFs) |\n| **`image_generate`** | Text-to-image generation via OpenRouter chat completions |\n| **`image_understand`** | Analyze images via vision models |\n| **`video_understand`** | Analyze videos (YouTube links work with Gemini) |\n| **`pdf_read`** | Extract and analyze PDF content |\n| **`tts_speak`** | Text-to-speech via OpenRouter `/audio/speech` endpoint |\n| **`stt_transcribe`** | Speech-to-text via OpenRouter `/audio/transcriptions` endpoint |\n\n## Install\n\n```bash\npi install npm:@dtmirizzi/pi-openrouter-multimodal\n```\n\nOr from a local checkout:\n\n```bash\npi install /path/to/pi-openrouter-multimodal\n```\n\n## API Key\n\nThe extension resolves the OpenRouter API key from (priority order):\n\n1. `OPENROUTER_API_KEY` environment variable\n2. Pi model registry (provider `openrouter`)\n3. `~/.pi/agent/models.json` under `providers.openrouter.apiKey`\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `/web-tools` | Toggle tools on/off and configure search/fetch engines |\n| `/web-models` | Select models per modality (image, vision, video, PDF, TTS voice, STT) |\n| `/web-search` | Toggle `web_search` and configure search engine |\n| `/web-fetch` | Toggle `web_fetch` and configure fetch engine |\n\nEach command opens an interactive overlay. Use `↑↓` to navigate, `←→` to\ncycle values, `Esc` to close. Settings persist across sessions and survive\ncompaction, shutdown, and tree navigation.\n\n### `/web-tools`\n\nToggle each tool on/off and set search/fetch engine preferences. Also includes\na verbose/compact status-bar display toggle.\n\n### `/web-models`\n\nSelect the model for each modality from a list fetched live from the OpenRouter\nAPI at startup. Falls back to a comprehensive built-in list if the API is\nunavailable.\n\n## Tools\n\n### web_search\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `query` | string | required | Search query |\n| `engine` | string | auto | auto, native, exa, firecrawl, parallel |\n| `max_results` | integer | 5 | Results per search (1-25) |\n| `search_context_size` | string | — | low (5K), medium (15K), high (30K) |\n| `allowed_domains` | string[] | — | Only return results from these domains |\n| `excluded_domains` | string[] | — | Exclude results from these domains |\n\n### web_fetch\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `url` | string | required | URL to fetch content from |\n| `engine` | string | auto | auto, native, exa, openrouter, firecrawl, parallel |\n| `max_content_tokens` | integer | — | Max content length (approximate tokens) |\n\n### image_generate\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `prompt` | string | required | Text prompt describing the image |\n| `model` | string | state | Override the default model from `/web-models` |\n\nSelected via `/web-models`. Models are fetched live from OpenRouter at startup;\nfallback list includes Gemini Flash Image, GPT-5 Image, FLUX.2, Seedream,\nRiverflow, Recraft, Grok Imagine, and more.\n\n### image_understand\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `url` | string | required | Image URL or base64 data URL |\n| `prompt` | string | Describe this image in detail | Analysis prompt |\n| `model` | string | state | Override default from `/web-models` |\n\n### video_understand\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `url` | string | required | Video URL (YouTube links work with Gemini) |\n| `prompt` | string | Describe what happens in this video | Analysis prompt |\n| `model` | string | state | Override default from `/web-models` |\n\n### pdf_read\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `url` | string | required | URL of the PDF document |\n| `prompt` | string | Summarize this document | Analysis prompt |\n| `model` | string | state | Override default from `/web-models` |\n| `engine` | string | cloudflare-ai | cloudflare-ai (free), mistral-ocr (scanned docs), or native |\n\n### tts_speak\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `text` | string | required | Text to convert to speech |\n| `model` | string | state | Override default from `/web-models` |\n| `voice` | string | state | Override default from `/web-models` |\n\n### stt_transcribe\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `audio` | string | required | Base64-encoded audio data |\n| `format` | string | required | wav, mp3, flac, m4a, ogg, webm, aac |\n| `model` | string | state | Override default from `/web-models` |\n| `language` | string | — | ISO-639-1 language code (optional) |\n\n## How It Works\n\nAll tools proxy requests through OpenRouter's API:\n\n- **web_search / web_fetch** — Chat completions with server tool definitions\n  (`openrouter:web_search` / `openrouter:web_fetch`)\n- **image_generate** — Chat completions with `modalities: [\"image\", \"text\"]`\n  on the selected image generation model\n- **image_understand / video_understand** — Chat completions with\n  multimodal content blocks (`image_url`, `video_url`)\n- **pdf_read** — Chat completions with file content block and\n  `file-parser` plugin\n- **tts_speak** — Direct call to `/api/v1/audio/speech`\n- **stt_transcribe** — Direct call to `/api/v1/audio/transcriptions`\n\n### Model Discovery\n\nOn startup, the extension fetches available models from\n`GET /api/v1/models?output_modalities=...` and caches them for use in the\n`/web-models` settings panel. If the API is unreachable, a comprehensive\nset of fallback models is used.\n\n## Development\n\n```bash\n# Install dependencies\nnpm install\n\n# Run tests\nnpm test               # all tests\nnpm run test:unit      # unit tests only\nnpm run test:integration  # requires OPENROUTER_API_KEY\n\n# Format and lint\nnpm run fmt            # format all files\nnpm run lint           # lint + fix all files\nnpm run check          # format + lint + organize imports\nnpm run check:ci       # strict CI check (format + lint, no writes)\n```\n\nThe repo uses [Biome](https://biomejs.dev/) for formatting and linting.\nCI enforces both on every push and PR.\n\n## Assets\n\n<img src=\"assets/logo.png\" width=\"128\" height=\"128\" alt=\"Logo\">\n\n## References\n\n- [OpenRouter Web Search docs](https://openrouter.ai/docs/guides/features/server-tools/web-search)\n- [OpenRouter Web Fetch docs](https://openrouter.ai/docs/guides/features/server-tools/web-fetch)\n- [OpenRouter Multimodal overview](https://openrouter.ai/docs/features/multimodal/overview)\n- [OpenRouter Image Generation](https://openrouter.ai/docs/features/multimodal/image-generation)\n- [OpenRouter TTS](https://openrouter.ai/docs/features/multimodal/text-to-speech)\n- [OpenRouter List Models API](https://openrouter.ai/api/v1/models)\n","readmeFilename":"README.md"}