Files
OmniRoute/open-sse/handlers/chatCore/cliproxyModelMapping.ts
Paijo 7cfabfc5c9 perf(executors): lazy-load the executor registry — defer class imports + construction to first use (#11220) (#11421)
Validated in a combined 3-PR batch worktree off release/v3.8.51 tip (a sibling PR from the same author, #11495, was held out — a typecheck error in zai-web.ts only reproduced with this PR + #11495 boarded together, and cleared without #11495; isolated this PR alone confirmed clean on its own too, so the interaction belonged to #11495's side — see its comment).
- Golden lock: executor-map-golden.test.ts — passes byte-identical (same keys, classes, provider identities, dispatch guards)
- Focused tests part of batch's 94/94 node:test run
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity — all OK
- Full-repo lint: 228 pre-existing dashboard react-hooks/* findings, unrelated to this diff

Thanks for the measured, careful methodology here — the golden-lock contract plus the isolated DATA_DIR benchmarking make this an easy PR to trust despite the wide surface (72 files).
2026-08-25 18:22:46 -03:00

70 lines
2.6 KiB
TypeScript

/**
* CLIProxyAPI model-mapping application (#6876).
*
* The dashboard persists `cliproxyapiModelMapping` per provider
* (`upstream_proxy_config.cliproxyapi_model_mapping`) but nothing at
* request-dispatch time ever consulted it — the configured alias was
* silently dropped and the original model was forwarded verbatim to
* CLIProxyAPI. This module applies the mapping exactly once, at the
* executor boundary, so it only affects requests that actually reach
* CLIProxyAPI (the `cliproxyapi` passthrough leg and the CLIProxyAPI retry
* leg of `fallback` mode) and never the native leg of `fallback` mode.
*/
type ExecutorInput = {
model: string;
body: unknown;
};
// No index signature: executors (BaseExecutor subclasses) must satisfy this
// structurally, and class instances don't carry index signatures.
type ExecutorLike = {
execute: (input: ExecutorInput) => Promise<unknown>;
};
export type CliproxyapiModelMapping = Record<string, unknown> | null | undefined;
function resolveMappedModel(model: string, mapping: CliproxyapiModelMapping): string | null {
if (!mapping || typeof mapping !== "object") return null;
const mapped = (mapping as Record<string, unknown>)[model];
return typeof mapped === "string" && mapped.trim() ? mapped : null;
}
/**
* Rewrites `input.model` (and `input.body.model` when body is a plain
* object) to the mapped model, if one is configured for `input.model`.
* Returns the original input unchanged when no mapping applies.
*/
export function applyCliproxyapiModelMapping(
input: ExecutorInput,
mapping: CliproxyapiModelMapping
): ExecutorInput {
const mappedModel = resolveMappedModel(input.model, mapping);
if (!mappedModel) return input;
const body =
input.body && typeof input.body === "object" && !Array.isArray(input.body)
? { ...(input.body as Record<string, unknown>), model: mappedModel }
: input.body;
return { ...input, model: mappedModel, body };
}
/**
* Wraps an executor so every `execute()` call has the CLIProxyAPI model
* mapping applied first. Returns the executor unchanged when no mapping is
* configured (empty/absent mapping is a no-op, matching prior behavior).
*/
export function wrapExecutorWithCliproxyapiModelMapping<T extends ExecutorLike>(
executor: T,
mapping: CliproxyapiModelMapping
): T {
if (!mapping || typeof mapping !== "object" || Object.keys(mapping).length === 0) {
return executor;
}
const wrapped = Object.create(executor) as T;
wrapped.execute = (input: ExecutorInput) =>
executor.execute(applyCliproxyapiModelMapping(input, mapping));
return wrapped;
}