feat: scenario routing architecture redesign (020)#25
Open
john-zhh wants to merge 8 commits intofeat/v3.0.1from
Open
feat: scenario routing architecture redesign (020)#25john-zhh wants to merge 8 commits intofeat/v3.0.1from
john-zhh wants to merge 8 commits intofeat/v3.0.1from
Conversation
Add comprehensive specification for redesigning scenario routing to be: - Protocol-agnostic (Anthropic, OpenAI Chat, OpenAI Responses) - Middleware-extensible (explicit routing decisions) - Open scenario namespace (custom route keys) - Per-scenario routing policies (strategy, weights, thresholds) Key requirements: - Normalized request layer for protocol-agnostic detection - First-class middleware routing hooks (RoutingDecision, RoutingHints) - Open scenario keys supporting custom workflows (spec-kit stages) - Strong config validation with fail-fast behavior - Comprehensive routing observability Includes quality checklist confirming specification readiness. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Completed foundational infrastructure for protocol-agnostic scenario routing:
Phase 1 (Setup):
- T001-T003: Created routing file structure and types
- Added RoutingDecision and RoutingHints types in routing_decision.go
- Extended RequestContext with routing fields (using interface{} to avoid circular deps)
Phase 2 (Foundational):
- T004: Bumped config version 14 → 15
- T005: Added RoutePolicy type replacing ScenarioRoute
- Supports per-scenario strategy, weights, threshold, fallback
- Updated ProfileConfig.Routing to use string keys and RoutePolicy values
- Updated Clone() method for deep copying
- T006: Implemented NormalizeScenarioKey function
- Supports camelCase, kebab-case, snake_case normalization
- Examples: web-search → webSearch, long_context → longContext
- T007: Implemented ValidateRoutingConfig function
- Validates provider existence, weights, strategies, scenario keys
- Comprehensive error messages for config issues
- T008: Added structured logging functions for routing
- LogRoutingDecision, LogRoutingFallback, LogProtocolDetection
- LogRequestFeatures, LogProviderSelection
Phase 3 (User Story 1 - Tests):
- T009-T013: Wrote comprehensive tests for protocol normalization
- TestNormalizeAnthropicMessages (7 test cases)
- TestNormalizeOpenAIChat (7 test cases)
- TestNormalizeOpenAIResponses (5 test cases)
- TestMalformedRequestHandling (5 test cases)
- TestExtractFeatures (5 test cases)
- Tests follow TDD approach (written before implementation)
Files modified:
- internal/config/config.go: RoutePolicy type, version bump
- internal/config/store.go: ValidateRoutingConfig function
- internal/middleware/interface.go: Routing fields in RequestContext
- internal/daemon/logger.go: Routing-specific logging functions
Files created:
- internal/proxy/routing_decision.go: RoutingDecision and RoutingHints types
- internal/proxy/routing_classifier.go: NormalizeScenarioKey function
- internal/proxy/routing_normalize_test.go: Comprehensive test suite (29 tests)
Next: Implement User Story 1 (protocol normalization functions)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implemented core normalization functions for protocol-agnostic routing: Types & Infrastructure: - Created NormalizedRequest and NormalizedMessage types - Created RequestFeatures type for routing classification - Updated config types: Scenario remains type alias, but routing uses string keys - Changed ProfileConfig.Routing from map[Scenario]*ScenarioRoute to map[string]*RoutePolicy - Updated RoutingConfig.ScenarioRoutes to use string keys Normalization Functions (T015-T021): - NormalizeAnthropicMessages: Handles Anthropic Messages API format - Extracts model, system prompt, messages - Supports both string and array content (text + images) - Detects image content and tool usage - NormalizeOpenAIChat: Handles OpenAI Chat Completions API format - Extracts system message from messages array - Supports vision content (image_url type) - Detects functions and tools - NormalizeOpenAIResponses: Handles OpenAI Responses API format - Supports both string and array input formats - Converts to user messages - ExtractFeatures: Extracts routing-relevant features - Detects images, tools, long context, message count Type Migration: - Updated DetectScenario and DetectScenarioFromJSON to return string - Updated all test files to use string keys instead of config.Scenario - Fixed profileInfo struct to use map[string]*RoutePolicy - Updated scenario detection in server.go to use string type Test Results: - All 29 normalization tests passing - TestNormalizeAnthropicMessages: 7/7 passing - TestNormalizeOpenAIChat: 7/7 passing - TestNormalizeOpenAIResponses: 5/5 passing - TestMalformedRequestHandling: 5/5 passing - TestExtractFeatures: 5/5 passing Files modified: - internal/proxy/routing_normalize.go: Core normalization implementation - internal/proxy/scenario.go: Return string instead of config.Scenario - internal/proxy/server.go: Use string for scenario routing - internal/proxy/profile_proxy.go: Use map[string]*RoutePolicy - internal/proxy/*_test.go: Updated all tests to use string keys Next: T017 (DetectProtocol), T022 (token counting), T023-T025 (server integration) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…T022-T025) Completed all remaining tasks for User Story 1: T014 - Integration Tests: - Created tests/integration/routing_protocol_test.go - TestProtocolAgnosticRouting: Verifies equivalent requests via different protocols - TestProtocolDetectionPriority: Tests priority order (URL → header → body → default) - All 7 integration test cases passing T017 - DetectProtocol Function: - Implements 4-level priority detection: 1. URL path (/v1/messages → anthropic, /v1/chat/completions → openai_chat) 2. X-Zen-Client header (anthropic/claude/openai/openai_responses) 3. Body structure (claude model → anthropic, input field → openai_responses) 4. Default to openai_chat (most common) - Handles ambiguous /completions path (checks for input field) T022 - Token Counting: - Added estimateTokens() helper using tiktoken - Falls back to character-based estimation (~4 chars/token) - Integrated into all normalization functions - TokenCount field populated for all NormalizedMessage instances - Accurate long-context detection via ExtractFeatures T023-T025 - Server Integration: - Updated ProxyServer.ServeHTTP to detect protocol and normalize requests - Populates RequestContext.RequestFormat with detected protocol - Populates RequestContext.NormalizedRequest with normalized data - Error handling: logs normalization errors, continues with default routing - Middleware receives normalized request for routing decisions Type Migration (Web API): - Updated internal/web/api_profiles.go to use map[string]*RoutePolicy - Fixed profileResponse, createProfileRequest, updateProfileRequest types - Updated routingResponseToConfig to return RoutePolicy map Test Results: - Unit tests: 29/29 passing (normalization, malformed, features) - Integration tests: 7/7 passing (protocol detection, routing) - All existing tests still passing Files modified: - internal/proxy/routing_normalize.go: Added estimateTokens, DetectProtocol - internal/proxy/server.go: Integrated normalization in ServeHTTP - internal/web/api_profiles.go: Updated types for string-keyed routing - tests/integration/routing_protocol_test.go: Comprehensive integration tests User Story 1 Status: ✅ COMPLETE - Protocol-agnostic normalization working across all 3 protocols - Token counting accurate with tiktoken integration - Server integration complete with error handling - All tests passing (36 total test cases) Next: User Story 2 (Middleware-Driven Custom Routing) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Changed all TUI code to use string keys for routing maps - Updated switchToScenarioEditMsg.scenario from config.Scenario to string - Updated scenarioEditModel.scenario from config.Scenario to string - Updated scenarioEntry.scenario from config.Scenario to string - Updated knownScenarios to use string(config.Scenario) conversions - Fixed cmd/root.go scenarioRoutes map type to map[string]*proxy.ScenarioProviders - Fixed all test files to use string() conversions for scenario keys - Updated test data format from v14 to v15 (ProviderRoute array structure) - Updated TestConfigMigrationV11ToV12 to expect version 15 All tests passing (36 total).
- Fix identical expressions bug in fbmessenger.go (len(payload) - len(payload)) - Remove unnecessary nil checks for map length (S1009) - Fix error string punctuation (ST1005) - Use type conversion instead of struct literal (S1016) - Remove unnecessary nil check around range (S1031) - Fix possible nil pointer dereference in nlu_test.go (SA5011) - Fix unused value assignment in store_test.go (SA4006) - Remove ineffective assignment in form.go (SA4005) - Run go mod tidy to clean up dependencies All tests passing (36 total). All staticcheck warnings resolved.
…ecks) - Add Principle IX requiring staticcheck for Go and eslint for TypeScript - Code quality checks MUST be run after tests and before PR submission - All staticcheck warnings MUST be addressed (except intentional U1000) - All eslint errors MUST be fixed, warnings SHOULD be addressed - Update Development Workflow section to include quality check steps - Update release checklist to include quality checks Version: 1.4.0 → 1.5.0 (MINOR) Rationale: New principle added for code quality enforcement
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
Redesign scenario routing to be protocol-agnostic, middleware-extensible, and support open scenario namespaces.
Specification
This PR adds the specification for redesigning the scenario routing system to address current architectural limitations:
Current Problems
Target Architecture
RoutingDecisionandRoutingHintsAPIFiles Added
specs/020-scenario-routing-redesign/spec.md- Complete feature specificationspecs/020-scenario-routing-redesign/checklists/requirements.md- Quality validation checklistdocs/scenario-routing-architecture.md- Detailed architecture design documentNext Steps
/speckit.planto generate implementation plan/speckit.tasksto generate task breakdownRelated
Checklist