Files
OmniRoute/tests/unit/azure-param-rules.test.ts
oyi77 77ea656b12 perf(executors): lazy-load the executor registry — defer class imports + construction to first use (#11220)
The executor barrel statically imported ~100 executor modules and
constructed every instance at module load. Measured cold cost on top of
the minimal set: ~0.7–1.2s boot time and ~35MB heap, paid by every
deployment regardless of which providers it uses.

Now:
- executors/index.ts keeps the declarative alias table byte-stable (same
  keys, same order, same ctor args — pinned by the golden lock) but each
  value is a deferred loader using dynamic import; bundlers emit
  on-demand chunks
- registry.ts gains registerLazyExecutor/loadRegisteredExecutor: aliases
  are declared eagerly so hasSpecializedExecutor() and
  listExecutorAliases() stay synchronous, instances materialize once on
  first use and cache into the same registry map
- getExecutor() becomes async; production call sites (chatCore proxy
  resolver, video generation, compression judge/eval clients,
  quotaAutoPing deps, anthropic OAuth validation) await it
- cliproxy wrapper ExecutorLike types drop their index signatures so
  BaseExecutor satisfies them structurally

Measured after (isolated DATA_DIR): barrel boot 712-832ms / ~45MB with
first-use materialization of an executor costing +120-150ms once.

Test impact: 24 unit suites adapted mechanically to the async seam
(await + union narrowing on the Response | {response} execute result);
class imports moved from the barrel to executor module files. The
web-cookie sweep SIGABRT failure is pre-existing (reproduced identically
on the clean base).

Commit gate note: husky lint-staged fails with 'suppressions left that
do not occur anymore' — reproduced identically on a stashed clean tree
(22 baseline problems), independent of this change.
2026-08-24 21:44:22 -03:00

98 lines
3.5 KiB
TypeScript

import { test } from "node:test";
import assert from "node:assert/strict";
import {
applyAzureParamRules,
AZURE_COMPLETION_TOKEN_DEPLOYMENT,
} from "../../open-sse/executors/azureParamRules.ts";
import { getExecutor } from "../../open-sse/executors/index.ts";
import { AzureAiExecutor } from "../../open-sse/executors/azure-ai.ts";
/**
* Regression guards for two Azure 400s observed against a live Azure AI Foundry
* resource:
*
* azure-ai/gpt-chat-latest
* -> 400 "Unsupported parameter: 'max_tokens' is not supported with this
* model. Use 'max_completion_tokens' instead."
* azure-ai/<any gpt-5 deployment> with tools
* -> 400 "Function tools with reasoning_effort are not supported ...
* Please use /v1/responses instead."
*
* Both rules already existed inline in AzureOpenAIExecutor, so the identical
* deployment succeeded on the `azure-openai` connection and failed on
* `azure-ai`, which routed through the bare DefaultExecutor.
*/
test("gpt-chat-latest converts max_tokens to max_completion_tokens", () => {
const out = applyAzureParamRules(
"gpt-chat-latest",
{ max_tokens: 4096 },
{ max_tokens: 4096, messages: [] }
) as Record<string, unknown>;
assert.equal(out.max_tokens, undefined);
assert.equal(out.max_completion_tokens, 4096);
});
test("gpt-5 family converts max_tokens too", () => {
for (const model of ["gpt-5.1", "gpt-5.4-nano", "my-gpt-5-prod", "o3", "o4-mini"]) {
const out = applyAzureParamRules(model, { max_tokens: 100 }, { max_tokens: 100 }) as Record<
string,
unknown
>;
assert.equal(out.max_tokens, undefined, `${model} should drop max_tokens`);
assert.equal(out.max_completion_tokens, 100, `${model} should set max_completion_tokens`);
}
});
test("reasoning_effort is dropped when tools are present", () => {
const out = applyAzureParamRules(
"gpt-5.1",
{},
{ reasoning_effort: "high", tools: [{ name: "read_file" }] }
) as Record<string, unknown>;
assert.equal(out.reasoning_effort, undefined);
assert.equal((out.tools as unknown[]).length, 1);
});
test("reasoning_effort survives when there are no tools", () => {
const out = applyAzureParamRules("gpt-5.1", {}, { reasoning_effort: "high" }) as Record<
string,
unknown
>;
assert.equal(out.reasoning_effort, "high");
});
test("non-default temperature is dropped, temperature=1 kept", () => {
const dropped = applyAzureParamRules("gpt-5.1", {}, { temperature: 0.7 }) as Record<
string,
unknown
>;
assert.equal(dropped.temperature, undefined);
const kept = applyAzureParamRules("gpt-5.1", {}, { temperature: 1 }) as Record<string, unknown>;
assert.equal(kept.temperature, 1);
});
test("unaffected deployments pass through untouched", () => {
const body = { max_tokens: 500, temperature: 0.2, reasoning_effort: "low" };
const out = applyAzureParamRules("Phi-4", {}, body);
assert.deepEqual(out, body);
});
test("the regex does not match unrelated names by accident", () => {
assert.equal(AZURE_COMPLETION_TOKEN_DEPLOYMENT.test("gpt-4o-mini"), false);
assert.equal(AZURE_COMPLETION_TOKEN_DEPLOYMENT.test("DeepSeek-V4-Flash"), false);
assert.equal(AZURE_COMPLETION_TOKEN_DEPLOYMENT.test("Kimi-K2.7-Code"), false);
});
test("azure-ai resolves to AzureAiExecutor, not the bare DefaultExecutor", async () => {
const executor = await getExecutor("azure-ai");
assert.ok(
executor instanceof AzureAiExecutor,
"azure-ai must have its own executor so it inherits the Azure param rules"
);
});