fix(opencode-plugin): honor geminiSanitization & fetchInterceptor feature flags (#2546)

Follow-up fix for #2529 feature-flag gating. Integrated into release/v3.8.2.
This commit is contained in:
Diego Rodrigues de Sa e Souza
2026-05-21 23:21:41 -03:00
committed by GitHub
parent c96ba2d7eb
commit e3ba13bd09
3 changed files with 64 additions and 19 deletions

View File

@@ -2,11 +2,11 @@ name: opencode-plugin CI
on:
push:
branches: [main, release/v3.8.1, release/v3.8.2]
branches: [main, release/v3.8.2]
paths:
- "@omniroute/opencode-plugin/**"
pull_request:
branches: [main, release/v3.8.1, release/v3.8.2]
branches: [main, release/v3.8.2]
paths:
- "@omniroute/opencode-plugin/**"
types: [opened, synchronize, reopened, ready_for_review]

View File

@@ -241,7 +241,13 @@ function coercePluginOptions(opts?: PluginOptions): OmniRoutePluginOptions {
* user instead of dispatching a request with bogus credentials.
*/
export function createOmniRouteAuthHook(opts?: OmniRoutePluginOptions): AuthHook {
const { providerId, displayName, baseURL } = resolveOmniRoutePluginOptions(opts);
const { providerId, displayName, baseURL, features } = resolveOmniRoutePluginOptions(opts);
// Both fetch-layer features default ON (parity with the rest of the plugin's
// `features.X !== false` convention). Honoring them here lets users disable
// the interceptor/sanitizer from opencode.json — previously these flags were
// documented and schema-validated but silently ignored.
const wantFetchInterceptor = (features ?? {}).fetchInterceptor !== false;
const wantGeminiSanitization = (features ?? {}).geminiSanitization !== false;
const hook: AuthHook = {
provider: providerId,
@@ -285,22 +291,26 @@ export function createOmniRouteAuthHook(opts?: OmniRoutePluginOptions): AuthHook
if (!resolvedBaseURL) {
return { apiKey };
}
return {
apiKey,
baseURL: resolvedBaseURL,
// Composition: sanitise Gemini tool schemas FIRST (T-06), then
// inject Bearer (T-04). Both layers are pure with respect to the
// other's concern (body vs headers) so order is logically free;
// wrapping the pure body-transform around the header-injecting
// interceptor reads cleaner and keeps T-06 testable in isolation
// against any inner fetch (real or stub).
fetch: createGeminiSanitizingFetch(
createOmniRouteFetchInterceptor({
apiKey,
baseURL: resolvedBaseURL,
})
),
};
// Composition: sanitise Gemini tool schemas FIRST (T-06), then inject
// Bearer (T-04). Both layers are pure with respect to the other's
// concern (body vs headers) so order is logically free; wrapping the
// pure body-transform around the header-injecting interceptor reads
// cleaner and keeps T-06 testable in isolation against any inner fetch
// (real or stub). Each layer is gated by its feature flag; when both
// are disabled we fall back to the SDK's default fetch (apiKey only).
let composedFetch: typeof fetch | undefined;
if (wantFetchInterceptor) {
composedFetch = createOmniRouteFetchInterceptor({
apiKey,
baseURL: resolvedBaseURL,
});
}
if (wantGeminiSanitization) {
composedFetch = createGeminiSanitizingFetch(composedFetch ?? fetch);
}
return composedFetch
? { apiKey, baseURL: resolvedBaseURL, fetch: composedFetch }
: { apiKey, baseURL: resolvedBaseURL };
}
return {};
},

View File

@@ -82,6 +82,41 @@ test("loader: valid api auth → {apiKey, baseURL, fetch} when baseURL option se
);
});
test("loader: features.fetchInterceptor=false AND geminiSanitization=false → no custom fetch (flags honored)", async () => {
// Regression: both fetch-layer flags were documented + schema-validated but
// silently ignored. Disabling both must fall back to the SDK default fetch.
const hook = createOmniRouteAuthHook({
baseURL: "https://or.example.com/v1",
features: { fetchInterceptor: false, geminiSanitization: false },
});
const result = await hook.loader!(
async () => ({ type: "api", key: "sk-x" }) as never,
{} as never
);
assert.deepEqual(result, { apiKey: "sk-x", baseURL: "https://or.example.com/v1" });
assert.equal(
(result as { fetch?: unknown }).fetch,
undefined,
"both flags off must omit the custom fetch"
);
});
test("loader: features.fetchInterceptor=false but geminiSanitization=true → fetch still wired (sanitizer only)", async () => {
const hook = createOmniRouteAuthHook({
baseURL: "https://or.example.com/v1",
features: { fetchInterceptor: false, geminiSanitization: true },
});
const result = await hook.loader!(
async () => ({ type: "api", key: "sk-x" }) as never,
{} as never
);
assert.equal(
typeof (result as { fetch?: unknown }).fetch,
"function",
"geminiSanitization alone must still provide a fetch wrapper"
);
});
test("loader: null/undefined auth → {} (no creds yet, OC surfaces /connect)", async () => {
const hook = createOmniRouteAuthHook();
const r1 = await hook.loader!(async () => null as never, {} as never);