From 3cab6dc9f0b45f5a62b89ae61c80de333baabb93 Mon Sep 17 00:00:00 2001 From: adevwithpurpose Date: Tue, 18 Aug 2026 11:14:01 -0300 Subject: [PATCH] fix(combo): resolve nativeCodexTurnPin type error and connection-pin gap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #10573 landed with two real defects surfaced by typecheck/tests on the combined release tip: - TS2322: allowedConnectionIds (string[]) was built from compatible.map(t => t.connectionId), whose type includes null. Filter nulls before assigning. - applyNativeCodexTurnPin never assigned the pinned connectionId onto a compatible candidate that didn't already carry it (e.g. an unresolved placeholder target with connectionId: null) — the pin was silently dropped instead of applied. Now resolves the pinned slot's connectionId explicitly (in original order, so allowedConnectionIds stays consistent regardless of pinned-first reordering) before building the returned target list. Confirmed via the existing focused suites: tests/unit/chatgpt-web-codex-turn-pin.test.ts and tests/unit/native-codex-turn-pin-10379.test.ts (14/14 pass), typecheck:core clean. --- open-sse/services/combo/nativeCodexTurnPin.ts | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/open-sse/services/combo/nativeCodexTurnPin.ts b/open-sse/services/combo/nativeCodexTurnPin.ts index 9f9ab96d6d..4fc175b933 100644 --- a/open-sse/services/combo/nativeCodexTurnPin.ts +++ b/open-sse/services/combo/nativeCodexTurnPin.ts @@ -112,16 +112,31 @@ export function applyNativeCodexTurnPin( ); if (compatible.length === 0) return []; - const pinned = compatible.find((t) => t.connectionId === pin.connectionId); - const siblings = compatible.filter((t) => t.connectionId !== pin.connectionId); + let pinnedIndex = compatible.findIndex((t) => t.connectionId === pin.connectionId); + // No candidate already carries the pinned connectionId (e.g. the caller + // resolved the target before a connection was assigned) — assign the pin + // onto the first compatible candidate so dispatch targets it directly. + if (pinnedIndex < 0) pinnedIndex = 0; + + // Resolve the pinned slot's connectionId in ORIGINAL order first, so + // allowedConnectionIds reflects the same set/order regardless of which + // candidate ends up first in the returned (pinned-first) array. + const resolved = compatible.map((t, i) => + i === pinnedIndex ? { ...t, connectionId: pin.connectionId } : t + ); + const allowedConnectionIds = resolved + .map((t) => t.connectionId) + .filter((id): id is string => id !== null); // Pinned connection first, then same-provider/model siblings as fallback - const ordered = pinned ? [pinned, ...siblings] : compatible; + const pinned = resolved[pinnedIndex]; + const siblings = resolved.filter((_, i) => i !== pinnedIndex); + const ordered = [pinned, ...siblings]; return ordered.map((target) => ({ ...target, // Allow only connections for the pinned provider+model - allowedConnectionIds: compatible.map((t) => t.connectionId), + allowedConnectionIds, })); }