Skip to content

Commit 265ff6f

Browse files
sena-labsclaude
andcommitted
chore(release): align metadata and docs for v1.3.0
- bump function.json + openrouter_pipe.py header to 1.3.0 - consolidate [Unreleased] + [1.2.0] (never tagged on GitHub) into [1.3.0] - correct stale test counts (252/322 -> 431) across README, CONTRIBUTING, SECURITY, TESTING, PULL_REQUEST_TEMPLATE - correct provider-icon count (22 -> 13) to match _PROVIDER_ICONS - standardize model count on 340+ - shift SECURITY.md supported-versions table by one minor Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 7019ea1 commit 265ff6f

11 files changed

Lines changed: 54 additions & 47 deletions

.github/ISSUE_TEMPLATE/bug_report.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ body:
2828
id: pipe-version
2929
attributes:
3030
label: Pipe Version
31-
placeholder: "e.g. 1.2.0"
31+
placeholder: "e.g. 1.3.0"
3232
validations:
3333
required: true
3434

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
## Testing
2727

28-
- [ ] All unit tests pass (`python test_pipe.py`322/322 ✓)
28+
- [ ] All unit tests pass (`python test_pipe.py`431/431 ✓)
2929
- [ ] New tests added for the changes
3030
- [ ] Integration tests pass (`python integration_test.py`) — if applicable
3131
- [ ] `CHANGELOG.md` updated under `[Unreleased]`

CHANGELOG.md

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,29 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [1.3.0] — 2026-05-07
11+
1012
### Added
1113

1214
- **Automatic provider-icon sync** — new `_sync_model_icons()` method writes provider icons directly into Open WebUI's Models database so they appear in the UI; controlled by the `SYNC_PROVIDER_ICONS` valve (default: enabled). Models with a manually-set icon are never overwritten
1315
- **`_is_owui_managed_icon()` helper** — distinguishes OWUI-default icons (`data:` URLs) and our own provider icons from user-set custom icons, enabling safe icon updates without clobbering user customisations
14-
15-
### Fixed
16-
17-
- **Icon sync: correct prefixed model IDs**`_sync_model_icons()` now discovers the pipe's `function_id` via `type(self).__module__` and writes DB records with the full prefixed ID (e.g. `openrouter_pipe.openai/gpt-4o`) matching what Open WebUI's frontend requests at `/models/model/profile/image`
18-
- **Icon sync: icons now actually appear in the UI** — five bugs prevented provider icons from ever showing after the first pipe load:
19-
- *Wrong skip condition*`if existing_icon:` skipped any model with *any* icon (including the generic `data:` SVG that OWUI assigns by default), so provider icons were never applied; fixed to skip only user-set custom URLs
20-
- *Race condition*`_sync_model_icons()` was called before `pipes()` returned, i.e. before OWUI registered the models; OWUI then overwrote the early insert with its own default icon; fixed by also calling `_sync_model_icons()` on cache-hit paths (until all models are confirmed synced)
21-
- *Exception swallowed retry* — DB errors added the model to `_icons_synced` anyway, permanently preventing retry; removed the erroneous add
22-
- *Insert marked as synced prematurely* — after `insert_new_model` the model was marked synced even though OWUI could overwrite it; the insert path no longer updates `_icons_synced`
23-
- *User params clobbered*`update_model_by_id` used an empty `ModelParams()`, erasing user-configured temperature/system-prompt/etc.; now preserves `existing.params`
24-
- **Icon sync: `function_id` cached at init**`type(self).__module__` is evaluated once in `__init__` instead of on every `_sync_model_icons()` call
25-
- **Streaming status event** — the "done" status event is now correctly emitted at the end of streaming responses (async generator wrapper replaces sync generator that could not `await`)
26-
- **Dead provider-icon code removed**`info.meta.profile_image_url` was included in model dicts returned by `pipes()` but Open WebUI ignores all fields except `id` and `name`; the field has been removed in favour of the new DB-sync approach
27-
- **`pipes()` response always closed** — added `finally: response.close()` to guarantee HTTP connections are returned to the session pool in all code paths (auth errors, JSON decode failures, unexpected exceptions)
28-
29-
## [1.2.0] — 2026-02-17
30-
31-
### Added
32-
16+
- **Audio output handling** — models that return audio (e.g. `openai/gpt-4o-audio-preview`) now have their transcript surfaced as text in both streaming and non-streaming responses
17+
- **Image output handling** — models that return images (e.g. `google/gemini-2.5-flash-image-preview`) now embed valid HTTP/HTTPS image URLs as markdown, with a leading blank-line separator and URL validation to drop unsafe schemes
18+
- **Token usage and cost display** — non-stream responses append a "Tokens: X in / Y out · Cost: $Z" footer when the OpenRouter response includes `usage` data
3319
- **Connection pooling** via `requests.Session` for better performance across multiple API calls
3420
- **Model list caching** with 5-minute TTL and valve-fingerprint invalidation — avoids redundant API calls when reopening the model selector
3521
- **Exponential backoff with jitter** on transient errors (Timeout, ConnectionError) — `min(2^attempt + random, 30s)`
@@ -55,16 +41,37 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
5541
- `FREE_ONLY` pricing comparison uses `float()` instead of string comparison
5642
- Model cache key includes `MODEL_PREFIX` to prevent stale results after prefix changes
5743
- Removed unused `_API_PATH_AUTH` constant and `auth_url` property
44+
- Provider-icon catalogue trimmed to 13 verified providers (was previously documented as 22 but only 13 were ever defined in `_PROVIDER_ICONS`); tilde model filtering and model-ID stripping corrected at the same time
5845

