From ddbffee4ae8ce6c1c83dbd09c638f87c7f0043e7 Mon Sep 17 00:00:00 2001 From: alpha nerd Date: Tue, 7 Apr 2026 16:53:07 +0200 Subject: [PATCH 01/15] fix: tidy up in workflow merge step --- .forgejo/workflows/docker-publish-semantic.yml | 9 +++++---- .forgejo/workflows/docker-publish.yml | 9 +++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/.forgejo/workflows/docker-publish-semantic.yml b/.forgejo/workflows/docker-publish-semantic.yml index 2174f21..eca84c5 100644 --- a/.forgejo/workflows/docker-publish-semantic.yml +++ b/.forgejo/workflows/docker-publish-semantic.yml @@ -148,10 +148,11 @@ jobs: - name: Delete intermediate platform tags run: | - CACHE_ENCODED=$(echo "${{ env.CACHE_IMAGE }}" | sed 's|/|%2F|g') + CACHE_NAME="${{ env.CACHE_IMAGE }}" + CACHE_NAME="${CACHE_NAME##*/}" for tag in platform-semantic-amd64 platform-semantic-arm64; do - curl -s -X DELETE \ + STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE \ -H "Authorization: token ${{ secrets.REGISTRY_TOKEN }}" \ - "https://${{ env.REGISTRY }}/api/v1/packages/${{ github.repository_owner }}/container/${CACHE_ENCODED}/${tag}" \ - && echo "Deleted ${tag}" || echo "Failed to delete ${tag} (ignored)" + "https://${{ env.REGISTRY }}/api/v1/packages/${{ github.repository_owner }}/container/${CACHE_NAME}/${tag}") + echo "DELETE ${tag}: HTTP ${STATUS}" done diff --git a/.forgejo/workflows/docker-publish.yml b/.forgejo/workflows/docker-publish.yml index c93ec2e..c9d5eed 100644 --- a/.forgejo/workflows/docker-publish.yml +++ b/.forgejo/workflows/docker-publish.yml @@ -138,10 +138,11 @@ jobs: - name: Delete intermediate platform tags run: | - IMAGE_ENCODED=$(echo "${{ env.IMAGE_NAME }}" | sed 's|/|%2F|g') + PACKAGE_NAME="${{ env.IMAGE_NAME }}" + PACKAGE_NAME="${PACKAGE_NAME##*/}" for tag in platform-amd64 platform-arm64; do - curl -s -X DELETE \ + STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE \ -H "Authorization: token ${{ secrets.REGISTRY_TOKEN }}" \ - "https://${{ env.REGISTRY }}/api/v1/packages/${{ github.repository_owner }}/container/${IMAGE_ENCODED}/${tag}" \ - && echo "Deleted ${tag}" || echo "Failed to delete ${tag} (ignored)" + "https://${{ env.REGISTRY }}/api/v1/packages/${{ github.repository_owner }}/container/${PACKAGE_NAME}/${tag}") + echo "DELETE ${tag}: HTTP ${STATUS}" done From 9c4b50680590cb454d552eed7c2d206bf07e99cb Mon Sep 17 00:00:00 2001 From: alpha nerd Date: Tue, 7 Apr 2026 17:33:23 +0200 Subject: [PATCH 02/15] fix: workflow tagging for releases --- .forgejo/workflows/docker-publish-semantic.yml | 2 ++ .forgejo/workflows/docker-publish.yml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.forgejo/workflows/docker-publish-semantic.yml b/.forgejo/workflows/docker-publish-semantic.yml index eca84c5..62dbe0d 100644 --- a/.forgejo/workflows/docker-publish-semantic.yml +++ b/.forgejo/workflows/docker-publish-semantic.yml @@ -133,6 +133,8 @@ jobs: uses: https://github.com/docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + flavor: | + latest=false tags: | type=semver,pattern={{version}}-semantic type=semver,pattern={{major}}.{{minor}}-semantic diff --git a/.forgejo/workflows/docker-publish.yml b/.forgejo/workflows/docker-publish.yml index c9d5eed..ad9a064 100644 --- a/.forgejo/workflows/docker-publish.yml +++ b/.forgejo/workflows/docker-publish.yml @@ -123,6 +123,8 @@ jobs: uses: https://github.com/docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + flavor: | + latest=false tags: | type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} From 27d77c6e5dd2c1e97ee22a9d530af64f0ff556e5 Mon Sep 17 00:00:00 2001 From: alpha nerd Date: Tue, 7 Apr 2026 17:50:42 +0200 Subject: [PATCH 03/15] fix: docker build --- .forgejo/workflows/docker-publish-semantic.yml | 10 ---------- .forgejo/workflows/docker-publish.yml | 12 +----------- README.md | 4 ++-- 3 files changed, 3 insertions(+), 23 deletions(-) diff --git a/.forgejo/workflows/docker-publish-semantic.yml b/.forgejo/workflows/docker-publish-semantic.yml index 62dbe0d..c47a1e5 100644 --- a/.forgejo/workflows/docker-publish-semantic.yml +++ b/.forgejo/workflows/docker-publish-semantic.yml @@ -148,13 +148,3 @@ jobs: ${{ env.REGISTRY }}/${{ env.CACHE_IMAGE }}:platform-semantic-amd64 \ ${{ env.REGISTRY }}/${{ env.CACHE_IMAGE }}:platform-semantic-arm64 - - name: Delete intermediate platform tags - run: | - CACHE_NAME="${{ env.CACHE_IMAGE }}" - CACHE_NAME="${CACHE_NAME##*/}" - for tag in platform-semantic-amd64 platform-semantic-arm64; do - STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE \ - -H "Authorization: token ${{ secrets.REGISTRY_TOKEN }}" \ - "https://${{ env.REGISTRY }}/api/v1/packages/${{ github.repository_owner }}/container/${CACHE_NAME}/${tag}") - echo "DELETE ${tag}: HTTP ${STATUS}" - done diff --git a/.forgejo/workflows/docker-publish.yml b/.forgejo/workflows/docker-publish.yml index ad9a064..e3dad4b 100644 --- a/.forgejo/workflows/docker-publish.yml +++ b/.forgejo/workflows/docker-publish.yml @@ -94,7 +94,7 @@ jobs: - name: Install Docker run: | apt-get update -qq - apt-get install -y -qq docker.io jq curl + apt-get install -y -qq docker.io jq - name: Start Docker daemon run: | @@ -138,13 +138,3 @@ jobs: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:platform-amd64 \ ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:platform-arm64 - - name: Delete intermediate platform tags - run: | - PACKAGE_NAME="${{ env.IMAGE_NAME }}" - PACKAGE_NAME="${PACKAGE_NAME##*/}" - for tag in platform-amd64 platform-arm64; do - STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE \ - -H "Authorization: token ${{ secrets.REGISTRY_TOKEN }}" \ - "https://${{ env.REGISTRY }}/api/v1/packages/${{ github.repository_owner }}/container/${PACKAGE_NAME}/${tag}") - echo "DELETE ${tag}: HTTP ${STATUS}" - done diff --git a/README.md b/README.md index 337b4c3..ef3e6f2 100644 --- a/README.md +++ b/README.md @@ -80,14 +80,14 @@ Pre-built multi-arch images (`linux/amd64`, `linux/arm64`) are published automat ```sh docker pull bitfreedom.net/nomyo-ai/nomyo-router:latest -docker pull bitfreedom.net/nomyo-ai/nomyo-router:v0.7.0 +docker pull bitfreedom.net/nomyo-ai/nomyo-router:0.7 ``` **Semantic image** (semantic cache with `all-MiniLM-L6-v2` pre-baked, ~800 MB): ```sh docker pull bitfreedom.net/nomyo-ai/nomyo-router:latest-semantic -docker pull bitfreedom.net/nomyo-ai/nomyo-router:0.7.0-semantic +docker pull bitfreedom.net/nomyo-ai/nomyo-router:0.7-semantic ``` ### Build the container image locally From f6a0f7266cd8f4e0667640574ceb9de5fd718a79 Mon Sep 17 00:00:00 2001 From: alpha nerd Date: Wed, 8 Apr 2026 10:12:19 +0200 Subject: [PATCH 04/15] fix: cache tags in workflows --- .forgejo/workflows/docker-publish-semantic.yml | 4 ++-- .forgejo/workflows/docker-publish.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.forgejo/workflows/docker-publish-semantic.yml b/.forgejo/workflows/docker-publish-semantic.yml index c47a1e5..79bd5d3 100644 --- a/.forgejo/workflows/docker-publish-semantic.yml +++ b/.forgejo/workflows/docker-publish-semantic.yml @@ -88,8 +88,8 @@ jobs: build-args: | SEMANTIC_CACHE=true tags: ${{ env.REGISTRY }}/${{ env.CACHE_IMAGE }}:platform-semantic-${{ matrix.arch }} - cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.CACHE_IMAGE }}:buildcache-semantic-${{ matrix.arch }} - cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.CACHE_IMAGE }}:buildcache-semantic-${{ matrix.arch }},mode=min + cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.CACHE_IMAGE }}:platform-semantic-${{ matrix.arch }} + cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.CACHE_IMAGE }}:platform-semantic-${{ matrix.arch }},mode=max merge: runs-on: docker-amd64 diff --git a/.forgejo/workflows/docker-publish.yml b/.forgejo/workflows/docker-publish.yml index e3dad4b..3979f62 100644 --- a/.forgejo/workflows/docker-publish.yml +++ b/.forgejo/workflows/docker-publish.yml @@ -79,7 +79,7 @@ jobs: provenance: false tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:platform-${{ matrix.arch }} cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache-${{ matrix.arch }} - cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache-${{ matrix.arch }},mode=min + cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache-${{ matrix.arch }},mode=max merge: runs-on: docker-amd64 From 88df31c3906e822703c2e611b0207e937b251e53 Mon Sep 17 00:00:00 2001 From: alpha nerd Date: Wed, 8 Apr 2026 10:18:59 +0200 Subject: [PATCH 05/15] fix: use internal cache tags --- .../workflows/docker-publish-semantic.yml | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.forgejo/workflows/docker-publish-semantic.yml b/.forgejo/workflows/docker-publish-semantic.yml index 79bd5d3..e2fe658 100644 --- a/.forgejo/workflows/docker-publish-semantic.yml +++ b/.forgejo/workflows/docker-publish-semantic.yml @@ -15,11 +15,11 @@ on: - "v*.*.*" workflow_dispatch: -env: - REGISTRY: bitfreedom.net - IMAGE_NAME: ${{ github.repository }} - CACHE_IMAGE: ${{ github.repository }}-buildcache-semantic - DOCKER_BUILD_SUMMARY: "false" + env: + REGISTRY: bitfreedom.net + IMAGE_NAME: ${{ github.repository }} + CACHE_REF: ${{ env.REGISTRY }}/${{ github.repository }}:semantic-buildcache-${{ matrix.arch }} + DOCKER_BUILD_SUMMARY: "false" jobs: build: @@ -87,9 +87,9 @@ jobs: provenance: false build-args: | SEMANTIC_CACHE=true - tags: ${{ env.REGISTRY }}/${{ env.CACHE_IMAGE }}:platform-semantic-${{ matrix.arch }} - cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.CACHE_IMAGE }}:platform-semantic-${{ matrix.arch }} - cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.CACHE_IMAGE }}:platform-semantic-${{ matrix.arch }},mode=max + tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:semantic-platform-${{ matrix.arch }} + cache-from: type=registry,ref=${{ env.CACHE_REF }} + cache-to: type=registry,ref=${{ env.CACHE_REF }},mode=max merge: runs-on: docker-amd64 @@ -145,6 +145,6 @@ jobs: run: | docker buildx imagetools create \ $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ - ${{ env.REGISTRY }}/${{ env.CACHE_IMAGE }}:platform-semantic-amd64 \ - ${{ env.REGISTRY }}/${{ env.CACHE_IMAGE }}:platform-semantic-arm64 + ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:semantic-platform-amd64 \ + ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:semantic-platform-arm64 From 56b214ef469197b85c31786460ee997c94c424ad Mon Sep 17 00:00:00 2001 From: alpha nerd Date: Wed, 8 Apr 2026 10:21:22 +0200 Subject: [PATCH 06/15] fix: avoid docker hub lookup --- .forgejo/workflows/docker-publish-semantic.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.forgejo/workflows/docker-publish-semantic.yml b/.forgejo/workflows/docker-publish-semantic.yml index e2fe658..d39fd2f 100644 --- a/.forgejo/workflows/docker-publish-semantic.yml +++ b/.forgejo/workflows/docker-publish-semantic.yml @@ -18,7 +18,7 @@ on: env: REGISTRY: bitfreedom.net IMAGE_NAME: ${{ github.repository }} - CACHE_REF: ${{ env.REGISTRY }}/${{ github.repository }}:semantic-buildcache-${{ matrix.arch }} + DOCKER_BUILD_SUMMARY: "false" jobs: @@ -88,8 +88,8 @@ jobs: build-args: | SEMANTIC_CACHE=true tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:semantic-platform-${{ matrix.arch }} - cache-from: type=registry,ref=${{ env.CACHE_REF }} - cache-to: type=registry,ref=${{ env.CACHE_REF }},mode=max + cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ github.repository }}:semantic-buildcache-${{ matrix.arch }} + cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ github.repository }}:semantic-buildcache-${{ matrix.arch }},mode=max merge: runs-on: docker-amd64 From f92099de11f9762a4f39b55a4693648f3cca3a2f Mon Sep 17 00:00:00 2001 From: alpha nerd Date: Wed, 8 Apr 2026 10:24:18 +0200 Subject: [PATCH 07/15] fix: don't know what to say --- .forgejo/workflows/docker-publish-semantic.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.forgejo/workflows/docker-publish-semantic.yml b/.forgejo/workflows/docker-publish-semantic.yml index d39fd2f..33da327 100644 --- a/.forgejo/workflows/docker-publish-semantic.yml +++ b/.forgejo/workflows/docker-publish-semantic.yml @@ -89,7 +89,7 @@ jobs: SEMANTIC_CACHE=true tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:semantic-platform-${{ matrix.arch }} cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ github.repository }}:semantic-buildcache-${{ matrix.arch }} - cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ github.repository }}:semantic-buildcache-${{ matrix.arch }},mode=max + cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ github.repository }}:semantic-buildcache-${{ matrix.arch }},mode=max,registry=${{ env.REGISTRY }} merge: runs-on: docker-amd64 From f364a2d123e43baca503ce36b7cea0a4cb2fc84a Mon Sep 17 00:00:00 2001 From: alpha nerd Date: Wed, 8 Apr 2026 10:28:28 +0200 Subject: [PATCH 08/15] fix: trying to replicate the non-semantic workflow --- .forgejo/workflows/docker-publish-semantic.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.forgejo/workflows/docker-publish-semantic.yml b/.forgejo/workflows/docker-publish-semantic.yml index 33da327..2fa59d5 100644 --- a/.forgejo/workflows/docker-publish-semantic.yml +++ b/.forgejo/workflows/docker-publish-semantic.yml @@ -15,11 +15,10 @@ on: - "v*.*.*" workflow_dispatch: - env: - REGISTRY: bitfreedom.net - IMAGE_NAME: ${{ github.repository }} - - DOCKER_BUILD_SUMMARY: "false" +env: + REGISTRY: bitfreedom.net + IMAGE_NAME: ${{ github.repository }} + DOCKER_BUILD_SUMMARY: "false" jobs: build: @@ -88,8 +87,8 @@ jobs: build-args: | SEMANTIC_CACHE=true tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:semantic-platform-${{ matrix.arch }} - cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ github.repository }}:semantic-buildcache-${{ matrix.arch }} - cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ github.repository }}:semantic-buildcache-${{ matrix.arch }},mode=max,registry=${{ env.REGISTRY }} + cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache-semantic-${{ matrix.arch }} + cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache-semantic-${{ matrix.arch }},mode=max merge: runs-on: docker-amd64 From a432a65396d17ab08fd91abeae1090dd5fe6d818 Mon Sep 17 00:00:00 2001 From: alpha nerd Date: Wed, 8 Apr 2026 13:01:56 +0200 Subject: [PATCH 09/15] fix: params is never defined in ollama native backend --- router.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/router.py b/router.py index c87c5ca..2f27d94 100644 --- a/router.py +++ b/router.py @@ -2110,7 +2110,11 @@ async def chat_proxy(request: Request): # Only cache when no max_tokens limit was set — otherwise # finish_reason=length might just mean max_tokens was hit, # not that the context window was exhausted. - _req_max_tok = params.get("max_tokens") or params.get("max_completion_tokens") or params.get("num_predict") + _req_max_tok = ( + params.get("max_tokens") or params.get("max_completion_tokens") or params.get("num_predict") + if use_openai else + (options.get("num_predict") if options else None) + ) if _dr == "length" and not _req_max_tok: _pt = getattr(chunk, "prompt_eval_count", 0) or 0 _ct = getattr(chunk, "eval_count", 0) or 0 From 263c66aedde37af6e21a112770f2df67f4a82cdb Mon Sep 17 00:00:00 2001 From: alpha nerd Date: Fri, 10 Apr 2026 17:29:43 +0200 Subject: [PATCH 10/15] feat: add hostname to dashboard --- router.py | 12 ++++++++++-- static/index.html | 6 ++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/router.py b/router.py index 2f27d94..e780a56 100644 --- a/router.py +++ b/router.py @@ -6,7 +6,7 @@ version: 0.7 license: AGPL """ # ------------------------------------------------------------- -import orjson, time, asyncio, yaml, ollama, openai, os, re, aiohttp, ssl, random, base64, io, enhance, secrets, math +import orjson, time, asyncio, yaml, ollama, openai, os, re, aiohttp, ssl, random, base64, io, enhance, secrets, math, socket try: import truststore; truststore.inject_into_ssl() except ImportError: @@ -3776,7 +3776,15 @@ async def health_proxy(request: Request): return JSONResponse(content=response_payload, status_code=http_status) # ------------------------------------------------------------- -# 27. SSE route for usage broadcasts +# 27. Hostname endpoint +# ------------------------------------------------------------- +@app.get("/api/hostname") +async def get_hostname(): + """Return the hostname of the machine running the router.""" + return JSONResponse(content={"hostname": socket.gethostname()}) + +# ------------------------------------------------------------- +# 28. SSE route for usage broadcasts # ------------------------------------------------------------- @app.get("/api/usage-stream") async def usage_stream(request: Request): diff --git a/static/index.html b/static/index.html index e53e629..419d7bb 100644 --- a/static/index.html +++ b/static/index.html @@ -344,6 +344,7 @@

Router Dashboard

+
@@ -1418,6 +1419,11 @@ function initStatsChart(timeSeriesData, endpointDistribution) {