Unified Agent + reusable Go agent core.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: remove implicit model fallbacks

Lyric 09e638c7 79f30acc

+86 -21
-3
agent/engine.go
··· 135 135 agentCtx := NewContext(task, e.config.MaxSteps) 136 136 137 137 model := strings.TrimSpace(opts.Model) 138 - if model == "" { 139 - model = "gpt-5.2" 140 - } 141 138 142 139 runID := llmstats.RunIDFromContext(ctx) 143 140 if runID == "" {
+2 -4
cmd/mistermorph/consolecmd/local_runtime.go
··· 156 156 baseRegistry, mcpHost = buildConsoleBaseRegistry(context.Background(), logger) 157 157 sharedGuard = buildConsoleGuardFromViper(logger) 158 158 taskRuntimeOpts := taskruntime.BootstrapOptions{ 159 - AgentConfig: consoleAgentConfigFromViper(), 160 - DefaultModelFallback: "gpt-5.2", 159 + AgentConfig: consoleAgentConfigFromViper(), 161 160 } 162 161 execRuntime, err := taskruntime.Bootstrap(commonDeps, taskRuntimeOpts) 163 162 if err != nil { ··· 303 302 deps.Guard = func(_ *slog.Logger) *guard.Guard { return sharedGuard } 304 303 deps.RuntimeToolsConfig = toolsutil.LoadRuntimeToolsRegisterConfigFromViper() 305 304 rt, err := taskruntime.Bootstrap(deps, taskruntime.BootstrapOptions{ 306 - AgentConfig: consoleAgentConfigFromViper(), 307 - DefaultModelFallback: "gpt-5.2", 305 + AgentConfig: consoleAgentConfigFromViper(), 308 306 }) 309 307 if err != nil { 310 308 if mcpHost != nil {
+4 -3
cmd/mistermorph/skillscmd/skills_install_builtin.go
··· 784 784 } 785 785 model := strings.TrimSpace(route.ClientConfig.Model) 786 786 if model == "" { 787 - model = "gpt-5.2" 787 + return nil, "", fmt.Errorf("missing llm.model (required to review remote skills safely)") 788 788 } 789 789 cfg := route.ClientConfig 790 790 cfg.Model = model ··· 846 846 if client == nil { 847 847 return remoteSkillReview{}, fmt.Errorf("missing llm client") 848 848 } 849 - if strings.TrimSpace(model) == "" { 850 - model = "gpt-5.2" 849 + model = strings.TrimSpace(model) 850 + if model == "" { 851 + return remoteSkillReview{}, fmt.Errorf("missing llm.model (required to review remote skills safely)") 851 852 } 852 853 853 854 sys := strings.TrimSpace(`
+40 -1
cmd/mistermorph/skillscmd/skills_install_builtin_test.go
··· 1 1 package skillscmd 2 2 3 - import "testing" 3 + import ( 4 + "context" 5 + "strings" 6 + "testing" 7 + 8 + "github.com/quailyquaily/mistermorph/llm" 9 + "github.com/spf13/viper" 10 + ) 11 + 12 + type stubRemoteSkillReviewClient struct{} 13 + 14 + func (stubRemoteSkillReviewClient) Chat(context.Context, llm.Request) (llm.Result, error) { 15 + return llm.Result{}, nil 16 + } 4 17 5 18 func TestSkillsInstallCommandExposesYesFlagShorthand(t *testing.T) { 6 19 cmd := NewSkillsInstallBuiltinCmd() ··· 12 25 t.Fatalf("expected --yes shorthand to be -y, got %q", flag.Shorthand) 13 26 } 14 27 } 28 + 29 + func TestLLMClientForRemoteSkillReviewRequiresModel(t *testing.T) { 30 + viper.Reset() 31 + t.Cleanup(viper.Reset) 32 + viper.Set("llm.provider", "openai") 33 + viper.Set("llm.api_key", "sk-test") 34 + viper.Set("llm.model", "") 35 + 36 + _, _, err := llmClientForRemoteSkillReview() 37 + if err == nil { 38 + t.Fatal("expected missing llm.model error") 39 + } 40 + if !strings.Contains(err.Error(), "missing llm.model") { 41 + t.Fatalf("error = %q, want missing llm.model", err.Error()) 42 + } 43 + } 44 + 45 + func TestReviewRemoteSkillRequiresModel(t *testing.T) { 46 + _, err := reviewRemoteSkill(context.Background(), stubRemoteSkillReviewClient{}, "", "https://example.com/SKILL.md", []byte("body")) 47 + if err == nil { 48 + t.Fatal("expected missing llm.model error") 49 + } 50 + if !strings.Contains(err.Error(), "missing llm.model") { 51 + t.Fatalf("error = %q, want missing llm.model", err.Error()) 52 + } 53 + }
+2 -6
internal/channelruntime/taskruntime/runtime.go
··· 19 19 type ClientDecorator func(client llm.Client, route llmutil.ResolvedRoute) llm.Client 20 20 21 21 type BootstrapOptions struct { 22 - AgentConfig agent.Config 23 - ClientDecorator ClientDecorator 24 - DefaultModelFallback string 22 + AgentConfig agent.Config 23 + ClientDecorator ClientDecorator 25 24 } 26 25 27 26 type Runtime struct { ··· 100 99 mainClient = opts.ClientDecorator(mainClient, mainRoute) 101 100 } 102 101 mainModel := strings.TrimSpace(mainRoute.ClientConfig.Model) 103 - if mainModel == "" { 104 - mainModel = strings.TrimSpace(opts.DefaultModelFallback) 105 - } 106 102 107 103 planRoute, err := depsutil.ResolveLLMRouteFromCommon(d, llmutil.RoutePurposePlanCreate) 108 104 if err != nil {
+38 -4
internal/channelruntime/taskruntime/runtime_test.go
··· 52 52 return agent.DefaultPromptSpec(), nil, nil 53 53 }, 54 54 }, BootstrapOptions{ 55 - AgentConfig: agent.Config{MaxSteps: 2, ParseRetries: 0, ToolRepeatLimit: 2}, 56 - DefaultModelFallback: "gpt-5.2", 55 + AgentConfig: agent.Config{MaxSteps: 2, ParseRetries: 0, ToolRepeatLimit: 2}, 57 56 }) 58 57 if err != nil { 59 58 t.Fatalf("Bootstrap() error = %v", err) ··· 94 93 return agent.DefaultPromptSpec(), nil, nil 95 94 }, 96 95 }, BootstrapOptions{ 97 - AgentConfig: agent.Config{MaxSteps: 2, ParseRetries: 0, ToolRepeatLimit: 2}, 98 - DefaultModelFallback: "gpt-5.2", 96 + AgentConfig: agent.Config{MaxSteps: 2, ParseRetries: 0, ToolRepeatLimit: 2}, 99 97 }) 100 98 if err != nil { 101 99 t.Fatalf("Bootstrap() error = %v", err) ··· 178 176 t.Fatalf("system prompt missing memory snapshot: %q", systemPrompt) 179 177 } 180 178 } 179 + 180 + func TestBootstrapLeavesMainModelEmptyWhenRouteModelMissing(t *testing.T) { 181 + rt, err := Bootstrap(depsutil.CommonDependencies{ 182 + Logger: func() (*slog.Logger, error) { 183 + return slog.Default(), nil 184 + }, 185 + LogOptions: func() agent.LogOptions { 186 + return agent.LogOptions{} 187 + }, 188 + ResolveLLMRoute: func(string) (llmutil.ResolvedRoute, error) { 189 + return llmutil.ResolvedRoute{ 190 + ClientConfig: llmconfig.ClientConfig{ 191 + Provider: "openai", 192 + Model: "", 193 + }, 194 + }, nil 195 + }, 196 + CreateLLMClient: func(llmutil.ResolvedRoute) (llm.Client, error) { 197 + return &stubTaskRuntimeClient{}, nil 198 + }, 199 + Registry: func() *tools.Registry { 200 + return tools.NewRegistry() 201 + }, 202 + PromptSpec: func(_ context.Context, _ *slog.Logger, _ agent.LogOptions, _ string, _ llm.Client, _ string, _ []string) (agent.PromptSpec, []string, error) { 203 + return agent.DefaultPromptSpec(), nil, nil 204 + }, 205 + }, BootstrapOptions{ 206 + AgentConfig: agent.Config{MaxSteps: 2, ParseRetries: 0, ToolRepeatLimit: 2}, 207 + }) 208 + if err != nil { 209 + t.Fatalf("Bootstrap() error = %v", err) 210 + } 211 + if rt.MainModel != "" { 212 + t.Fatalf("MainModel = %q, want empty", rt.MainModel) 213 + } 214 + }