5946
### Fixed
6047

48+
- **Icon sync: correct prefixed model IDs**`_sync_model_icons()` now discovers the pipe's `function_id` via `type(self).__module__` and writes DB records with the full prefixed ID (e.g. `openrouter_pipe.openai/gpt-4o`) matching what Open WebUI's frontend requests at `/models/model/profile/image`
49+
- **Icon sync: icons now actually appear in the UI** — five bugs prevented provider icons from ever showing after the first pipe load:
50+
- *Wrong skip condition*`if existing_icon:` skipped any model with *any* icon (including the generic `data:` SVG that OWUI assigns by default), so provider icons were never applied; fixed to skip only user-set custom URLs
51+
- *Race condition*`_sync_model_icons()` was called before `pipes()` returned, i.e. before OWUI registered the models; OWUI then overwrote the early insert with its own default icon; fixed by also calling `_sync_model_icons()` on cache-hit paths (until all models are confirmed synced)
52+
- *Exception swallowed retry* — DB errors added the model to `_icons_synced` anyway, permanently preventing retry; removed the erroneous add
53+
- *Insert marked as synced prematurely* — after `insert_new_model` the model was marked synced even though OWUI could overwrite it; the insert path no longer updates `_icons_synced`
54+
- *User params clobbered*`update_model_by_id` used an empty `ModelParams()`, erasing user-configured temperature/system-prompt/etc.; now preserves `existing.params`
55+
- **Icon sync: `function_id` cached at init**`type(self).__module__` is evaluated once in `__init__` instead of on every `_sync_model_icons()` call
56+
- **Streaming status event** — the "done" status event is now correctly emitted at the end of streaming responses (async generator wrapper replaces sync generator that could not `await`)
57+
- **Dead provider-icon code removed**`info.meta.profile_image_url` was included in model dicts returned by `pipes()` but Open WebUI ignores all fields except `id` and `name`; the field has been removed in favour of the new DB-sync approach
58+
- **`pipes()` response always closed** — added `finally: response.close()` to guarantee HTTP connections are returned to the session pool in all code paths (auth errors, JSON decode failures, unexpected exceptions)
59+
- **Image markdown safety** — image URLs are validated against `http://`/`https://` schemes before being embedded; invalid URLs are silently dropped instead of producing broken markdown
6160
- Fixed potential payload mutation when `ENABLE_CACHE_CONTROL` is active (deepcopy prevents side effects)
6261
- Fixed potential `IndexError` on stream chunks with empty `choices` array
6362
- Fixed stream error handler not caching response body before closing connection
6463
- Safe `isinstance(err, dict)` checks before calling `.get()` on error objects
6564
- `_close_think_tag()` helper eliminates duplicated think-tag closure logic (was 5x repeated)
6665
- `_stream_response` now closes the response in a `finally` block even on consumer `break`
6766

