fix(agent): use DB provider_type for SOUL echo and strict mode detection

- Add providerTypeOf() to extract provider_type via type assertion
  (e.g. "chatgpt_oauth") instead of config name (user-set "openai")
- Exclude "compat" providers (openai_compat → OpenRouter/DeepSeek/Groq)
  from strict mode and SOUL echo — they proxy to non-OpenAI models
- Fix isOpenAIStrict matching openai_compat incorrectly
This commit is contained in:
viettranx committed 2026-03-31 23:38:48 +07:00
1 parent 2a9400949b
commit 2092c50a04
5 files changed
+39 -7

No files matched your search

+1 -1
View File
@@ -252,7 +252,7 @@ func (l *Loop) buildMessages(ctx context.Context, history []providers.Message, s
SandboxWorkspaceAccess: l.sandboxWorkspaceAccess,
ShellDenyGroups: l.shellDenyGroups,
SelfEvolve: l.selfEvolve,
ProviderType: l.provider.Name(),
ProviderType: providerTypeOf(l.provider),
CredentialCLIContext: l.buildCredentialCLIContext(ctx),
IsBootstrap: hadBootstrap && l.agentType != store.AgentTypePredefined,
})
+1 -1
View File
@@ -108,7 +108,7 @@ func (l *Loop) runMemoryFlush(ctx context.Context, sessionKey string, settings *
Mode: PromptMinimal,
ToolNames: l.filteredToolNames(),
HasMemory: l.hasMemory,
ProviderType: l.provider.Name(),
ProviderType: providerTypeOf(l.provider),
})
systemPrompt += "\n\n" + settings.SystemPrompt
+15
View File
@@ -6,10 +6,25 @@ import (
"strings"
"github.com/nextlevelbuilder/goclaw/internal/bootstrap"
"github.com/nextlevelbuilder/goclaw/internal/providers"
"github.com/nextlevelbuilder/goclaw/internal/store"
"github.com/nextlevelbuilder/goclaw/internal/tools"
)
// providerTypeOf extracts the DB provider_type (e.g. "chatgpt_oauth", "codex")
// from a Provider. Falls back to Name() if the provider doesn't expose ProviderType().
func providerTypeOf(p providers.Provider) string {
type providerTyper interface {
ProviderType() string
}
if pt, ok := p.(providerTyper); ok {
if t := pt.ProviderType(); t != "" {
return t
}
}
return p.Name()
}
// PromptMode controls which system prompt sections are included.
// Matches TS PromptMode type in system-prompt.ts.
type PromptMode string
+9 -2
View File
@@ -374,10 +374,17 @@ func buildPersonaReminder(files []bootstrap.ContextFile, agentType, providerType
// needsSOULEcho returns true for providers that benefit from recency-zone personality echo.
// GPT models have strong recency bias and tend to lose persona in long prompts.
// Matches first-party OpenAI (chatgpt_oauth) and Codex only — not compat proxies.
func needsSOULEcho(providerType string) bool {
switch strings.ToLower(providerType) {
case "openai", "codex":
lower := strings.ToLower(providerType)
if strings.Contains(lower, "compat") {
return false // openai_compat routes to non-OpenAI models
}
switch {
case lower == "openai" || lower == "codex":
return true
case strings.Contains(lower, "chatgpt"):
return true // chatgpt_oauth, chatgpt_plus, etc.
}
return false
}
+13 -3
View File
@@ -79,11 +79,21 @@ func profileForProvider(name string) SchemaProfile {
}
// isOpenAIStrict returns true for providers known to support strict tool mode.
// Only first-party OpenAI and Codex are safe — third-party proxies (OpenRouter,
// DeepSeek, Groq, DashScope, etc.) may reject nullable unions or the strict flag.
// Matches first-party OpenAI (including chatgpt_oauth) and Codex.
// Explicitly excludes openai_compat (proxy for OpenRouter, DeepSeek, Groq, etc.).
func isOpenAIStrict(name string) bool {
lower := strings.ToLower(name)
return lower == "openai" || lower == "codex"
// Exclude compat/proxy providers first — they route to non-OpenAI models.
if strings.Contains(lower, "compat") {
return false
}
switch {
case lower == "openai" || lower == "codex":
return true
case strings.Contains(lower, "chatgpt"):
return true // chatgpt_oauth, chatgpt_plus, etc.
}
return false
}
// isGeminiName matches config names ("gemini", "gemini-flash") and