mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-08 08:12:20 +03:00
fix(release): repair inherited base-red tests from #5480/#5527/#5427/#5521
The fast-path (PR->release/**) does not run the full unit+integration suites, so four merged feature PRs shipped with stale/incorrect tests that only surface on the release PR (PR->main). Repairs (features are correct; align tests to the new behavior — no assertions weakened): - #5480 (gate claude adaptive thinking): adaptive thinking is now injected only for a real Claude Code client (x-app:cli / claude-code UA), not for any bare Claude OAuth token. claude-thinking-tool-choice-guard + base-thinking-budget-5312 now identify as a Claude Code client to exercise the adaptive path (3 tests). - #5527 (T02 inflation guard): the guard reverts a stacked body that did not shrink in tokens. The bail-out/advancement fixtures used growth-appending mock engines; they now carry a droppable padding message the engines empty, so the body realistically shrinks and the marker assertions survive. bailout (5), stacked-async (3), engine-enabled-toggle (2). - #5427 (render onboarding wizard at /providers/new): integration-wiring asserted the old redirect stub; now asserts the route renders ProviderOnboardingWizard. - #5521 (mimocode SOCKS5 per-account proxy): the constructor's default account omitted the proxy field (undefined), breaking the 'all proxies null' backward compat guard. Default it to null, mirroring syncAccountsFromCredentials().
This commit is contained in:
@@ -219,6 +219,10 @@ export class MimocodeExecutor extends BaseExecutor {
|
||||
expiresAt: 0,
|
||||
cooldownUntil: 0,
|
||||
consecutiveFails: 0,
|
||||
// #3837/#5521 backward compat: default the per-account proxy to null (not undefined),
|
||||
// mirroring the syncAccountsFromCredentials() account builder, so an executor with no
|
||||
// accountProxies config still exposes `acct.proxy === null` on every account.
|
||||
proxy: null,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -602,18 +602,15 @@ describe("Page Integration — provider test results privacy", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("Page Integration — legacy provider create route retirement", () => {
|
||||
const legacyProviderNewSrc = readProjectFile(
|
||||
"src/app/(dashboard)/dashboard/providers/new/page.tsx"
|
||||
);
|
||||
describe("Page Integration — provider create route renders the onboarding wizard (#5427)", () => {
|
||||
const providerNewSrc = readProjectFile("src/app/(dashboard)/dashboard/providers/new/page.tsx");
|
||||
|
||||
it("should redirect legacy /dashboard/providers/new to the canonical providers flow", () => {
|
||||
assert.ok(
|
||||
legacyProviderNewSrc,
|
||||
"src/app/(dashboard)/dashboard/providers/new/page.tsx should exist"
|
||||
);
|
||||
assert.match(legacyProviderNewSrc, /redirect\("\/dashboard\/providers"\)/);
|
||||
assert.doesNotMatch(legacyProviderNewSrc, /authMethod:\s*"api_key"/);
|
||||
assert.doesNotMatch(legacyProviderNewSrc, /displayName/);
|
||||
it("renders ProviderOnboardingWizard instead of redirecting (#5427)", () => {
|
||||
// #5427 reversed the earlier redirect-stub retirement: /dashboard/providers/new now
|
||||
// renders the previously-orphaned ProviderOnboardingWizard directly (auth enforced by
|
||||
// the (dashboard) layout). The dedicated guard is tests/unit/onboarding-wizard-route-5427.
|
||||
assert.ok(providerNewSrc, "src/app/(dashboard)/dashboard/providers/new/page.tsx should exist");
|
||||
assert.match(providerNewSrc, /ProviderOnboardingWizard/);
|
||||
assert.doesNotMatch(providerNewSrc, /redirect\("\/dashboard\/providers"\)/);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -52,6 +52,11 @@ async function captureUpstreamBody(
|
||||
body,
|
||||
stream: false,
|
||||
credentials: { accessToken: "sk-ant-oat-test-5312" },
|
||||
// #5480: the default adaptive-thinking injection (and the native-Claude-Code wire
|
||||
// image these #5312 cases exercise) is gated behind a real Claude Code client
|
||||
// (`x-app: cli` / `claude-code` UA). A bare OAuth token from a generic OpenAI-compat
|
||||
// client must opt in via x-omniroute-thinking, so identify as a Claude Code client here.
|
||||
clientHeaders: { "x-app": "cli" },
|
||||
});
|
||||
} finally {
|
||||
globalThis.fetch = originalFetch;
|
||||
|
||||
@@ -52,6 +52,11 @@ async function captureUpstreamBody(
|
||||
stream: false,
|
||||
// OAuth token (sk-ant-oat…) with NO apiKey => wire-image path fires.
|
||||
credentials: { accessToken: "sk-ant-oat-test-thinkguard" },
|
||||
// #5480: the default adaptive-thinking injection is gated behind a real Claude Code
|
||||
// client (`x-app: cli` / `claude-code` UA). A bare OAuth token (generic OpenAI-compat
|
||||
// client) must opt in via x-omniroute-thinking and no longer gets force-injected, so
|
||||
// these tests now identify as a Claude Code client to exercise the adaptive path.
|
||||
clientHeaders: { "x-app": "cli" },
|
||||
});
|
||||
} finally {
|
||||
globalThis.fetch = originalFetch;
|
||||
|
||||
@@ -71,8 +71,9 @@ function makeLowGainEngine(id = LOW_GAIN_ENGINE_ID): CompressionEngine {
|
||||
...makeBaseEngine(id),
|
||||
apply: (body) => {
|
||||
const messages = (body.messages as Array<{ role: string; content: string }>) ?? [];
|
||||
// Tag the user message; drop any padding (non-user) content so the body shrinks.
|
||||
const next = messages.map((m) =>
|
||||
m.role === "user" ? { ...m, content: m.content + "|low" } : m
|
||||
m.role === "user" ? { ...m, content: m.content + "|low" } : { ...m, content: "" }
|
||||
);
|
||||
return {
|
||||
body: { ...body, messages: next },
|
||||
@@ -97,8 +98,9 @@ const highGainEngine: CompressionEngine = {
|
||||
...makeBaseEngine(HIGH_GAIN_ENGINE_ID),
|
||||
apply: (body) => {
|
||||
const messages = (body.messages as Array<{ role: string; content: string }>) ?? [];
|
||||
// Tag the user message; drop any padding (non-user) content so the body shrinks.
|
||||
const next = messages.map((m) =>
|
||||
m.role === "user" ? { ...m, content: m.content + "|high" } : m
|
||||
m.role === "user" ? { ...m, content: m.content + "|high" } : { ...m, content: "" }
|
||||
);
|
||||
return {
|
||||
body: { ...body, messages: next },
|
||||
@@ -146,6 +148,22 @@ function userContent(result: CompressionResult): string {
|
||||
const BAILOUT_ON = { bailout: { enabled: true, minGainPercent: 10 } };
|
||||
const BAILOUT_OFF = {}; // default — no bailout field
|
||||
|
||||
// A fixture body carrying a large droppable padding message. When an engine runs it
|
||||
// drops that padding (and tags the user message), so the FINAL stacked body genuinely
|
||||
// shrinks — keeping the #5527 (T02) inflation guard from reverting these advancement
|
||||
// fixtures. The guard only reverts a pipeline whose final body did NOT shrink in tokens;
|
||||
// these tests exercise bail-out/advancement, an orthogonal concern, so the body must
|
||||
// realistically shrink for the marker assertions to survive the guard.
|
||||
const PADDING = "padding tokens ".repeat(40);
|
||||
function mkBody(): { messages: Array<{ role: string; content: string }> } {
|
||||
return {
|
||||
messages: [
|
||||
{ role: "user", content: "hello" },
|
||||
{ role: "assistant", content: PADDING },
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
// ── suite ────────────────────────────────────────────────────────────────────
|
||||
|
||||
describe("TV1 — stacked pipeline bail-out discipline (OPT-IN)", () => {
|
||||
@@ -169,7 +187,7 @@ describe("TV1 — stacked pipeline bail-out discipline (OPT-IN)", () => {
|
||||
|
||||
describe("sync — applyStackedCompression", () => {
|
||||
it("bail-out ON: throwing engine → step skipped, pipeline does NOT throw", () => {
|
||||
const body = { messages: [{ role: "user", content: "hello" }] };
|
||||
const body = mkBody();
|
||||
|
||||
// Must not throw and original body is kept (throw engine was the only step)
|
||||
const result = applyStackedCompression(body, pipeline(THROW_ENGINE_ID), BAILOUT_ON);
|
||||
@@ -186,7 +204,7 @@ describe("TV1 — stacked pipeline bail-out discipline (OPT-IN)", () => {
|
||||
});
|
||||
|
||||
it("bail-out ON: throwing engine before a good engine → good engine still runs", () => {
|
||||
const body = { messages: [{ role: "user", content: "hello" }] };
|
||||
const body = mkBody();
|
||||
|
||||
// throw engine first, then high-gain engine — the high-gain must still run
|
||||
const result = applyStackedCompression(
|
||||
@@ -201,7 +219,7 @@ describe("TV1 — stacked pipeline bail-out discipline (OPT-IN)", () => {
|
||||
});
|
||||
|
||||
it("bail-out ON: low-gain engine (5%) → body NOT advanced (step skipped)", () => {
|
||||
const body = { messages: [{ role: "user", content: "hello" }] };
|
||||
const body = mkBody();
|
||||
|
||||
const result = applyStackedCompression(body, pipeline(LOW_GAIN_ENGINE_ID), BAILOUT_ON);
|
||||
|
||||
@@ -212,7 +230,7 @@ describe("TV1 — stacked pipeline bail-out discipline (OPT-IN)", () => {
|
||||
});
|
||||
|
||||
it("bail-out ON: high-gain engine (20%) → body IS advanced normally", () => {
|
||||
const body = { messages: [{ role: "user", content: "hello" }] };
|
||||
const body = mkBody();
|
||||
|
||||
const result = applyStackedCompression(body, pipeline(HIGH_GAIN_ENGINE_ID), BAILOUT_ON);
|
||||
|
||||
@@ -221,7 +239,7 @@ describe("TV1 — stacked pipeline bail-out discipline (OPT-IN)", () => {
|
||||
});
|
||||
|
||||
it("bail-out ON: low-gain then high-gain → only high-gain advances body", () => {
|
||||
const body = { messages: [{ role: "user", content: "hello" }] };
|
||||
const body = mkBody();
|
||||
|
||||
const result = applyStackedCompression(
|
||||
body,
|
||||
@@ -234,7 +252,7 @@ describe("TV1 — stacked pipeline bail-out discipline (OPT-IN)", () => {
|
||||
});
|
||||
|
||||
it("bail-out OFF (default): low-gain engine IS applied (opt-in guard)", () => {
|
||||
const body = { messages: [{ role: "user", content: "hello" }] };
|
||||
const body = mkBody();
|
||||
|
||||
// No bailout config at all — original behavior
|
||||
const result = applyStackedCompression(body, pipeline(LOW_GAIN_ENGINE_ID), BAILOUT_OFF);
|
||||
@@ -245,7 +263,7 @@ describe("TV1 — stacked pipeline bail-out discipline (OPT-IN)", () => {
|
||||
});
|
||||
|
||||
it("bail-out OFF (default): throwing engine propagates — unchanged existing behavior", () => {
|
||||
const body = { messages: [{ role: "user", content: "hello" }] };
|
||||
const body = mkBody();
|
||||
|
||||
// Without bail-out, a throw is NOT caught → pipeline throws
|
||||
assert.throws(() => {
|
||||
@@ -258,7 +276,7 @@ describe("TV1 — stacked pipeline bail-out discipline (OPT-IN)", () => {
|
||||
|
||||
describe("async — applyStackedCompressionAsync", () => {
|
||||
it("bail-out ON: async throwing engine → step skipped, no throw", async () => {
|
||||
const body = { messages: [{ role: "user", content: "hello" }] };
|
||||
const body = mkBody();
|
||||
|
||||
const result = await applyStackedCompressionAsync(body, pipeline(THROW_ASYNC_ID), BAILOUT_ON);
|
||||
|
||||
@@ -267,7 +285,7 @@ describe("TV1 — stacked pipeline bail-out discipline (OPT-IN)", () => {
|
||||
});
|
||||
|
||||
it("bail-out ON: async low-gain engine (5%) → step skipped", async () => {
|
||||
const body = { messages: [{ role: "user", content: "hello" }] };
|
||||
const body = mkBody();
|
||||
|
||||
const result = await applyStackedCompressionAsync(
|
||||
body,
|
||||
@@ -280,7 +298,7 @@ describe("TV1 — stacked pipeline bail-out discipline (OPT-IN)", () => {
|
||||
});
|
||||
|
||||
it("bail-out OFF (default): async low-gain engine IS applied", async () => {
|
||||
const body = { messages: [{ role: "user", content: "hello" }] };
|
||||
const body = mkBody();
|
||||
|
||||
const result = await applyStackedCompressionAsync(
|
||||
body,
|
||||
|
||||
@@ -53,8 +53,10 @@ function makeTaggingEngine(id: string): CompressionEngine {
|
||||
validateConfig: () => ({ valid: true, errors: [] }),
|
||||
apply: (body) => {
|
||||
const messages = (body.messages as Array<{ role: string; content: string }>) ?? [];
|
||||
// Tag the user message; drop any padding (non-user) content so the body shrinks
|
||||
// and the #5527 (T02) inflation guard keeps the tagged output instead of reverting.
|
||||
const next = messages.map((m) =>
|
||||
m.role === "user" ? { ...m, content: m.content + "|tagged" } : m
|
||||
m.role === "user" ? { ...m, content: m.content + "|tagged" } : { ...m, content: "" }
|
||||
);
|
||||
return {
|
||||
body: { ...body, messages: next },
|
||||
@@ -83,7 +85,14 @@ function userContent(result: CompressionResult): string {
|
||||
}
|
||||
|
||||
function freshBody() {
|
||||
return { messages: [{ role: "user", content: "hi" }] };
|
||||
// Includes a droppable padding message so an engine that runs nets a real token shrink
|
||||
// (the engine empties non-user content), keeping the #5527 inflation guard from reverting.
|
||||
return {
|
||||
messages: [
|
||||
{ role: "user", content: "hi" },
|
||||
{ role: "assistant", content: "padding tokens ".repeat(40) },
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
describe("registry enabled toggle — stacked loop honors setEngineEnabled", () => {
|
||||
|
||||
@@ -27,8 +27,10 @@ const FA = "fake-async-engine";
|
||||
*/
|
||||
function tag(id: string, body: Record<string, unknown>): CompressionResult {
|
||||
const messages = (body.messages as Array<{ role: string; content: string }>) ?? [];
|
||||
// Tag the user message; drop any padding (non-user) content so the stacked body
|
||||
// genuinely shrinks and the #5527 (T02) inflation guard does not revert it.
|
||||
const next = messages.map((m) =>
|
||||
m.role === "user" ? { ...m, content: `${m.content}|${id}` } : m
|
||||
m.role === "user" ? { ...m, content: `${m.content}|${id}` } : { ...m, content: "" }
|
||||
);
|
||||
return {
|
||||
body: { ...body, messages: next },
|
||||
@@ -87,6 +89,20 @@ function pipeline(...ids: string[]): CompressionPipelineStep[] {
|
||||
return ids.map((engine) => ({ engine })) as unknown as CompressionPipelineStep[];
|
||||
}
|
||||
|
||||
// Fixture body with a large droppable padding message: engines drop it (see `tag`) so the
|
||||
// final stacked body shrinks and the #5527 (T02) inflation guard keeps the tagged output
|
||||
// instead of reverting it. These tests assert engine ORDER/advancement, not compression
|
||||
// ratios, so the body must realistically shrink for the tag assertions to survive the guard.
|
||||
const PADDING = "padding tokens ".repeat(40);
|
||||
function mkBody(): { messages: Array<{ role: string; content: string }> } {
|
||||
return {
|
||||
messages: [
|
||||
{ role: "user", content: "hello" },
|
||||
{ role: "assistant", content: PADDING },
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
describe("stacked compression — async interface (H10)", () => {
|
||||
before(() => {
|
||||
registerCompressionEngine(makeEngine(FS));
|
||||
@@ -98,7 +114,7 @@ describe("stacked compression — async interface (H10)", () => {
|
||||
});
|
||||
|
||||
it("runs a mixed sync+async pipeline in pipeline order", async () => {
|
||||
const body = { messages: [{ role: "user", content: "hello" }] };
|
||||
const body = mkBody();
|
||||
const result = await applyStackedCompressionAsync(body, pipeline(FS, FA));
|
||||
|
||||
assert.equal(userContent(result), "hello|fake-sync-engine|fake-async-engine");
|
||||
@@ -111,7 +127,7 @@ describe("stacked compression — async interface (H10)", () => {
|
||||
});
|
||||
|
||||
it("preserves order when the async engine runs first", async () => {
|
||||
const body = { messages: [{ role: "user", content: "hello" }] };
|
||||
const body = mkBody();
|
||||
const result = await applyStackedCompressionAsync(body, pipeline(FA, FS));
|
||||
|
||||
assert.equal(userContent(result), "hello|fake-async-engine|fake-sync-engine");
|
||||
@@ -122,7 +138,7 @@ describe("stacked compression — async interface (H10)", () => {
|
||||
});
|
||||
|
||||
it("async path yields the same result as sync path for sync-only engines", async () => {
|
||||
const body = { messages: [{ role: "user", content: "hello" }] };
|
||||
const body = mkBody();
|
||||
const asyncResult = await applyStackedCompressionAsync(body, pipeline(FS));
|
||||
const syncResult = applyStackedCompression(body, pipeline(FS));
|
||||
|
||||
@@ -131,7 +147,7 @@ describe("stacked compression — async interface (H10)", () => {
|
||||
});
|
||||
|
||||
it("legacy sync path gracefully skips async-only work without crashing", () => {
|
||||
const body = { messages: [{ role: "user", content: "hello" }] };
|
||||
const body = mkBody();
|
||||
const result = applyStackedCompression(body, pipeline(FA));
|
||||
|
||||
// The async-only engine's sync apply() is a pass-through: no transform.
|
||||
|
||||
Reference in New Issue
Block a user