67+
## [1.2.0] — 2026-02-17
68+
69+
> Documented but never tagged on GitHub. The features below shipped to users via direct paste-install of `openrouter_pipe.py` and were rolled into the `v1.3.0` GitHub release.
70+
71+
### Added
72+
73+
- See `[1.3.0]` for the consolidated entry list. Original 1.2.0 scope: connection pooling, model list caching, exponential backoff with jitter, fallback deduplication, citation URL sanitization, base URL validation, "error" model guard, empty messages guard, fallback model attribution, HTTP 502 auth detection.
74+
6875
## [1.1.1] — 2026-02-17
6976

7077
### Changed
@@ -134,10 +141,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
134141
- Basic error handling and timeout configuration
135142
- Model prefix customization
136143

137-
<!-- Compare links -->
138-
[Unreleased]: https://github.com/sena-labs/Open-WebUI-Pipe-OpenRouter/compare/v1.2.0...HEAD
139-
[1.2.0]: https://github.com/sena-labs/Open-WebUI-Pipe-OpenRouter/compare/v1.1.1...v1.2.0
140-
[1.1.1]: https://github.com/sena-labs/Open-WebUI-Pipe-OpenRouter/compare/v1.1.0...v1.1.1
144+
<!-- Compare links — only point to tags that exist on GitHub.
145+
v1.1.1 and v1.2.0 were documented but never tagged; their content is consolidated under v1.3.0. -->
146+
[Unreleased]: https://github.com/sena-labs/Open-WebUI-Pipe-OpenRouter/compare/v1.3.0...HEAD
147+
[1.3.0]: https://github.com/sena-labs/Open-WebUI-Pipe-OpenRouter/compare/v1.1.0...v1.3.0
141148
[1.1.0]: https://github.com/sena-labs/Open-WebUI-Pipe-OpenRouter/compare/v1.0.0...v1.1.0
142149
[1.0.0]: https://github.com/sena-labs/Open-WebUI-Pipe-OpenRouter/compare/v0.1.0...v1.0.0
143150
[0.1.0]: https://github.com/sena-labs/Open-WebUI-Pipe-OpenRouter/releases/tag/v0.1.0

CONTRIBUTING.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ By participating, you agree to uphold this code.
5555

5656
| Command | Description |
5757
| --- | --- |
58-
| `python test_pipe.py` | Run the full unit test suite (252 tests) |
58+
| `python test_pipe.py` | Run the full unit test suite (431 tests) |
5959
| `python integration_test.py` | Run live API tests (requires `OPENROUTER_API_KEY`) |
6060

6161
## Deliverable-PR playbook
@@ -74,7 +74,7 @@ of value. The playbook:
7474
incidental refactors.
7575

7676
3. **Add or update tests.** A change without test coverage needs a written justification
77-
in the PR body. The unit test suite must remain at 252/252.
77+
in the PR body. The unit test suite must remain at 431/431.
7878

