mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-31 04:12:10 +03:00
* feat(combo): add context requirements config for target filtering
Add contextRequirements config field to combo runtime config:
- minContextWindow: filter models below threshold (0-10M tokens)
- preferLargeContext: sort targets by context size descending
- contextFilterMode: 'strict' excludes unknown limits, 'lenient' includes them
Implementation:
- Added Zod schema validation in combo.ts
- Created contextRequirements.ts module with applyContextRequirements()
- Integrated filtering after filterTargetsByRequestCompatibility()
- Full test coverage with unit + integration tests
Tests: 17/17 pass (combo-context-requirements.test.ts + integration)
* feat(combo): add ContextRequirementsEditor UI component
Add standalone React component for editing context requirements config:
- Slider for minContextWindow (0 to 1M tokens) with presets
- Toggle for preferLargeContext sorting
- Radio group for contextFilterMode (strict/lenient)
- Tooltips explaining each option
- Active filters summary display
Component features:
- Shadcn UI components (Card, Slider, Switch, RadioGroup)
- Preset buttons for common context sizes (8K, 32K, 128K, 1M)
- Conditional display of filter mode when minContextWindow > 0
- Clear visual feedback of active filters
Integration:
Import and use in combo config form where other config fields
like fusionTuning and judgeModel are edited. Pass combo.config.contextRequirements
as value prop and update on onChange.
Example usage:
<ContextRequirementsEditor
value={config.contextRequirements}
onChange={(val) => updateConfig({ contextRequirements: val })}
/>
UI matches existing combo config editor patterns.
* feat(combo): wire ContextRequirementsEditor into combo config form
Adds context requirements section to combo edit page (strategy section),
matching existing ResponseValidation pattern. Placed after response
validation block, before agent features.
* docs(combo): add context requirements feature documentation
Covers: config schema, behavior, use cases, UI integration,
troubleshooting, and test instructions.
* fix(combo): pass provider+modelStr to getModelContextLimit for accurate context resolution
Per gemini-code-assist review feedback: model names are not globally
unique across providers. Passing both provider and modelStr ensures
correct context limit resolution in applyContextRequirements().
* fix(combo): repair broken doc links and restore test:unit:fast flag
- Point docs/combo-context-requirements.md 'Related' links at real docs
(routing/AUTO-COMBO.md, architecture/RESILIENCE_GUIDE.md) — the three
placeholder links (strategies.md/model-capabilities.md/fusion-tuning.md)
did not exist and failed check:doc-links (Docs Gates fast-path).
- Revert an out-of-scope package.json change to test:unit:fast that dropped
--test-isolation=none; restore to match release/v3.8.47.
Co-authored-by: oyi77 <oyi77@users.noreply.github.com>
* test(combo): validate context requirements against the real Zod schema
Point tests/unit/combo-context-requirements.test.ts at the real
comboRuntimeConfigSchema export (src/shared/validation/schemas/combo.ts)
instead of hand-duplicating the Zod schema inline, so the test catches
schema drift.
Also declare contextRequirements on DEFAULT_COMBO_CONFIG so
resolveComboSetupConfig's inferred return type includes the key —
combo.ts reads config.contextRequirements but the property was missing
from the object typecheck:core infers types from, causing a build error.
Co-authored-by: oyi77 <oyi77@users.noreply.github.com>
* fix(combos): remove dead ContextRequirementsEditor scaffolding (broken ui/card+label imports)
The editor imported @/components/ui/card and @/components/ui/label which do not
exist in the repo, breaking the Turbopack build. Removed the editor + its page.tsx
usage + doc mention; the real fix (comboConfig contextRequirements default + test)
is preserved.
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
---------
Co-authored-by: oyi77 <oyi77@users.noreply.github.com>
Co-authored-by: Diego Rodrigues de Sa e Souza <diegosouza.pw@gmail.com>
Co-authored-by: Diego Rodrigues de Sa e Souza <8016841+diegosouzapw@users.noreply.github.com>
102 lines
3.4 KiB
TypeScript
102 lines
3.4 KiB
TypeScript
import { describe, it } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import { applyContextRequirements } from "../../../open-sse/services/combo/contextRequirements";
|
|
import type { ResolvedComboTarget } from "../../../open-sse/services/combo/types";
|
|
|
|
// Mock logger
|
|
const mockLog = {
|
|
info: () => {},
|
|
debug: () => {},
|
|
warn: () => {},
|
|
error: () => {},
|
|
};
|
|
|
|
describe("Context Requirements Integration", () => {
|
|
it("should filter and sort targets with full context requirements", () => {
|
|
const targets = [
|
|
{ modelStr: "gpt-3.5-turbo", provider: "openai", weight: 1 },
|
|
{ modelStr: "gpt-4", provider: "openai", weight: 1 },
|
|
{ modelStr: "gpt-4-turbo", provider: "openai", weight: 1 },
|
|
{ modelStr: "claude-3-opus-20240229", provider: "anthropic", weight: 1 },
|
|
{ modelStr: "gemini-1.5-pro", provider: "google", weight: 1 },
|
|
];
|
|
|
|
const requirements = {
|
|
minContextWindow: 100000,
|
|
preferLargeContext: true,
|
|
contextFilterMode: "strict" as const,
|
|
};
|
|
|
|
const result = applyContextRequirements(targets, requirements, mockLog);
|
|
// Should filter out models with <100k context and, in strict mode, also drop
|
|
// models whose context window is unknown in the current catalog snapshot.
|
|
assert.ok(result.length < targets.length);
|
|
assert.ok(
|
|
result.every((target) => targets.some((original) => original.modelStr === target.modelStr)),
|
|
"Filtered targets should be a subset of the original list"
|
|
);
|
|
});
|
|
|
|
it("should not filter when no requirements specified", () => {
|
|
const targets = [
|
|
{ modelStr: "gpt-3.5-turbo", provider: "openai", weight: 1 },
|
|
{ modelStr: "gpt-4", provider: "openai", weight: 1 },
|
|
];
|
|
|
|
const result = applyContextRequirements(targets, undefined, mockLog);
|
|
assert.equal(result.length, targets.length);
|
|
assert.equal(result, targets); // Same reference
|
|
});
|
|
|
|
it("should handle empty targets array", () => {
|
|
const targets: ResolvedComboTarget[] = [];
|
|
const requirements = {
|
|
minContextWindow: 32000,
|
|
preferLargeContext: true,
|
|
};
|
|
|
|
const result = applyContextRequirements(targets, requirements, mockLog);
|
|
assert.equal(result.length, 0);
|
|
});
|
|
|
|
it("should handle lenient mode with unknown context models", () => {
|
|
const targets = [
|
|
{ modelStr: "gpt-4", provider: "openai", weight: 1 },
|
|
{ modelStr: "unknown-model", provider: "custom", weight: 1 },
|
|
];
|
|
|
|
const requirements = {
|
|
minContextWindow: 32000,
|
|
contextFilterMode: "lenient" as const,
|
|
};
|
|
|
|
const result = applyContextRequirements(targets, requirements, mockLog);
|
|
|
|
// Should include unknown-model in lenient mode
|
|
assert.ok(
|
|
result.some((t) => t.modelStr === "unknown-model"),
|
|
"Should include unknown model in lenient mode"
|
|
);
|
|
});
|
|
|
|
it("should handle strict mode with unknown context models", () => {
|
|
const targets = [
|
|
{ modelStr: "claude-3-opus-20240229", provider: "anthropic", weight: 1 },
|
|
{ modelStr: "unknown-model", provider: "custom", weight: 1 },
|
|
];
|
|
|
|
const requirements = {
|
|
minContextWindow: 32000,
|
|
contextFilterMode: "strict" as const,
|
|
};
|
|
|
|
const result = applyContextRequirements(targets, requirements, mockLog);
|
|
|
|
// Should exclude unknown-model in strict mode
|
|
assert.ok(
|
|
!result.some((t) => t.modelStr === "unknown-model"),
|
|
"Should exclude unknown model in strict mode"
|
|
);
|
|
});
|
|
});
|