ci / vet-and-test (pull_request) Successful in 39s
Why: workspace writes had no checkpoint, and a 5xx before any output stopped the turn instead of trying the next configured model. Evidence: GOWORK=off go test ./internal/runtime/ ./internal/runmgr/ ./internal/tools/ ./internal/settings/ ./internal/server/ ./internal/app/ Impact: models.chat.fallbacks defaults to empty, so existing runs keep their model. Rewind restores only tracked writes and appends a system note. Usage records the model that served. Refs: feature/durable-rewind Co-authored-by: Cursor <cursoragent@cursor.com>
71 lines
2.1 KiB
Go
71 lines
2.1 KiB
Go
package runtime
|
||
|
||
import (
|
||
"strings"
|
||
|
||
core "agent-system-core"
|
||
)
|
||
|
||
// 模型路由解析(4.7 / 4.9 覆盖链):设置层 defaults → system → user → project,
|
||
// 画像 ModelRoute 为会话内最高层覆盖(kind 为空回落设置层主模型)。
|
||
// 端点与密钥按 kind 独立配置,轻量档空则回落主档。
|
||
|
||
// ResolvedModel 是一次路由解析的结果。
|
||
type ResolvedModel struct {
|
||
Kind string // chat | lightweight
|
||
Model string
|
||
Base string
|
||
Key string
|
||
}
|
||
|
||
// ResolveChatModel 解析主对话模型(画像 route > 设置层)。
|
||
func ResolveChatModel(prof core.AgentProfile, eff core.EffectiveSettings) ResolvedModel {
|
||
m := eff.GetString("models.chat.model", "")
|
||
if prof.Model.Chat != "" {
|
||
m = prof.Model.Chat
|
||
}
|
||
return ResolvedModel{Kind: "chat", Model: m,
|
||
Base: eff.GetString("models.chat.baseUrl", ""),
|
||
Key: eff.GetString("models.chat.apiKey", "")}
|
||
}
|
||
|
||
// ChatFallbacks 解析 models.chat.fallbacks。默认空,不改变现有模型选择。
|
||
func ChatFallbacks(eff core.EffectiveSettings) []string {
|
||
raw := strings.TrimSpace(eff.GetString("models.chat.fallbacks", ""))
|
||
if raw == "" {
|
||
return nil
|
||
}
|
||
var out []string
|
||
seen := map[string]bool{}
|
||
for _, part := range strings.Split(raw, ",") {
|
||
name := strings.TrimSpace(part)
|
||
if name == "" || seen[name] {
|
||
continue
|
||
}
|
||
seen[name] = true
|
||
out = append(out, name)
|
||
}
|
||
return out
|
||
}
|
||
|
||
// ResolveLightweightModel 解析轻量模型:画像 route > 设置层轻量档 > 回落主档。
|
||
func ResolveLightweightModel(prof core.AgentProfile, eff core.EffectiveSettings) ResolvedModel {
|
||
m := eff.GetString("models.lightweight.model", "")
|
||
base := eff.GetString("models.lightweight.baseUrl", "")
|
||
key := eff.GetString("models.lightweight.apiKey", "")
|
||
if prof.Model.Lightweight != "" {
|
||
m = prof.Model.Lightweight
|
||
}
|
||
if m == "" || base == "" {
|
||
// 回落主档(模型与端点分别回落,允许轻量仅覆盖模型名)。
|
||
chat := ResolveChatModel(prof, eff)
|
||
if m == "" {
|
||
m = chat.Model
|
||
}
|
||
if base == "" {
|
||
base, key = chat.Base, chat.Key
|
||
}
|
||
}
|
||
return ResolvedModel{Kind: "lightweight", Model: m, Base: base, Key: key}
|
||
}
|