7979
4. **Validate locally** using the same commands CI runs:
8080

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
[![Python](https://img.shields.io/badge/Python-%E2%89%A53.10-blue)](https://www.python.org/)
55
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
66

7-
Access **300+ AI models** through OpenRouter directly inside Open WebUI — with provider routing,
7+
Access **340+ AI models** through OpenRouter directly inside Open WebUI — with provider routing,
88
reasoning tokens, streaming, fallbacks, and cache control out of the box.
99

1010
## Feature gallery
@@ -58,7 +58,7 @@ reasoning tokens, streaming, fallbacks, and cache control out of the box.
5858
- **Middle-out compression** — fits long prompts within context windows (`transforms: ["middle-out"]`).
5959
- **Cache control** — Anthropic-style `cache_control` injection on the longest message chunk.
6060
- **Citations**`[n]` references from web-search-enabled models are converted to markdown links.
61-
- **Provider icons**22 provider logos synced directly into Open WebUI's model database.
61+
- **Provider icons**13 provider logos synced directly into Open WebUI's model database.
6262
- **Retry logic** — exponential backoff with jitter on timeout and connection errors.
6363
- **FREE_ONLY mode** — filter to show only free-tier models (`:free` suffix or `0/0` pricing).
6464
- **Pre-flight validation** — invalid API keys are caught at model-fetch time, not after sending a message.
@@ -96,7 +96,7 @@ All OpenRouter models will appear in the model selector immediately.
9696
git clone https://github.com/sena-labs/Open-WebUI-Pipe-OpenRouter.git
9797
cd Open-WebUI-Pipe-OpenRouter
9898
pip install -r requirements.txt
99-
python test_pipe.py # 252 tests — verify everything is green
99+
python test_pipe.py # 431 tests — verify everything is green
100100
```
101101

102102
## Usage
@@ -199,8 +199,8 @@ The pipe implements the **Manifold** pattern: one pipe entry point that surfaces
199199
Open-WebUI-Pipe-OpenRouter/
200200
├── openrouter_pipe.py # Main pipe source — install this in Open WebUI
201201
├── function.json # Open WebUI community manifest
202-
├── test_pipe.py # Unit test suite (252 tests)
203-
├── integration_test.py # Live API integration tests (47 tests)
202+
├── test_pipe.py # Unit test suite (431 tests)
203+
├── integration_test.py # Live API integration tests (43 assertions)
204204
├── TESTING.md # Manual pre-release checklist
205205
├── SECURITY.md # Security policy
206206
├── CONTRIBUTING.md # Contribution guidelines
@@ -229,7 +229,7 @@ It also removes `user` when sent as a dict (Open WebUI format) since OpenRouter
229229
## Development
230230

231231
```bash
232-
python test_pipe.py # Unit tests (252 tests)
232+
python test_pipe.py # Unit tests (431 tests)
233233
python integration_test.py # Live API tests (requires OPENROUTER_API_KEY)
234234
```
235235

SECURITY.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ critical-only fixes on the previous one.
77

88
| Version | Status | Security fixes |
99
| ------- | ------------------- | -------------- |
10-
| 1.2.x | :white_check_mark: | active |
11-
| 1.1.x | :white_check_mark: | critical only |
12-
| 1.0.x | :x: | end-of-life |
13-
| < 1.0 | :x: | end-of-life |
10+
| 1.3.x | :white_check_mark: | active |
11+
| 1.2.x | :white_check_mark: | critical only |
12+
| 1.1.x | :x: | end-of-life |
13+
| < 1.1 | :x: | end-of-life |
1414

1515
## Reporting a Vulnerability
1616

@@ -70,7 +70,7 @@ The pipe implements the following security practices:
7070

7171
Every push to `main` and every pull request runs:
7272

73-
- **Unit tests** (`.github/workflows/tests.yml`) — 252 tests across Python 3.10–3.13. Failures block merge.
73+
- **Unit tests** (`.github/workflows/tests.yml`) — 431 tests across Python 3.10–3.13. Failures block merge.
7474

7575
## Disclosure Policy
7676

TESTING.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,8 +194,8 @@ Must exit with `All tests passed! ✓` and `✗ Failed: 0`. If any test fails, *
194194

195195
## Quick pre-release checklist
196196

197-
- [ ] `python test_pipe.py`252 passed, 0 failed
198-
- [ ] `python integration_test.py`47/47
197+
- [ ] `python test_pipe.py`431 passed, 0 failed
198+
- [ ] `python integration_test.py`43/43
199199
- [ ] Empty API key → clear error message in model selector
200200
- [ ] Valid API key → 340+ models with provider icons
201201
- [ ] Non-streaming chat works

function.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33
"name": "OpenRouter Pipe",
44
"type": "manifold",
55
"meta": {
6-
"description": "Access 300+ AI models through OpenRouter directly inside Open WebUI. Features provider routing, reasoning tokens with <think> tags, full SSE streaming, model fallbacks, middle-out compression, Anthropic cache control, citations, 22 provider icons, and configurable retry logic.",
6+
"description": "Access 340+ AI models through OpenRouter directly inside Open WebUI. Features provider routing, reasoning tokens with <think> tags, full SSE streaming, model fallbacks, middle-out compression, Anthropic cache control, citations, 13 provider icons, and configurable retry logic.",
77
"manifest": {
88
"title": "OpenRouter Pipe",
99
"author": "Sena Labs",
1010
"author_url": "https://github.com/sena-labs",
1111
"funding_url": "https://github.com/sponsors/sena-labs",
12-
"version": "1.2.0",
12+
"version": "1.3.0",
1313
"license": "MIT",
1414
"required_open_webui_version": "0.4.0",
1515
"requirements": ["requests>=2.20", "pydantic>=2.0"]
@@ -32,6 +32,6 @@
3232
"content": "openrouter_pipe.py",
3333
"is_active": true,
3434
"is_global": true,
35-
"updated_at": "2026-02-17T00:00:00.000Z",
35+
"updated_at": "2026-05-07T00:00:00.000Z",
3636
"created_at": "2026-01-21T00:00:00.000Z"
3737
}

integration_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
Integration test for OpenRouter Pipe v1.2.0
2+
Integration test for OpenRouter Pipe v1.3.0
33
Tests the pipe against the LIVE OpenRouter API.
44
55
Usage:

openrouter_pipe.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
author: Sena Labs
44
author_url: https://github.com/sena-labs
55
funding_url: https://github.com/sponsors/sena-labs
6-
version: 1.2.0
6+
version: 1.3.0
77
license: MIT
88
icon_url: data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48ZGVmcz48bGluZWFyR3JhZGllbnQgaWQ9ImJnIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjEwMCUiIHkyPSIxMDAlIj48c3RvcCBvZmZzZXQ9IjAlIiBzdG9wLWNvbG9yPSIjNmQyOGQ5Ii8+PHN0b3Agb2Zmc2V0PSIxMDAlIiBzdG9wLWNvbG9yPSIjYTc4YmZhIi8+PC9saW5lYXJHcmFkaWVudD48L2RlZnM+PHJlY3Qgd2lkdGg9IjEwMCIgaGVpZ2h0PSIxMDAiIHJ4PSIyMCIgZmlsbD0idXJsKCNiZykiLz48cGF0aCBkPSJNMjAgNTAgQzIwIDMwLCA0MCAzMCwgNTAgMzAgTDUwIDIyIEw2OCA0MCBMNTAgNTggTDUwIDUwIEM0MCA1MCwgMzUgNDUsIDMwIDUwIEMyNSA1NSwgMjAgNzAsIDIwIDUwIFoiIGZpbGw9IndoaXRlIiBvcGFjaXR5PSIwLjk1Ii8+PGNpcmNsZSBjeD0iNzgiIGN5PSIzMCIgcj0iNyIgZmlsbD0id2hpdGUiIG9wYWNpdHk9IjAuOCIvPjxjaXJjbGUgY3g9IjgyIiBjeT0iNTAiIHI9IjciIGZpbGw9IndoaXRlIiBvcGFjaXR5PSIwLjk1Ii8+PGNpcmNsZSBjeD0iNzgiIGN5PSI3MCIgcj0iNyIgZmlsbD0id2hpdGUiIG9wYWNpdHk9IjAuOCIvPjxsaW5lIHgxPSI2OCIgeTE9IjQwIiB4Mj0iNzYiIHkyPSIzMiIgc3Ryb2tlPSJ3aGl0ZSIgc3Ryb2tlLXdpZHRoPSIyIiBvcGFjaXR5PSIwLjUiLz48bGluZSB4MT0iNjgiIHkxPSI0MCIgeDI9Ijc2IiB5Mj0iNTAiIHN0cm9rZT0id2hpdGUiIHN0cm9rZS13aWR0aD0iMiIgb3BhY2l0eT0iMC41Ii8+PGxpbmUgeDE9IjY4IiB5MT0iNDAiIHgyPSI3NiIgeTI9IjY4IiBzdHJva2U9IndoaXRlIiBzdHJva2Utd2lkdGg9IjIiIG9wYWNpdHk9IjAuNSIvPjwvc3ZnPg==
99
required_open_webui_version: 0.4.0
1010
requirements: requests>=2.20, pydantic>=2.0
11-
description: Access 300+ AI models through OpenRouter directly inside Open WebUI. Features provider routing, reasoning tokens with <think> tags, full SSE streaming, model fallbacks, middle-out compression, Anthropic cache control, citations, 22 provider icons, and configurable retry logic.
11+
description: Access 340+ AI models through OpenRouter directly inside Open WebUI. Features provider routing, reasoning tokens with <think> tags, full SSE streaming, model fallbacks, middle-out compression, Anthropic cache control, citations, 13 provider icons, and configurable retry logic.
1212
"""
1313

1414
import copy

0 commit comments

Comments
 (0)