diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index e8ef957e3d..5a1df2f179 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -8,11 +8,11 @@ on: env: GHCR_IMAGE: ghcr.io/${{ github.repository }} - DOCKERHUB_IMAGE: decolua/9router jobs: build-and-push: runs-on: ubuntu-latest + timeout-minutes: 20 permissions: contents: read packages: write @@ -29,22 +29,16 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Log in to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Extract metadata id: meta uses: docker/metadata-action@v5 with: images: | ${{ env.GHCR_IMAGE }} - ${{ env.DOCKERHUB_IMAGE }} tags: | type=semver,pattern={{version}} type=raw,value=latest,enable={{is_default_branch}} + type=sha,prefix=,suffix=,format=short - name: Build and push uses: docker/build-push-action@v6 @@ -53,8 +47,6 @@ jobs: push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - cache-from: type=registry,ref=${{ env.GHCR_IMAGE }}:buildcache - cache-to: type=registry,ref=${{ env.GHCR_IMAGE }}:buildcache,mode=max - platforms: linux/amd64,linux/arm64 + platforms: linux/amd64 provenance: false sbom: false diff --git a/open-sse/handlers/chatCore.js b/open-sse/handlers/chatCore.js index cb6ce96146..e420ca90f7 100644 --- a/open-sse/handlers/chatCore.js +++ b/open-sse/handlers/chatCore.js @@ -161,6 +161,24 @@ export async function handleChatCore({ body, modelInfo, credentials, log, onCred } catch (e) { log?.warn?.("MODALITY", `image prefetch failed: ${e.message}`); } } + + // Per-request opt-out: client can bypass all token savers via header + const tokenSaverEnabled = clientRawRequest?.headers?.[TOKEN_SAVER_HEADER]?.toLowerCase() !== "off"; + // Headroom: compress source messages before translation so all + // output formats (commandcode, ollama, gemini, ...) are covered. + // Uses sourceFormat so body.messages is always present. + // See: https://github.com/decolua/9router/issues/2620 + const headroomDiagnostics = {}; + const headroomStats = await compressWithHeadroom(body, { enabled: tokenSaverEnabled && headroomEnabled, url: headroomUrl, model: upstreamModel, format: sourceFormat, compressUserMessages: headroomCompressUserMessages, diagnostics: headroomDiagnostics }); + const headroomLine = formatHeadroomLog(headroomStats); + const headroomSizeLine = formatHeadroomSizeLog(headroomDiagnostics); + if (headroomLine) { + log?.info?.("HEADROOM", `${headroomLine}${headroomSizeLine ? ` | ${headroomSizeLine}` : ""}`); + if (isHeadroomPhantomSavings(headroomStats, headroomDiagnostics)) { + log?.warn?.("HEADROOM", `reported token delta, but outbound JSON shrank <5%; provider may bill near-original payload | ${headroomSizeLine}`); + } + } else if (tokenSaverEnabled && headroomEnabled) log?.warn?.("HEADROOM", `skipped: ${headroomDiagnostics.reason || "compression unavailable"}${headroomDiagnostics.endpoint ? ` (${headroomDiagnostics.endpoint})` : ""}`); + let translatedBody; let toolNameMap; let customToolNames; @@ -235,26 +253,12 @@ export async function handleChatCore({ body, modelInfo, credentials, log, onCred delete translatedBody.tools; } - // Per-request opt-out: client can bypass all token savers via header - const tokenSaverEnabled = clientRawRequest?.headers?.[TOKEN_SAVER_HEADER]?.toLowerCase() !== "off"; // RTK: compress tool_result content const rtkStats = compressMessages(translatedBody, tokenSaverEnabled && rtkEnabled); const rtkLine = formatRtkLog(rtkStats); if (rtkLine) console.log(rtkLine); - // Headroom: optional external proxy compression; fail open if proxy is absent. - const headroomDiagnostics = {}; - const headroomStats = await compressWithHeadroom(translatedBody, { enabled: tokenSaverEnabled && headroomEnabled, url: headroomUrl, model: upstreamModel, format: finalFormat, compressUserMessages: headroomCompressUserMessages, diagnostics: headroomDiagnostics }); - const headroomLine = formatHeadroomLog(headroomStats); - const headroomSizeLine = formatHeadroomSizeLog(headroomDiagnostics); - if (headroomLine) { - log?.info?.("HEADROOM", `${headroomLine}${headroomSizeLine ? ` | ${headroomSizeLine}` : ""}`); - if (isHeadroomPhantomSavings(headroomStats, headroomDiagnostics)) { - log?.warn?.("HEADROOM", `reported token delta, but outbound JSON shrank <5%; provider may bill near-original payload | ${formatHeadroomSizeLog(headroomDiagnostics)}`); - } - } else if (tokenSaverEnabled && headroomEnabled) log?.warn?.("HEADROOM", `skipped: ${headroomDiagnostics.reason || "compression unavailable"}${headroomDiagnostics.endpoint ? ` (${headroomDiagnostics.endpoint})` : ""}`); - // Token-saver flags accumulator for the single "⚙" log line below. const xf = [];