on main help sign in
refactor: adjustment based on fantasy api changes
commit7d0a6ad42d5551b2212af0a78966357d8269f636 authorAndrey Nering <andreynering@users.noreply.github.com> dateWed 22 Oct 2025, 14:57 (1 year ago) parent47fe8fc
6 files changed+62−50
internal/agent/agent_tool.go+2−2 internal/agent/common_test.go+22−10 internal/agent/coordinator.go+29−30 internal/app/app.go+5−4 internal/tui/page/chat/chat.go+3−3 internal/tui/tui.go+1−1
internal/agent/agent_tool.go+2−2
@@ -25,7 +25,7 @@ const (
2525 AgentToolName = "agent"
2626)
2727
28−func (c *coordinator) agentTool() (fantasy.AgentTool, error) {
28+func (c *coordinator) agentTool(ctx context.Context) (fantasy.AgentTool, error) {
2929 agentCfg, ok := c.cfg.Agents[config.AgentTask]
3030 if !ok {
3131 return nil, errors.New("task agent not configured")
@@ -35,7 +35,7 @@ func (c *coordinator) agentTool() (fantasy.AgentTool, error) {
3535 return nil, err
3636 }
3737
38− agent, err := c.buildAgent(prompt, agentCfg)
38+ agent, err := c.buildAgent(ctx, prompt, agentCfg)
3939 if err != nil {
4040 return nil, err
4141 }
internal/agent/common_test.go+22−10
@@ -47,43 +47,55 @@ type modelPair struct {
4747}
4848
4949func anthropicBuilder(model string) builderFunc {
50− return func(_ *testing.T, r *recorder.Recorder) (fantasy.LanguageModel, error) {
51− provider := anthropic.New(
50+ return func(t *testing.T, r *recorder.Recorder) (fantasy.LanguageModel, error) {
51+ provider, err := anthropic.New(
5252 anthropic.WithAPIKey(os.Getenv("CRUSH_ANTHROPIC_API_KEY")),
5353 anthropic.WithHTTPClient(&http.Client{Transport: r}),
5454 )
55− return provider.LanguageModel(model)
55+ if err != nil {
56+ return nil, err
57+ }
58+ return provider.LanguageModel(t.Context(), model)
5659 }
5760}
5861
5962func openaiBuilder(model string) builderFunc {
60− return func(_ *testing.T, r *recorder.Recorder) (fantasy.LanguageModel, error) {
61− provider := openai.New(
63+ return func(t *testing.T, r *recorder.Recorder) (fantasy.LanguageModel, error) {
64+ provider, err := openai.New(
6265 openai.WithAPIKey(os.Getenv("CRUSH_OPENAI_API_KEY")),
6366 openai.WithHTTPClient(&http.Client{Transport: r}),
6467 )
65− return provider.LanguageModel(model)
68+ if err != nil {
69+ return nil, err
70+ }
71+ return provider.LanguageModel(t.Context(), model)
6672 }
6773}
6874
6975func openRouterBuilder(model string) builderFunc {
7076 return func(t *testing.T, r *recorder.Recorder) (fantasy.LanguageModel, error) {
71− provider := openrouter.New(
77+ provider, err := openrouter.New(
7278 openrouter.WithAPIKey(os.Getenv("CRUSH_OPENROUTER_API_KEY")),
7379 openrouter.WithHTTPClient(&http.Client{Transport: r}),
7480 )
75− return provider.LanguageModel(model)
81+ if err != nil {
82+ return nil, err
83+ }
84+ return provider.LanguageModel(t.Context(), model)
7685 }
7786}
7887
7988func zAIBuilder(model string) builderFunc {
8089 return func(t *testing.T, r *recorder.Recorder) (fantasy.LanguageModel, error) {
81− provider := openaicompat.New(
90+ provider, err := openaicompat.New(
8291 openaicompat.WithBaseURL("https://api.z.ai/api/coding/paas/v4"),
8392 openaicompat.WithAPIKey(os.Getenv("CRUSH_ZAI_API_KEY")),
8493 openaicompat.WithHTTPClient(&http.Client{Transport: r}),
8594 )
86− return provider.LanguageModel(model)
95+ if err != nil {
96+ return nil, err
97+ }
98+ return provider.LanguageModel(t.Context(), model)
8799 }
88100}
89101
internal/agent/coordinator.go+29−30
@@ -45,7 +45,7 @@ type Coordinator interface {
4545 ClearQueue(sessionID string)
4646 Summarize(context.Context, string) error
4747 Model() Model
48− UpdateModels() error
48+ UpdateModels(ctx context.Context) error
4949}
5050
5151type coordinator struct {
@@ -61,6 +61,7 @@ type coordinator struct {
6161}
6262
6363func NewCoordinator(
64+ ctx context.Context,
6465 cfg *config.Config,
6566 sessions session.Service,
6667 messages message.Service,
@@ -89,7 +90,7 @@ func NewCoordinator(
8990 return nil, err
9091 }
9192
92− agent, err := c.buildAgent(prompt, agentCfg)
93+ agent, err := c.buildAgent(ctx, prompt, agentCfg)
9394 if err != nil {
9495 return nil, err
9596 }
@@ -255,8 +256,8 @@ func mergeCallOptions(model Model, tp catwalk.Type) (fantasy.ProviderOptions, *f
255256 return modelOptions, temp, topP, topK, freqPenalty, presPenalty
256257}
257258
258−func (c *coordinator) buildAgent(prompt *prompt.Prompt, agent config.Agent) (SessionAgent, error) {
259− large, small, err := c.buildAgentModels()
259+func (c *coordinator) buildAgent(ctx context.Context, prompt *prompt.Prompt, agent config.Agent) (SessionAgent, error) {
260+ large, small, err := c.buildAgentModels(ctx)
260261 if err != nil {
261262 return nil, err
262263 }
@@ -266,17 +267,17 @@ func (c *coordinator) buildAgent(prompt *prompt.Prompt, agent config.Agent) (Ses
266267 return nil, err
267268 }
268269
269− tools, err := c.buildTools(agent)
270+ tools, err := c.buildTools(ctx, agent)
270271 if err != nil {
271272 return nil, err
272273 }
273274 return NewSessionAgent(SessionAgentOptions{large, small, systemPrompt, c.cfg.Options.DisableAutoSummarize, c.sessions, c.messages, tools}), nil
274275}
275276
276−func (c *coordinator) buildTools(agent config.Agent) ([]fantasy.AgentTool, error) {
277+func (c *coordinator) buildTools(ctx context.Context, agent config.Agent) ([]fantasy.AgentTool, error) {
277278 var allTools []fantasy.AgentTool
278279 if slices.Contains(agent.AllowedTools, AgentToolName) {
279− agentTool, err := c.agentTool()
280+ agentTool, err := c.agentTool(ctx)
280281 if err != nil {
281282 return nil, err
282283 }
@@ -334,7 +335,7 @@ func (c *coordinator) buildTools(agent config.Agent) ([]fantasy.AgentTool, error
334335}
335336
336337// TODO: when we support multiple agents we need to change this so that we pass in the agent specific model config
337−func (c *coordinator) buildAgentModels() (Model, Model, error) {
338+func (c *coordinator) buildAgentModels(ctx context.Context) (Model, Model, error) {
338339 largeModelCfg, ok := c.cfg.Models[config.SelectedModelTypeLarge]
339340 if !ok {
340341 return Model{}, Model{}, errors.New("large model not selected")
@@ -386,11 +387,11 @@ func (c *coordinator) buildAgentModels() (Model, Model, error) {
386387 return Model{}, Model{}, errors.New("snall model not found in provider config")
387388 }
388389
389− largeModel, err := largeProvider.LanguageModel(largeModelCfg.Model)
390+ largeModel, err := largeProvider.LanguageModel(ctx, largeModelCfg.Model)
390391 if err != nil {
391392 return Model{}, Model{}, err
392393 }
393− smallModel, err := smallProvider.LanguageModel(smallModelCfg.Model)
394+ smallModel, err := smallProvider.LanguageModel(ctx, smallModelCfg.Model)
394395 if err != nil {
395396 return Model{}, Model{}, err
396397 }
@@ -406,7 +407,7 @@ func (c *coordinator) buildAgentModels() (Model, Model, error) {
406407 }, nil
407408}
408409
409−func (c *coordinator) buildAnthropicProvider(baseURL, apiKey string, headers map[string]string) fantasy.Provider {
410+func (c *coordinator) buildAnthropicProvider(baseURL, apiKey string, headers map[string]string) (fantasy.Provider, error) {
410411 hasBearerAuth := false
411412 for key := range headers {
412413 if strings.ToLower(key) == "authorization" {
@@ -441,7 +442,7 @@ func (c *coordinator) buildAnthropicProvider(baseURL, apiKey string, headers map
441442 return anthropic.New(opts...)
442443}
443444
444−func (c *coordinator) buildOpenaiProvider(baseURL, apiKey string, headers map[string]string) fantasy.Provider {
445+func (c *coordinator) buildOpenaiProvider(baseURL, apiKey string, headers map[string]string) (fantasy.Provider, error) {
445446 opts := []openai.Option{
446447 openai.WithAPIKey(apiKey),
447448 openai.WithUseResponsesAPI(),
@@ -459,7 +460,7 @@ func (c *coordinator) buildOpenaiProvider(baseURL, apiKey string, headers map[st
459460 return openai.New(opts...)
460461}
461462
462−func (c *coordinator) buildOpenrouterProvider(_, apiKey string, headers map[string]string) fantasy.Provider {
463+func (c *coordinator) buildOpenrouterProvider(_, apiKey string, headers map[string]string) (fantasy.Provider, error) {
463464 opts := []openrouter.Option{
464465 openrouter.WithAPIKey(apiKey),
465466 }
@@ -473,7 +474,7 @@ func (c *coordinator) buildOpenrouterProvider(_, apiKey string, headers map[stri
473474 return openrouter.New(opts...)
474475}
475476
476−func (c *coordinator) buildOpenaiCompatProvider(baseURL, apiKey string, headers map[string]string) fantasy.Provider {
477+func (c *coordinator) buildOpenaiCompatProvider(baseURL, apiKey string, headers map[string]string) (fantasy.Provider, error) {
477478 opts := []openaicompat.Option{
478479 openaicompat.WithBaseURL(baseURL),
479480 openaicompat.WithAPIKey(apiKey),
@@ -489,7 +490,7 @@ func (c *coordinator) buildOpenaiCompatProvider(baseURL, apiKey string, headers
489490 return openaicompat.New(opts...)
490491}
491492
492−func (c *coordinator) buildAzureProvider(baseURL, apiKey string, headers map[string]string, options map[string]string) fantasy.Provider {
493+func (c *coordinator) buildAzureProvider(baseURL, apiKey string, headers map[string]string, options map[string]string) (fantasy.Provider, error) {
493494 opts := []azure.Option{
494495 azure.WithBaseURL(baseURL),
495496 azure.WithAPIKey(apiKey),
@@ -511,7 +512,7 @@ func (c *coordinator) buildAzureProvider(baseURL, apiKey string, headers map[str
511512 return azure.New(opts...)
512513}
513514
514−func (c *coordinator) buildGoogleProvider(baseURL, apiKey string, headers map[string]string) fantasy.Provider {
515+func (c *coordinator) buildGoogleProvider(baseURL, apiKey string, headers map[string]string) (fantasy.Provider, error) {
515516 opts := []google.Option{
516517 google.WithBaseURL(baseURL),
517518 google.WithGeminiAPIKey(apiKey),
@@ -526,7 +527,7 @@ func (c *coordinator) buildGoogleProvider(baseURL, apiKey string, headers map[st
526527 return google.New(opts...)
527528}
528529
529−func (c *coordinator) buildGoogleVertexProvider(headers map[string]string, options map[string]string) fantasy.Provider {
530+func (c *coordinator) buildGoogleVertexProvider(headers map[string]string, options map[string]string) (fantasy.Provider, error) {
530531 opts := []google.Option{}
531532 if c.cfg.Options.Debug {
532533 httpClient := log.NewHTTPClient()
@@ -574,27 +575,25 @@ func (c *coordinator) buildProvider(providerCfg config.ProviderConfig, model con
574575 // TODO: make sure we have
575576 apiKey, _ := c.cfg.Resolve(providerCfg.APIKey)
576577 baseURL, _ := c.cfg.Resolve(providerCfg.BaseURL)
577− var provider fantasy.Provider
578+
578579 switch providerCfg.Type {
579580 case openai.Name:
580− provider = c.buildOpenaiProvider(baseURL, apiKey, headers)
581+ return c.buildOpenaiProvider(baseURL, apiKey, headers)
581582 case anthropic.Name:
582− provider = c.buildAnthropicProvider(baseURL, apiKey, headers)
583+ return c.buildAnthropicProvider(baseURL, apiKey, headers)
583584 case openrouter.Name:
584− provider = c.buildOpenrouterProvider(baseURL, apiKey, headers)
585+ return c.buildOpenrouterProvider(baseURL, apiKey, headers)
585586 case azure.Name:
586− provider = c.buildAzureProvider(baseURL, apiKey, headers, providerCfg.ExtraParams)
587+ return c.buildAzureProvider(baseURL, apiKey, headers, providerCfg.ExtraParams)
587588 case google.Name:
588− provider = c.buildGoogleProvider(baseURL, apiKey, headers)
589− // this is not in fantasy since its just the google provider with extra stuff
589+ return c.buildGoogleProvider(baseURL, apiKey, headers)
590590 case "vertexai":
591− provider = c.buildGoogleVertexProvider(headers, providerCfg.ExtraParams)
591+ return c.buildGoogleVertexProvider(headers, providerCfg.ExtraParams)
592592 case openaicompat.Name:
593− provider = c.buildOpenaiCompatProvider(baseURL, apiKey, headers)
593+ return c.buildOpenaiCompatProvider(baseURL, apiKey, headers)
594594 default:
595595 return nil, errors.New("provider type not supported")
596596 }
597− return provider, nil
598597}
599598
600599func (c *coordinator) Cancel(sessionID string) {
@@ -621,9 +620,9 @@ func (c *coordinator) Model() Model {
621620 return c.currentAgent.Model()
622621}
623622
624−func (c *coordinator) UpdateModels() error {
623+func (c *coordinator) UpdateModels(ctx context.Context) error {
625624 // build the models again so we make sure we get the latest config
626− large, small, err := c.buildAgentModels()
625+ large, small, err := c.buildAgentModels(ctx)
627626 if err != nil {
628627 return err
629628 }
@@ -634,7 +633,7 @@ func (c *coordinator) UpdateModels() error {
634633 return errors.New("coder agent not configured")
635634 }
636635
637− tools, err := c.buildTools(agentCfg)
636+ tools, err := c.buildTools(ctx, agentCfg)
638637 if err != nil {
639638 return err
640639 }
internal/app/app.go+5−4
@@ -87,7 +87,7 @@ func New(ctx context.Context, conn *sql.DB, cfg *config.Config) (*App, error) {
8787
8888 // TODO: remove the concept of agent config, most likely.
8989 if cfg.IsConfigured() {
90− if err := app.InitCoderAgent(); err != nil {
90+ if err := app.InitCoderAgent(ctx); err != nil {
9191 return nil, fmt.Errorf("failed to initialize coder agent: %w", err)
9292 }
9393 } else {
@@ -207,8 +207,8 @@ func (app *App) RunNonInteractive(ctx context.Context, prompt string, quiet bool
207207 }
208208}
209209
210−func (app *App) UpdateAgentModel() error {
211− return app.AgentCoordinator.UpdateModels()
210+func (app *App) UpdateAgentModel(ctx context.Context) error {
211+ return app.AgentCoordinator.UpdateModels(ctx)
212212}
213213
214214func (app *App) setupEvents() {
@@ -262,13 +262,14 @@ func setupSubscriber[T any](
262262 })
263263}
264264
265−func (app *App) InitCoderAgent() error {
265+func (app *App) InitCoderAgent(ctx context.Context) error {
266266 coderAgentCfg := app.config.Agents[config.AgentCoder]
267267 if coderAgentCfg.ID == "" {
268268 return fmt.Errorf("coder agent configuration is missing")
269269 }
270270 var err error
271271 app.AgentCoordinator, err = agent.NewCoordinator(
272+ ctx,
272273 app.config,
273274 app.Sessions,
274275 app.Messages,
internal/tui/page/chat/chat.go+3−3
@@ -346,7 +346,7 @@ func (p *chatPage) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
346346 p.splashFullScreen = true
347347 return p, p.SetSize(p.width, p.height)
348348 }
349− err := p.app.InitCoderAgent()
349+ err := p.app.InitCoderAgent(context.TODO())
350350 if err != nil {
351351 return p, util.ReportError(err)
352352 }
@@ -538,7 +538,7 @@ func (p *chatPage) toggleThinking() tea.Cmd {
538538 cfg.Models[agentCfg.Model] = currentModel
539539
540540 // Update the agent with the new configuration
541− if err := p.app.UpdateAgentModel(); err != nil {
541+ if err := p.app.UpdateAgentModel(context.TODO()); err != nil {
542542 return util.InfoMsg{
543543 Type: util.InfoTypeError,
544544 Msg: "Failed to update thinking mode: " + err.Error(),
@@ -589,7 +589,7 @@ func (p *chatPage) handleReasoningEffortSelected(effort string) tea.Cmd {
589589 }
590590
591591 // Update the agent with the new configuration
592− if err := p.app.UpdateAgentModel(); err != nil {
592+ if err := p.app.UpdateAgentModel(context.TODO()); err != nil {
593593 return util.InfoMsg{
594594 Type: util.InfoTypeError,
595595 Msg: "Failed to update reasoning effort: " + err.Error(),
internal/tui/tui.go+1−1
@@ -204,7 +204,7 @@ func (a *appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
204204 config.Get().UpdatePreferredModel(msg.ModelType, msg.Model)
205205
206206 // Update the agent with the new model/provider configuration
207− if err := a.app.UpdateAgentModel(); err != nil {
207+ if err := a.app.UpdateAgentModel(context.TODO()); err != nil {
208208 return a, util.ReportError(fmt.Errorf("model changed to %s but failed to update agent: %v", msg.Model.Model, err))
209209 }
210210