Claude/laughing beaver f67164#13
Closed
sena-labs wants to merge 10 commits into
Closed
Conversation
- Add Ko-fi and PayPal badges to the README header - Add Support section before License with Ko-fi (primary) and PayPal links - Update Table of Contents to include Support section - Update .github/FUNDING.yml to surface Ko-fi and PayPal in GitHub's Sponsor button alongside the existing GitHub Sponsors entry Ko-fi: https://ko-fi.com/ivansena (0% fee) PayPal: https://paypal.me/SenaIvan Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove ruvector.db (1.5MB binary) and local .claude worktree state from version control and extend .gitignore to cover swarm/vector/cache dirs (.claude/, .claude-flow/, .swarm/, .remember/, .mypy_cache/, ruvector.db). These are machine-local artifacts that should never have been committed. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
CI installed bare `requests pydantic`, ignoring the version floors in requirements.txt. Install from the file so the tested environment enforces the security-critical `requests>=2.32.4` floor. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…rmance Audit-driven hardening of the OpenRouter pipe. Code + tests + metadata. Security: - Pin requests>=2.32.4 and pass allow_redirects=False on all calls so a misconfigured base URL cannot leak the Authorization header on redirect (CVE-2024-35195 family). - Reject plaintext http:// base URLs except for loopback hosts (SSRF / in-transit bearer leakage). - Add _md_escape_url to percent-encode markdown-breaking characters in citation/image URLs (link-injection defence). - Block data:image/svg+xml and any .svg path from image auto-rendering (inline-script XSS), even on trusted CDN hosts. Output / correctness fixes: - Image-gen models that return the image as message.content (bare CDN URL or data: URI) now render via _looks_like_image_content + an image-CDN allow-list, replacing the false-positive-prone bare-URL heuristic. - Request usage:{include:true} when SHOW_COST_INFO so streaming responses actually carry cost. - Fix HTTPError handler crash when exc.response is None. - Include OPENROUTER_BASE_URL in the model-cache key (stale-cache fix). - Route audio transcripts through _insert_citations. - Retry 502/503/504/429 with proportional backoff, honouring Retry-After. - Accept SSE lines without a space after "data:". - Skip bare-string content parts in cache_control injection. Icon sync: - Track insert-exhausted models separately from synced so a late OWUI registration is still picked up; prune icon-state on cache rebuild. - Extract _write_model_icon to dedupe the update call sites. Misc: - Unify pipe() streaming return to AsyncGenerator. - HTTPAdapter connection-pool tuning; named constants for retry/backoff/caps. Test suite expanded to 603 passing (was 252); mypy and pyflakes clean. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Correct provider-icon count (22 -> 13) across README, function.json was already fixed in the metadata commit. - Update unit-test count to 603 and integration-test count to 44. - Add SHOW_COST_INFO / COST_CURRENCY valves to the README configuration table. - Document the new security behaviours (SecretStr decision, http:// rejection, SVG block, image-CDN allow-list, redirect disabling, 5xx/429 retry) in README Features and SECURITY.md. - Record all fixes under CHANGELOG [Unreleased], including the http:// base-URL breaking change. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Recent Open WebUI (open-webui:main) migrated the Models table methods (get_model_by_id / insert_new_model / update_model_by_id) to async coroutines. _sync_model_icons called them synchronously, so every read returned an un-awaited coroutine and every write was a silent no-op — no provider icon ever reached the database (every model showed OWUI's default). Confirmed by inspecting the live instance: all openrouter_pipe.* model records held /static/favicon.png. Fixes: - Add _resolve_owui_call: runs a returned coroutine to completion in a dedicated thread (pipes() executes inside OWUI's running event loop, so asyncio.run on the current loop is impossible) and passes synchronous results through unchanged, so the pipe works on both sync and async OWUI. - Recognise /static/ as a managed/overwritable default icon (OWUI's current default for pipe sub-models is /static/favicon.png); previously treated as a user-set icon and never overwritten. - Add the Tencent provider icon (live-verified at /images/icons/Tencent.png); 14 provider icons total. Note: OpenRouter only hosts icons for these 14 providers at /images/icons/; other providers (x-ai, z-ai, nvidia, minimax, …) have no icon there and fall back to OWUI's default. Test suite: 622 passing (adds §44 async-OWUI regression + Tencent coverage). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- CONTRIBUTING: requests prerequisite >=2.20 -> >=2.32.4 (matches requirements.txt / function.json). - TESTING: add pre-release checklist sections for cost display (SHOW_COST_INFO), image-generation output rendering, and base-URL security (https enforcement, 5xx/429 retry). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
OpenRouter's live catalog is ~356 models; "300+" understated it. Updated the description in the module docstring, function.json, and README to "350+". Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Strip UTF-8 BOM from function.json (OWUI's JSON manifest parser rejects BOM-prefixed files; json.load() raises JSONDecodeError) and LICENSE (cosmetic; consistent encoding). - Remove the "Feature gallery" placeholder section from README.md — captions without actual screenshot images. The dedicated Features section below already describes every capability. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR strengthens the OpenRouter Pipe’s security and reliability while improving UI rendering for image-generation outputs and adding optional cost display. It also updates dependencies, CI installation, and documentation/test coverage to reflect the new behaviors.
Changes:
- Hardened request handling: enforced safer base URL validation, disabled redirects, bumped
requestsminimum, and added transparent retries for transient HTTP errors (incl. 429 withRetry-After). - Improved output rendering: markdown-escape URLs, block SVG
data:rendering, and detect image-gen outputs delivered asmessage.content(streaming and non-streaming). - Improved Open WebUI integration: adapted provider icon syncing to work with OWUI’s async Models API and added extensive regression/unit tests and updated docs/checklists.
Reviewed changes
Copilot reviewed 12 out of 14 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
openrouter_pipe.py |
Core security/retry hardening, cost opt-in, image-gen detection/rendering, async OWUI icon sync compatibility. |
test_pipe.py |
Large expansion of unit/regression coverage for new security and behavior branches. |
integration_test.py |
Minor assertion message cleanup. |
requirements.txt |
Bumps minimum requests version to >=2.32.4. |
.github/workflows/tests.yml |
Installs dependencies via requirements.txt to enforce minimum versions in CI. |
CHANGELOG.md |
Documents new security and behavior changes and bug fixes. |
README.md |
Updates feature list/counts and adds cost display + support section. |
SECURITY.md |
Updates documented security practices (base URL/TLS, redirects, URL escaping, etc.). |
TESTING.md |
Adds manual checklist items for cost display, image output, base URL security; updates test counts. |
CONTRIBUTING.md |
Updates dependency requirements and test-count references. |
function.json |
Updates requirements list and metadata timestamp; removes BOM. |
LICENSE |
Removes BOM. |
.gitignore |
Ignores new local tooling/artifact directories/files. |
.github/FUNDING.yml |
Adds Ko-fi and PayPal funding links. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+480
to
+488
| if v.startswith("http://"): | ||
| # Reject plaintext HTTP except for loopback hosts to prevent | ||
| # bearer-token leakage in transit and SSRF to public origins. | ||
| host = v[len("http://"):].split("/", 1)[0].split(":", 1)[0].lower() | ||
| if host in ("localhost", "127.0.0.1", "::1") or host.endswith(".localhost"): | ||
| return v | ||
| raise ValueError( | ||
| "Base URL must use https:// (plaintext http:// allowed only for localhost)" | ||
| ) |
Comment on lines
+785
to
793
| async def _wrap_stream(): | ||
| try: | ||
| for chunk in gen: | ||
| yield chunk | ||
| finally: | ||
| if __event_emitter__: | ||
| await __event_emitter__( | ||
| {"type": "status", "data": {"description": "", "done": True}} | ||
| ) |
Comment on lines
+18
to
+20
| - **Empty-model guard** — `pipe()` now returns `"OpenRouter Error: No model specified."` instead of forwarding a blank model ID to the upstream API | ||
| - **Icon-insert retry cap** — `_sync_model_icons` no longer retries an insert indefinitely; after 3 attempts the model is marked synced to avoid unbounded DB churn when OWUI never registers it | ||
| - **Backoff/Retry helpers** — `_backoff_delay()` and `_parse_retry_after()` extracted as static methods; backoff jitter is now proportional (`0.5x–1.5x`) to better distribute load under correlated failures |
Owner
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Related Issue
Type of Change
Changes Made
Testing
python test_pipe.py— 431/431 ✓)python integration_test.py) — if applicableCHANGELOG.mdupdated under[Unreleased]Screenshots / Demo
Checklist
printstatements beyond[OpenRouter Pipe]logging