Repository navigation
fix(config): externalize 'ws' to fix copilot-m365-web chat timeout - #6098
Merged
diegosouzapw merged 123 commits intoJul 3, 2026
Merged
diegosouzapw merged 123 commits into
diegosouzapw merged 123 commits into
Conversation
…m 11+ pnpm 11 introduced ERR_PNPM_IGNORED_BUILDS for native addon packages. Without explicit allowBuilds approval, these packages silently skip build scripts and OmniRoute fails to start with missing native modules. Changes: - pnpm-workspace.yaml: Set allowBuilds=true for all 13 native addon packages (@parcel/watcher, @swc/core, better-sqlite3, core-js, esbuild, keytar, koffi, libxmljs2, onnxruntime-node, protobufjs, sharp, tls-client-node, unrs-resolver) - pnpm.json: Migrate onlyBuiltDependencies from package.json (deprecated field) to the new pnpm.json config file per pnpm 11 spec. Tested on: pnpm 11.9.0, Node 24, Windows 11. Fixes: pnpm install ERR_PNPM_IGNORED_BUILDS on fresh clone with pnpm 11.
…odeQL cheaper-inference#689) (cheaper-inference#5928) Alert js/incomplete-url-substring-sanitization: the Kimi Web executor test asserted result.url.includes("www.kimi.com"), which a hostile host like www.kimi.com.evil.net would also satisfy. Parse the URL and assert on the exact hostname (new URL(result.url).hostname === "www.kimi.com"), which is both a stronger check and clears the CodeQL warning.
…claude (cheaper-inference#5932) Extract the thinking-budget fitting cluster (fitThinkingToMaxTokens + private safeCapMaxOutputTokens + MIN_* constants) verbatim into the pure leaf openai-to-claude/thinkingBudget.ts. Host re-exports fitThinkingToMaxTokens so external importers keep working and imports it back for internal use. Host 822 -> 738 LOC (under the 800 cap). No behavior change: byte-identical bodies, public export set unchanged. Adds a split-guard test; all consumer tests stay green (translator-openai-to-claude, strip-empty, minimax-m3, passthrough).
…ontributors/uncovered helpers (cheaper-inference#5926) * chore(ci): add test-masking PR-context gate to release-green pre-flight Reproduce check:test-masking (vs origin/main) inside validate-release-green so non-allowlisted net-assert reductions surface in the local pre-flight instead of in a ~40-min CI layer on the release PR. run() now merges a per-gate opts.env so GITHUB_BASE_REF reaches the child. HARD gate; skipped under --quick. Context: v3.8.43 release cost 3 CI round-trips for PR-context gates (test-masking, file-size, pr-evidence) that check:release-green did not reproduce locally. * chore(release): add contributors generator + uncovered-commit reconciliation helpers - scripts/release/gen-contributors.mjs: reproducible `### 🙌 Contributors` table for a CHANGELOG version (parenthetical-group parser → accurate per-PR attribution, noise-handle denylist). v3.8.43 shipped without the section (a real miss) because it was hand-built. npm run release:contributors <version> [--inject]. - scripts/release/list-uncovered-commits.mjs: lists commits since the last tag with no CHANGELOG bullet (v3.8.43 had 123/176 uncovered at reconciliation start). Advisory, maintainer-side. npm run release:uncovered. - 20 unit tests (parenthetical attribution, noise exclusion, idempotent injection, coverage window). * chore(quality): absorb web-cookie-providers-new file-size drift from cheaper-inference#5928 (base-red on release/v3.8.44)
…pure leaves (cheaper-inference#5940) Extract the shared pure primitives and the chat->Responses direction out of the 894-line openai-responses.ts request translator: - openai-responses/helpers.ts: pure primitives (toRecord/toString/clampCallId/ normalizeVerbosity/etc + markers/regexes/JsonRecord), zero host imports - openai-responses/toResponses.ts: openaiToOpenAIResponsesRequest (chat->Responses), imports the helpers leaf Host keeps openaiResponsesToOpenAIRequest (Responses->chat, imported by production) plus both register() directions, and re-exports openaiToOpenAIResponsesRequest so external importers (tests) keep working. Host 894 -> 529 LOC (under the 800 cap). Verbatim bodies (multiset check: leaf A 54/54, leaf B 294 lines, fn1 intact), public export set unchanged, leaves never import the host (no cycle). Adds a split-guard test; all consumer tests stay green (responses-translation-fixes 37, verbosity 4, reasoning-effort 4, orphaned-tool-filter 8, empty-tool-name-loop 8, headroom-responses-format 3).
…not re-run the gate) (cheaper-inference#5944) ci.yml ignores the 'edited' event, so adding the Evidence block to the PR body after a push does not re-run check:pr-evidence — you need another commit. The FAIL report now says so, at the exact place someone sees the red check. + 5 unit tests (classification + hint-on-fail / no-hint-on-pass). Decided against a separate edited-triggered workflow: pr-evidence is not a required check (no ruleset gates it; release PRs merge UNSTABLE, not BLOCKED), so the gap is cosmetic and the generate-release skill already puts Evidence in the body before the first push.
…e (mirror chatgpt-web toolMode) (cheaper-inference#5927) (cheaper-inference#5937) Perplexity Web (Pro/Max) only converted <tool>{...}</tool> text into OpenAI tool_calls for non-streaming requests (hasTools && !stream). Streaming requests -- the default for agentic coding clients -- got the raw <tool> text as plain delta.content and never emitted a tool_calls SSE delta, so clients could not execute tools. Reuses the provider-agnostic buildToolModeResponse()/ toolCompletionToSseStream() helpers already shipped for chatgpt-web (cheaper-inference#5240): when tools are requested, buffer the full completion and convert it into either a JSON completion or a terminal SSE replay carrying delta.tool_calls + finish_reason: tool_calls, regardless of the caller's stream flag. Extended buildToolModeResponse()'s idSeed to be caller-supplied (default 'cgpt', perplexity-web passes 'pplx') so tool_call ids stay provider-specific without duplicating the helper. Non-tool streaming is unchanged (still lives token-by-token via buildStreamingResponse).
…per-inference#5904) Integrated into release/v3.8.44. Thanks @hamsa0x7 for diagnosing the doubled /v1 discovery path and the REDIRECT_BLOCKED probe-loop abort (cheaper-inference#5899). De-scoped to the discovery fix (the cheaper-inference#5903 session-affinity work is handled by cheaper-inference#5943) and added Rule cheaper-inference#18 regression guards.
… (release-pipeline hardening) under v3.8.44 Maintenance (cheaper-inference#5952)
…ty (git stash + in-flight PRs) (cheaper-inference#5955) Integrated into release/v3.8.44 — Hard Rule cheaper-inference#22 (cross-session safety).
…nses (cheaper-inference#5949) Extract the 5 stateless helpers (normalizeToolName, stripEmptyOptionalToolArgs, normalizeOutputIndex, normalizeUpstreamFailure, extractResponsesReasoningSummaryText) verbatim into the pure leaf openai-responses/pureHelpers.ts (no stream state, no host import). Host imports them back and re-exports normalizeUpstreamFailure for external importers (tests). Host 1091 -> 1001 LOC. The stateful streaming core stays in the host (out of scope). Byte-identical bodies (multiset 73/73), no cycle. Adds a split-guard; consumer tests stay green (responses-translation-fixes 37, combo-param-validation-fallback-4519 5).
…nes (cheaper-inference#5830) (cheaper-inference#5948) Integrated into release/v3.8.44 — docs-only upstream sync policy for RTK/Caveman engines (closes cheaper-inference#5830). All 7 checks green.
…er-inference#5934) Integrated into release/v3.8.44 — ReDoS-safe ANSI/VT100 strip for gemini-cli stream frames (port of upstream cheaper-inference#2273, thanks @anki1kr). PR test green (5/5), file-size gate OK.
…vity→openai request (cheaper-inference#5935) Integrated into release/v3.8.44 — strict Anthropic content-block compliance in antigravity→openai (port upstream cheaper-inference#2296). PR test green (9/9). UNSTABLE red is the pre-existing environmental setup-claude base-red (opencode-plugin dist not built in fast-path), not a regression from this PR.
…heaper-inference#5957) Integrated into release/v3.8.44 — MCP stale streamable-HTTP session auto-recovery (thanks @Chewji9875).
…aper-inference#5954) Integrated into release/v3.8.44 — v0-vercel Platform API key validation (thanks @vittoroliveira-dev).
…nference#5907) Integrated into release/v3.8.44 — relaxed provider-scoped chat validation + regression test (thanks @nickwizard).
…h error (cheaper-inference#5899) (cheaper-inference#5920) Integrated into release/v3.8.44 — unconditional /v1 strip in both models-discovery paths + regression test (thanks @anki1kr).
…flight for priority combos (cheaper-inference#5923) (cheaper-inference#5941) Integrated into release/v3.8.44.
… reset-aware re-scoring (cheaper-inference#5903) (cheaper-inference#5943) Integrated into release/v3.8.44.
…se present and thinking enabled (cheaper-inference#5945) (cheaper-inference#5953) Integrated into release/v3.8.44.
Integrated into release/v3.8.44 — ClinePass API-key (BYOK) provider (port upstream 9router#2304, co-authored @adentdk). Validated locally: 16 clinepass tests green; fixed the APIKEY count 158→159 + translate-path golden snapshot (clinepass is a genuine new provider). Remaining UNSTABLE red is the pre-existing environmental setup-claude base-red (opencode-plugin dist not built in fast-path). Supersedes stub cheaper-inference#5541.
…heaper-inference#5950) Integrated into release/v3.8.44 — /v1/ocr endpoint (Mistral OCR) + Mistral moderation (port upstream 9router#2064, co-authored @waguriagentic). Validated locally: 14 ocr-route tests + moderation/servicekind/endpoint-category suites green (CORS→Zod→handler + no-stack-leak assertion). Reds are inherited DRIFT only: cognitive-complexity ratchet (none from OCR files — pre-existing cycle drift, rebaselined at release) + environmental setup-claude base-red.
…r-inference#5933) Integrated into release/v3.8.44 — converts Chat Completions json_schema response_format → Responses API text.format on the Codex path, and preserves existing text.format through verbosity normalization. Base redirected main→release; the openai-responses.ts split that landed this cycle was reconciled by re-applying the delta onto openai-responses/toResponses.ts. Validated locally: 48 translator-openai-responses-req + 8 codex-verbosity tests green. Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
cheaper-inference#5833) Integrated into release/v3.8.44 — wires claude-sonnet-5 end-to-end (registries, modelSpecs, pricing ×3, cost, Sonnet-family fallback, 1M-ctx, static models). Reconciled the add/add overlap with the already-merged cheaper-inference#5796 (kept the PR's superset test with the family-fallback assertion). Validated locally: kiro-sonnet-5 + catalog + pricing/modelSpecs/fallback suites all green. Thanks @ggiak! Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
…inference#5870) Integrated into release/v3.8.44 — gates Bifrost auto-routing by the provider plugin manifest (only manifest-eligible providers reach the sidecar; ineligible/unknown fall back to the TS path with explicit reasons). Superset of cheaper-inference#5869 (carries the full manifest + registry + docs). Resolved an integration-test conflict in favor of the release (which already subsumes this PR's readiness/removeDirWithRetry improvements). Validated locally: 4 provider-plugin-manifest + 11 relay-routing-backend tests green. Thanks @KooshaPari! Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
…o (852→751) (cheaper-inference#5947) * refactor(translator): extract pure message helpers from openai-to-kiro Extract the pure tool/message helpers (parseToolInput, normalizeKiroToolSchema, serializeToolResultContent) verbatim into the leaf openai-to-kiro/messageHelpers.ts. The host imports them back for convertMessages. They were module-private, so the public export set is unchanged (no re-export needed). Host 852 -> 751 LOC. Byte-identical bodies (multiset 99/99), leaf has zero imports (no cycle). Adds a split-guard; consumer tests stay green (translator-openai-to-kiro 33, translator-ai-sdk-image-parts 3). * chore: re-trigger CI (stuck runner on 2/2 shard)
…or (cheaper-inference#5960) Extract two pure clusters from the cursor executor into sibling leaves: - cursor/prompt.ts: isRecordLike + toolChoiceDirectiveLine + buildCursorOutputConstraints - cursor/composer.ts: composer thinking-as-content decoding (isComposerModel, visibleComposerContentFromThinking, composerReasoningRemainder + markers) Host imports both back for internal use and re-exports the 3 composer helpers for external importers (tests). Host 1576 -> 1451 LOC. Byte-identical bodies (verbatim multiset prompt 65/65, composer 32/32), leaves have zero imports (no cycle). Adds a split-guard; consumer tests stay green (cursor-composer-thinking, cursor-streaming, cursor-agent-tool-calls, translator-openai-to-cursor, cursor-agent-system-prompt).
cheaper-inference#5962) Extract the pure SSE-payload -> collected-stream parser (AntigravityCollectedStream, stripZeroWidth, parseAntigravityTextualToolCall, addAntigravityTextualToolCall, processAntigravitySSEPayload/Text, flushAntigravitySSEText) verbatim into the leaf antigravity/sseCollect.ts. Host imports the helpers it uses and re-exports processAntigravitySSEPayload for external importers (tests). Host 1812 -> 1671 LOC. Byte-identical bodies (verbatim multiset 135/135), leaf does not import the host (no cycle). Credit/quota state, auth, and HTTP dispatch untouched. Adds a split-guard; consumer tests stay green (executor-agy 8, executor-antigravity 26, antigravity-sse-collect-socket-release, copilot-agent-antigravity-parity 6).
Contributor
|
Warning Gemini encountered an error creating the review. You can try again by commenting |
…llowbuilds-workspace fix(install): pnpm 11 ERR_PNPM_IGNORED_BUILDS — add allowBuilds to pnpm-workspace.yaml
The Bifrost embedded-service merge referenced process.env.BIFROST_PORT (src/lib/services/bootstrap.ts, default 8080) without adding it to .env.example / ENVIRONMENT.md, so check:env-doc-sync failed on the release tip and reddened Fast Quality Gates for every open PR->release. Docs-only.
…se-envdoc-bifrost-port fix(ci): document BIFROST_PORT — clear env-doc-sync base-red blocking the PR queue
…aper-inference#6051) (cheaper-inference#6111) Co-authored-by: felssxs <felssxs@users.noreply.github.com>
…ce#5913) grok-build 128k→256k, grok-composer-2.5-fast 128k→200k to match actual Grok CLI /context capacities so context-aware routing stops filtering these models out. Registry-only. Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
…lias fix (cheaper-inference#5918) Proxy-registry batch management (batch-delete, auto-test, background health scheduler) + fix resolveProviderAlias to follow the alias chain transitively (oc -> opencode -> opencode-zen). Probe target now operator-configurable via PROXY_HEALTH_TEST_URL. Scope-creep files from the original branch dropped. Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
…heaper-inference#6073) MiniMax M3 leaks raw <think>...</think> into content on 8 OpenAI-format provider tiers; extract it into reasoning_content, leaving the direct minimax/minimax-cn (Claude-format) tiers untouched. Replacement for the stale cheaper-inference#5804 branch. Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
…aper-inference#6076) Normalize OS/arch-derived request headers (X-Stainless-Os/Arch, (OS;arch) UAs, and Antigravity's os.platform()-derived platform substring) in the golden so the test is runner-independent. Fixes the Mac-literal Antigravity UA that would have failed on Linux CI. Supersedes stale cheaper-inference#6002. Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
…e-coverage (cheaper-inference#5975 collateral) cheaper-inference#5975 made the embeddings service honor the connection-level proxy. The pre-existing route-edge-coverage embeddings edge-case tests seed an openai connection while the settings-proxy suite has left a provider-level proxy (provider.local:8080) in the shared DATA_DIR that resetStorage() does not clear — inert before cheaper-inference#5975, but now the leaked proxy fast-fails the embedding upstream with PROXY_UNREACHABLE. These tests do not exercise proxying, so seedOpenAIConnection now pins the connection to proxyEnabled:false, making resolveProxyForConnection return a direct egress regardless of leaked global proxyConfig. No assertions weakened; 16/16 in the file pass. Regression surfaced by the concurrency=1 full-suite run; passes on cheaper-inference#5975's parent, red after it.
…ference#6062) The copilot-m365-web executor imports 'ws' as a client-side WebSocket, but the production Next server bundle did not externalize ws or its native masking helpers (bufferutil, utf-8-validate). Bundling ws breaks the native masking path → TypeError: b.mask is not a function on the first outgoing frame → every chat request times out at the ~80s stream-readiness watchdog. Externalize ws / bufferutil / utf-8-validate in serverExternalPackages. Regression guard added to tests/unit/next-config.test.ts. Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
diegosouzapw
force-pushed
the
fix/ws-externalize-copilot-m365-6062
branch
from
July 3, 2026 19:36
6f3915e to
5ffabef
Compare
Collaborator
|
Heads-up @anki1kr — this fix is now live on |
Merged
HouMinXi
pushed a commit
to HouMinXi/OmniRoute
that referenced
this pull request
Aug 2, 2026
…ference#6098, closes cheaper-inference#6062) Externalize ws / bufferutil / utf-8-validate in serverExternalPackages so the copilot-m365-web WebSocket masking path works at runtime (bundling ws → TypeError: b.mask is not a function → 80s chat timeout). Regression guard in next-config.test.ts. Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
HouMinXi
pushed a commit
to HouMinXi/OmniRoute
that referenced
this pull request
Aug 2, 2026
…eaper-inference#6098, closes cheaper-inference#6062)" This reverts commit bf5a805.
Poid-ZA
pushed a commit
to Poid-ZA/OmniRoute
that referenced
this pull request
Aug 5, 2026
…ference#6098, closes cheaper-inference#6062) Externalize ws / bufferutil / utf-8-validate in serverExternalPackages so the copilot-m365-web WebSocket masking path works at runtime (bundling ws → TypeError: b.mask is not a function → 80s chat timeout). Regression guard in next-config.test.ts. Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
Poid-ZA
pushed a commit
to Poid-ZA/OmniRoute
that referenced
this pull request
Aug 5, 2026
…eaper-inference#6098, closes cheaper-inference#6062)" This reverts commit e61b75f.
KooshaPari
added a commit
to KooshaPari/OmniRoute
that referenced
this pull request
Aug 11, 2026
KooshaPari
added a commit
to KooshaPari/OmniRoute
that referenced
this pull request
Aug 11, 2026
tkgo11
pushed a commit
to tkgo11/OmniRoute
that referenced
this pull request
Sep 23, 2026
…ference#6130, closes cheaper-inference#6062) Re-lands the cheaper-inference#6098 ws-externalization fix onto release/v3.8.44 (it had merged to main by mistake and was reverted). Externalize ws/bufferutil/utf-8-validate so the copilot-m365-web WebSocket masking path works at runtime. Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
muhamadgalihsaputra
pushed a commit
to niyatna/NiyatnaRoute
that referenced
this pull request
Sep 27, 2026
…ference#6098, closes cheaper-inference#6062) Externalize ws / bufferutil / utf-8-validate in serverExternalPackages so the copilot-m365-web WebSocket masking path works at runtime (bundling ws → TypeError: b.mask is not a function → 80s chat timeout). Regression guard in next-config.test.ts. Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
muhamadgalihsaputra
pushed a commit
to niyatna/NiyatnaRoute
that referenced
this pull request
Sep 27, 2026
…eaper-inference#6098, closes cheaper-inference#6062)" This reverts commit 67979e1.
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.
Fixes #6062.
Problem
copilot-m365-webprovider connects, saves, and validates successfully (fixed by #5432 in v3.8.43), but every actual chat request times out after ~80s with:Container logs show the root cause immediately before the timeout:
Root cause
open-sse/executors/copilot-m365-web.tsimportswsas a client-side WebSocket to the BizChat upstream. RFC 6455 §5.3 requires client→server frames to be masked.wsdelegates this to itsbufferutilnative addon.When Next.js bundles
wsinto the server chunk (because it isn't inserverExternalPackages), neitherbufferutilnorutf-8-validateare present in the container'snode_modules— they get tree-shaken away. The addon cannot be resolved, so the frame-masking function ends upundefined. The first outgoing WebSocket frame throwsTypeError: b.mask is not a function.The executor's
ws.on("error")handler catches the throw and callsabort(), but since this happens before any content frame arrives, the stream-readiness watchdog (streamReadiness.ts) fires a generic 80s timeout rather than surfacing the real error.Fix
Add
"ws","bufferutil", and"utf-8-validate"toserverExternalPackagesinnext.config.mjs.This is the same pattern already used for
better-sqlite3,keytar,koffi,tls-client-node, and other packages requiring native addon resolution or CJS interop — it keepswsas an externalrequire()so Node can locatebufferutilat runtime.Note:
src/server/ws/liveServer.tsalso importswsbut is unaffected because it acts as a server (inbound connections only) — it never sends masked frames and never callsbufferutil.Verification
Send a chat completion to
copilot-m365-web/copilot-m365after deploying — the response should stream normally instead of producing the 80s timeout.