mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-07 15:52:52 +03:00
* fix(build): exec native tool binaries directly in runBuildTool #8858 routed every resolved local bin through process.execPath to avoid Windows .cmd shims — but esbuild >=0.25 ships bin/esbuild as the NATIVE platform executable (ELF on Linux), so Node parsed machine code as JS and build:cli died with 'SyntaxError: Invalid or unexpected token', turning dast-smoke red for every PR. runBuildTool now sniffs the entry's magic bytes (ELF / Mach-O / PE) and execs native binaries directly; JS entries keep going through this Node binary (the .cmd-shim avoidance #8858 wanted). Validation (RED->GREEN on this box): - RED: node node_modules/esbuild/bin/esbuild --version -> SyntaxError (ELF) - GREEN: the exact failing CI step reproduced via the new logic bundles open-sse/mcp-server/server.ts successfully (4.2MB output, 1.3s). * fix(docs): add MDX frontmatter to the 20 remaining docs without it Same failure class as AGENTROUTER_WAF (#9503) and DOCKER_RELEASE_CHANNELS (this run's dast-smoke red): any doc without frontmatter breaks the fumadocs MDX loader during next build, killing build:cli/dast-smoke for every PR. Swept ALL of docs/ (i18n mirrors excluded) in one pass so this class cannot recur one file at a time. * docs(env): document OMNIROUTE_INTERNAL_SERVICE_TOKEN(+_FILE), OPENROUTER_PROVIDER_STATS_* and embedded-Redis binding vars Pre-existing env/docs contract drift from recently merged features made check:env-doc-sync red for any docs-touching PR. Values and defaults read from the defining modules (internalServiceAuth.ts, openrouterProviderStats.ts). * fix(build): resolve bundled npm-cli.js in the standard Unix layout + safe npm fallback off-Windows The opencode-plugin step hard-failed on GitHub runners because resolveBundledNpmEntry only looked next to the node binary (Windows zip layout); hostedtoolcache Node keeps npm at <prefix>/lib/node_modules/npm. Added that candidate, and when neither exists on non-Windows the step now falls back to plain 'npm' — the .cmd-shim hazard #8858 avoids is Windows-only. * test(mutation): register xai-agent-tools-passthrough.test.ts in stryker tap.testFiles The test landed on release/v3.8.50 covering open-sse/handlers/chatCore/passthroughHelpers.ts without the stryker registration, so Fast Quality Gates' drift detection reds any PR that carries it. Mechanical registration so its mutant kills count. --------- Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
274 lines
7.2 KiB
Markdown
274 lines
7.2 KiB
Markdown
---
|
|
title: "Combo Context Requirements Feature"
|
|
version: 3.8.50
|
|
lastUpdated: 2026-08-06
|
|
---
|
|
|
|
# Combo Context Requirements Feature
|
|
|
|
## Overview
|
|
|
|
The Context Requirements feature allows combo configurations to filter and sort targets based on their context window size. This is useful for use cases requiring large context windows like:
|
|
|
|
- Long document processing (100k+ tokens)
|
|
- Large codebase analysis
|
|
- Extensive conversation histories
|
|
- Multi-file code reviews
|
|
|
|
## Configuration
|
|
|
|
### Schema
|
|
|
|
Add `contextRequirements` to your combo's runtime config:
|
|
|
|
```json
|
|
{
|
|
"contextRequirements": {
|
|
"minContextWindow": 128000,
|
|
"preferLargeContext": true,
|
|
"contextFilterMode": "strict"
|
|
}
|
|
}
|
|
```
|
|
|
|
### Fields
|
|
|
|
#### `minContextWindow` (optional)
|
|
|
|
- **Type**: `number` (0 to 10,000,000)
|
|
- **Default**: `undefined` (no filtering)
|
|
- **Description**: Filters out models with context windows below this threshold
|
|
|
|
**Examples**:
|
|
|
|
- `32000` - Filter out models with <32K context
|
|
- `128000` - Require 128K+ context (GPT-4 Turbo, Claude 3)
|
|
- `200000` - Require 200K+ context (Claude 3 Opus)
|
|
- `1000000` - Require 1M+ context (Gemini 1.5 Pro)
|
|
|
|
#### `preferLargeContext` (optional)
|
|
|
|
- **Type**: `boolean`
|
|
- **Default**: `false`
|
|
- **Description**: When `true`, sorts remaining targets by context size (descending). Large context models are tried first.
|
|
|
|
#### `contextFilterMode` (optional)
|
|
|
|
- **Type**: `"strict"` | `"lenient"`
|
|
- **Default**: `"lenient"`
|
|
- **Description**: How to handle models with unknown context window limits
|
|
- `"strict"`: Excludes models with unknown context limits when a known-good target remains; fail-opens to unknowns if the pool would otherwise be empty (#8786)
|
|
- `"lenient"`: Includes models with unknown context limits
|
|
|
|
## Behavior
|
|
|
|
### Filtering Pipeline
|
|
|
|
Context requirements are applied after `filterTargetsByRequestCompatibility()`:
|
|
|
|
1. **Request compatibility filtering** - Removes models incompatible with request (tools, vision, structured output)
|
|
2. **Context requirements filtering** - Applies `minContextWindow` and `contextFilterMode`
|
|
3. **Context-based sorting** - If `preferLargeContext` is true, sorts by context size descending
|
|
|
|
### Filter Mode Logic
|
|
|
|
When `minContextWindow` is set:
|
|
|
|
**Lenient mode** (default):
|
|
|
|
- ✅ Includes models with context >= minContextWindow
|
|
- ✅ Includes models with unknown context limits
|
|
- ❌ Excludes models with context < minContextWindow
|
|
|
|
**Strict mode**:
|
|
|
|
- ✅ Includes models with context >= minContextWindow
|
|
- ❌ Excludes models with unknown context limits (when at least one known-good target remains)
|
|
- ❌ Excludes models with context < minContextWindow
|
|
- ⚠️ **Fail-open (#8786)**: if strict filtering would empty the pool and at least one
|
|
unknown-context target exists, those unknowns are restored instead of returning
|
|
`404 Combo has no executable targets`. Known-too-small targets are never resurrected.
|
|
When the pool is still empty (every known target is below `minContextWindow`), the
|
|
API returns `terminalReason: "context_requirements_exhausted"` with a recovery hint.
|
|
|
|
### Sorting Logic
|
|
|
|
When `preferLargeContext` is true:
|
|
|
|
- Models are sorted by context window size (descending)
|
|
- Unknown context models sort to the end
|
|
- Original strategy order is used as a tiebreaker
|
|
|
|
## Use Cases
|
|
|
|
### Example 1: Long Document Processing
|
|
|
|
```json
|
|
{
|
|
"name": "Document Analysis",
|
|
"strategy": "fusion",
|
|
"config": {
|
|
"contextRequirements": {
|
|
"minContextWindow": 128000,
|
|
"preferLargeContext": true,
|
|
"contextFilterMode": "strict"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
This configuration:
|
|
|
|
- Requires 128K+ context window
|
|
- Prefers larger context models (Gemini 1.5 Pro > Claude 3 Opus > GPT-4 Turbo)
|
|
- Excludes models with unknown context limits
|
|
|
|
### Example 2: Large Codebase Analysis
|
|
|
|
```json
|
|
{
|
|
"name": "Code Review",
|
|
"strategy": "auto",
|
|
"config": {
|
|
"contextRequirements": {
|
|
"minContextWindow": 200000,
|
|
"preferLargeContext": true,
|
|
"contextFilterMode": "lenient"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
This configuration:
|
|
|
|
- Requires 200K+ context window
|
|
- Prefers larger context models
|
|
- Includes models with unknown limits (lenient)
|
|
|
|
### Example 3: Prefer Large Context Without Strict Requirements
|
|
|
|
```json
|
|
{
|
|
"name": "Flexible Chat",
|
|
"strategy": "weighted",
|
|
"config": {
|
|
"contextRequirements": {
|
|
"preferLargeContext": true
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
This configuration:
|
|
|
|
- No minimum requirement (all models eligible)
|
|
- Sorts by context size (largest first)
|
|
- Useful when large context is preferred but not required
|
|
|
|
## API Response
|
|
|
|
When context requirements filter targets, the combo logger outputs:
|
|
|
|
```
|
|
[COMBO] Context requirements: filtered 10 → 3 targets (minContextWindow: 128000, mode: strict)
|
|
[COMBO] Context requirements: kept models gemini-1.5-pro, claude-3-opus-20240229, gpt-4-turbo
|
|
[COMBO] Context requirements: sorted by context size (descending): gemini-1.5-pro(1000000), claude-3-opus-20240229(200000), gpt-4-turbo(128000)
|
|
```
|
|
|
|
## Implementation Details
|
|
|
|
### Backend Module
|
|
|
|
`open-sse/services/combo/contextRequirements.ts`:
|
|
|
|
- `applyContextRequirements()` - Main filtering function
|
|
- `getTargetContextWindow()` - Context lookup helper
|
|
- Uses `getModelContextLimit()` from `modelCapabilities.ts`
|
|
|
|
### Integration Point
|
|
|
|
`open-sse/services/combo.ts` line 1187:
|
|
|
|
```typescript
|
|
orderedTargets = filterTargetsByRequestCompatibility(orderedTargets, body, log);
|
|
orderedTargets = applyContextRequirements(orderedTargets, config.contextRequirements, log);
|
|
```
|
|
|
|
### Schema Definition
|
|
|
|
`src/shared/validation/schemas/combo.ts`:
|
|
|
|
```typescript
|
|
contextRequirements: z
|
|
.object({
|
|
minContextWindow: z.coerce.number().int().min(0).max(10_000_000).optional(),
|
|
preferLargeContext: z.boolean().optional(),
|
|
contextFilterMode: z.enum(["strict", "lenient"]).optional(),
|
|
})
|
|
.strict()
|
|
.optional(),
|
|
```
|
|
|
|
## Testing
|
|
|
|
### Run Tests
|
|
|
|
```bash
|
|
# Unit tests (schema + logic)
|
|
npm test tests/unit/combo-context-requirements.test.ts
|
|
|
|
# Integration tests (end-to-end)
|
|
npm test tests/unit/combo/context-requirements-integration.test.ts
|
|
```
|
|
|
|
### Test Coverage
|
|
|
|
- Schema validation: 6 tests
|
|
- Filtering logic: 6 tests
|
|
- Integration: 5 tests
|
|
- **Total**: 17/17 passing ✅
|
|
|
|
## Troubleshooting
|
|
|
|
### All targets filtered out
|
|
|
|
**Problem**: All targets removed, combo returns "no compatible models"
|
|
|
|
**Solutions**:
|
|
|
|
1. Lower `minContextWindow` threshold
|
|
2. Switch to `"lenient"` mode to include unknown context models
|
|
3. Remove `minContextWindow` and use only `preferLargeContext`
|
|
|
|
### Unknown context models excluded
|
|
|
|
**Problem**: Custom/new models excluded even though they have large context
|
|
|
|
**Solutions**:
|
|
|
|
1. Switch to `"lenient"` mode (default)
|
|
2. Add model context limit to `modelCapabilities.ts`
|
|
3. Remove context filtering and rely on strategy order
|
|
|
|
### Sorting not applied
|
|
|
|
**Problem**: `preferLargeContext` doesn't change order
|
|
|
|
**Check**:
|
|
|
|
1. Verify `preferLargeContext: true` in config
|
|
2. Check if all targets have unknown context (all sort equal)
|
|
3. Verify multiple targets remain after filtering
|
|
|
|
## Related
|
|
|
|
- [Auto-Combo Routing Strategies](./routing/AUTO-COMBO.md)
|
|
- [Resilience Guide](./architecture/RESILIENCE_GUIDE.md)
|
|
|
|
## Version History
|
|
|
|
- **v3.8.47**: Initial implementation
|
|
- Added `contextRequirements` config
|
|
- Created backend filtering module
|
|
- Full test coverage (no dedicated dashboard UI yet — configure via combo JSON)
|