@@ -21,6 +21,7 @@ var templatesFS embed.FS
2121// Server represents the web server for the chat interface
2222type Server struct {
2323 agent * agent.Agent
24+ providers []agent.LLMProvider
2425 templates * template.Template
2526 eventChan chan SSEvent
2627 ctx context.Context
@@ -33,14 +34,15 @@ type SSEvent struct {
3334}
3435
3536// NewServer creates a new web server instance
36- func NewServer (ctx context.Context , ag * agent.Agent ) (* Server , error ) {
37+ func NewServer (ctx context.Context , ag * agent.Agent , providers []agent. LLMProvider ) (* Server , error ) {
3738 tmpl , err := template .ParseFS (templatesFS , "templates/*.html" )
3839 if err != nil {
3940 return nil , fmt .Errorf ("failed to parse templates: %w" , err )
4041 }
4142
4243 return & Server {
4344 agent : ag ,
45+ providers : providers ,
4446 templates : tmpl ,
4547 eventChan : make (chan SSEvent , 100 ),
4648 ctx : ctx ,
@@ -57,6 +59,9 @@ func (s *Server) Start(addr string) error {
5759 mux .HandleFunc ("POST /tool/deny" , s .handleToolDeny )
5860 mux .HandleFunc ("GET /events" , s .handleSSE )
5961 mux .HandleFunc ("POST /reset" , s .handleReset )
62+ mux .HandleFunc ("GET /api/models" , s .handleListModels )
63+ mux .HandleFunc ("GET /api/model" , s .handleGetModel )
64+ mux .HandleFunc ("POST /api/model" , s .handleSetModel )
6065
6166 server := & http.Server {
6267 Addr : addr ,
@@ -260,6 +265,65 @@ func (s *Server) send(event SSEvent) {
260265 }
261266}
262267
268+ func (s * Server ) handleListModels (w http.ResponseWriter , r * http.Request ) {
269+ var allModels []agent.ModelInfo
270+
271+ for _ , p := range s .providers {
272+ models , err := p .ListModels (r .Context ())
273+ if err != nil {
274+ log .Printf ("[MODELS] Failed to list %s models: %v" , p .Name (), err )
275+ continue
276+ }
277+ allModels = append (allModels , models ... )
278+ }
279+
280+ w .Header ().Set ("Content-Type" , "application/json" )
281+ if err := json .NewEncoder (w ).Encode (allModels ); err != nil {
282+ log .Printf ("[ERROR] Failed to encode models response: %v" , err )
283+ }
284+ }
285+
286+ func (s * Server ) handleGetModel (w http.ResponseWriter , r * http.Request ) {
287+ w .Header ().Set ("Content-Type" , "application/json" )
288+ resp := map [string ]string {"model" : s .agent .GetModel ()}
289+ if err := json .NewEncoder (w ).Encode (resp ); err != nil {
290+ log .Printf ("[ERROR] Failed to encode model response: %v" , err )
291+ }
292+ }
293+
294+ func (s * Server ) handleSetModel (w http.ResponseWriter , r * http.Request ) {
295+ r .Body = http .MaxBytesReader (w , r .Body , 1 << 20 )
296+
297+ var req struct {
298+ Provider string `json:"provider"`
299+ Model string `json:"model"`
300+ }
301+ if err := json .NewDecoder (r .Body ).Decode (& req ); err != nil {
302+ http .Error (w , "Invalid request body" , http .StatusBadRequest )
303+ return
304+ }
305+ if req .Model == "" {
306+ http .Error (w , "Model is required" , http .StatusBadRequest )
307+ return
308+ }
309+
310+ for _ , p := range s .providers {
311+ if p .Name () == req .Provider {
312+ s .agent .SetModel (p , req .Model )
313+ log .Printf ("[MODEL] Switched to %s/%s" , req .Provider , req .Model )
314+
315+ w .Header ().Set ("Content-Type" , "application/json" )
316+ resp := map [string ]string {"model" : req .Model , "provider" : req .Provider }
317+ if err := json .NewEncoder (w ).Encode (resp ); err != nil {
318+ log .Printf ("[ERROR] Failed to encode set model response: %v" , err )
319+ }
320+ return
321+ }
322+ }
323+
324+ http .Error (w , fmt .Sprintf ("Unknown provider: %s" , req .Provider ), http .StatusBadRequest )
325+ }
326+
263327func (s * Server ) renderMessage (role , content , toolID string , tool * agent.ToolRequest ) string {
264328 data := map [string ]interface {}{
265329 "Role" : role ,
0 commit comments