11import json
2+ from typing import Optional
23
34import structlog
45from fastapi import APIRouter , HTTPException , Request
56
6- from codegate .clients .clients import ClientType
77from codegate .clients .detector import DetectClient
8- from codegate .extract_snippets .body_extractor import BodyCodeSnippetExtractorError
9- from codegate .extract_snippets .factory import BodyCodeExtractorFactory
8+ from codegate .muxing import models as mux_models
109from codegate .muxing import rulematcher
1110from codegate .muxing .adapter import BodyAdapter , ResponseAdapter
11+ from codegate .providers .fim_analyzer import FIMAnalyzer
1212from codegate .providers .registry import ProviderRegistry
1313from codegate .workspaces .crud import WorkspaceCrud
1414
@@ -39,40 +39,20 @@ def get_routes(self) -> APIRouter:
3939 def _ensure_path_starts_with_slash (self , path : str ) -> str :
4040 return path if path .startswith ("/" ) else f"/{ path } "
4141
42- def _extract_request_filenames (self , detected_client : ClientType , data : dict ) -> set [str ]:
42+ async def _get_model_route (
43+ self , thing_to_match : mux_models .ThingToMatchMux
44+ ) -> Optional [rulematcher .ModelRoute ]:
4345 """
44- Extract filenames from the request data .
46+ Get the model route for the given things_to_match .
4547 """
46- try :
47- body_extractor = BodyCodeExtractorFactory .create_snippet_extractor (detected_client )
48- return body_extractor .extract_unique_filenames (data )
49- except BodyCodeSnippetExtractorError as e :
50- logger .error (f"Error extracting filenames from request: { e } " )
51- return set ()
52-
53- async def _get_model_routes (self , filenames : set [str ]) -> list [rulematcher .ModelRoute ]:
54- """
55- Get the model routes for the given filenames.
56- """
57- model_routes = []
5848 mux_registry = await rulematcher .get_muxing_rules_registry ()
5949 try :
60- # Try to get a catch_all route
61- single_model_route = await mux_registry .get_match_for_active_workspace (
62- thing_to_match = None
63- )
64- model_routes .append (single_model_route )
65-
66- # Get the model routes for each filename
67- for filename in filenames :
68- model_route = await mux_registry .get_match_for_active_workspace (
69- thing_to_match = filename
70- )
71- model_routes .append (model_route )
50+ # Try to get a model route for the active workspace
51+ model_route = await mux_registry .get_match_for_active_workspace (thing_to_match )
52+ return model_route
7253 except Exception as e :
7354 logger .error (f"Error getting active workspace muxes: { e } " )
7455 raise HTTPException (str (e ), status_code = 404 )
75- return model_routes
7656
7757 def _setup_routes (self ):
7858
@@ -88,34 +68,45 @@ async def route_to_dest_provider(
8868 1. Get destination provider from DB and active workspace.
8969 2. Map the request body to the destination provider format.
9070 3. Run pipeline. Selecting the correct destination provider.
91- 4. Transmit the response back to the client in the correct format.
71+ 4. Transmit the response back to the client in OpenAI format.
9272 """
9373
9474 body = await request .body ()
9575 data = json .loads (body )
76+ is_fim_request = FIMAnalyzer .is_fim_request (rest_of_path , data )
77+
78+ # 1. Get destination provider from DB and active workspace.
79+ thing_to_match = mux_models .ThingToMatchMux (
80+ body = data ,
81+ url_request_path = rest_of_path ,
82+ is_fim_request = is_fim_request ,
83+ client_type = request .state .detected_client ,
84+ )
85+ model_route = await self ._get_model_route (thing_to_match )
86+ if not model_route :
87+ raise HTTPException (
88+ "No matching rule found for the active workspace" , status_code = 404
89+ )
9690
97- filenames_in_data = self ._extract_request_filenames (request .state .detected_client , data )
98- logger .info (f"Extracted filenames from request: { filenames_in_data } " )
99-
100- model_routes = await self ._get_model_routes (filenames_in_data )
101- if not model_routes :
102- raise HTTPException ("No rule found for the active workspace" , status_code = 404 )
103-
104- # We still need some logic here to handle the case where we have multiple model routes.
105- # For the moment since we match all only pick the first.
106- model_route = model_routes [0 ]
91+ logger .info (
92+ "Muxing request routed to destination provider" ,
93+ model = model_route .model .name ,
94+ provider_type = model_route .endpoint .provider_type ,
95+ provider_name = model_route .endpoint .name ,
96+ )
10797
108- # Parse the input data and map it to the destination provider format
98+ # 2. Map the request body to the destination provider format.
10999 rest_of_path = self ._ensure_path_starts_with_slash (rest_of_path )
110100 new_data = self ._body_adapter .map_body_to_dest (model_route , data )
101+
102+ # 3. Run pipeline. Selecting the correct destination provider.
111103 provider = self ._provider_registry .get_provider (model_route .endpoint .provider_type )
112104 api_key = model_route .auth_material .auth_blob
113-
114- # Send the request to the destination provider. It will run the pipeline
115105 response = await provider .process_request (
116- new_data , api_key , rest_of_path , request .state .detected_client
106+ new_data , api_key , is_fim_request , request .state .detected_client
117107 )
118- # Format the response to the client always using the OpenAI format
108+
109+ # 4. Transmit the response back to the client in OpenAI format.
119110 return self ._response_adapter .format_response_to_client (
120111 response , model_route .endpoint .provider_type
121112 )
0 commit comments