Files
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

253 lines
8.9 KiB
Go

package agentruntime
import (
"encoding/json"
"testing"
)
func TestApplyACPModelsResultProjectsModelConfigOption(t *testing.T) {
state := newACPLiveState()
applyACPModelsResult(&state, json.RawMessage(`{
"models": {
"availableModels": [
{"modelId":"auto-gemini-3","name":"Auto (Gemini 3)","description":"Routes automatically\nwithout rewriting"},
{"modelId":"gemini-3-pro-preview","name":"Gemini 3 Pro","description":"Frontier model · x0.71 credits"},
{"modelId":"hy3","name":"Hy3","description":"0.00x Credits"}
],
"currentModelId":"auto-gemini-3"
}
}`), StandardACPModelDescriptionMetadataFormatCreditConsumptionMultiplierV1)
if !state.modelsAPI {
t.Fatal("modelsAPI = false, want true")
}
options := extractModelOptionsFromRuntimeDescriptorsForTest(state.configOptionDescriptors)
if len(options) != 3 {
t.Fatalf("model options = %#v, want three", options)
}
if options[0]["value"] != "auto-gemini-3" || options[0]["label"] != "Auto (Gemini 3)" {
t.Fatalf("first model option = %#v", options[0])
}
if options[0]["description"] != "Routes automatically\nwithout rewriting" {
t.Fatalf("ordinary model description = %#v, want verbatim text", options[0]["description"])
}
if options[1]["description"] != "Frontier model" || options[1]["consumptionMultiplier"] != "0.71" {
t.Fatalf("model consumption metadata = %#v", options[1])
}
if _, present := options[2]["description"]; present || options[2]["consumptionMultiplier"] != "0.00" {
t.Fatalf("credit-only model metadata = %#v", options[2])
}
if state.configOptions["model"] != "auto-gemini-3" {
t.Fatalf("current model = %#v, want auto-gemini-3", state.configOptions["model"])
}
}
func TestApplyACPModelsResultPreservesDescriptionWithoutDeclaredMetadataFormat(t *testing.T) {
state := newACPLiveState()
applyACPModelsResult(&state, json.RawMessage(`{
"models": {
"availableModels": [
{"modelId":"ordinary-provider","name":"Ordinary Provider","description":"Frontier model · x0.71 credits"}
],
"currentModelId":"ordinary-provider"
}
}`), "")
options := extractModelOptionsFromRuntimeDescriptorsForTest(state.configOptionDescriptors)
if len(options) != 1 || options[0]["description"] != "Frontier model · x0.71 credits" {
t.Fatalf("model options = %#v, want provider description preserved", options)
}
if _, present := options[0]["consumptionMultiplier"]; present {
t.Fatalf("undeclared consumption metadata should not be inferred: %#v", options[0])
}
}
func TestApplyACPConfigOptionsResultProjectsDeclaredModelConsumptionMetadata(t *testing.T) {
state := newACPLiveState()
applyACPConfigOptionsResult(&state, json.RawMessage(`{
"configOptions": [
{
"type":"select",
"id":"model",
"currentValue":"hy3",
"options":[
{"value":"hy3","name":"Hy3","description":"x0.00 credits"},
{"value":"glm-5.3","name":"GLM-5.3","description":"Frontier model · x0.79 credits"}
]
}
]
}`), "model", StandardACPModelDescriptionMetadataFormatCreditConsumptionMultiplierV1)
options := extractModelOptionsFromRuntimeDescriptorsForTest(state.configOptionDescriptors)
if len(options) != 2 {
t.Fatalf("model options = %#v, want two", options)
}
if _, present := options[0]["description"]; present || options[0]["consumptionMultiplier"] != "0.00" {
t.Fatalf("credit-only config option metadata = %#v", options[0])
}
if options[1]["description"] != "Frontier model" || options[1]["consumptionMultiplier"] != "0.79" {
t.Fatalf("mixed config option metadata = %#v", options[1])
}
}
func TestApplyACPConfigOptionsResultPreservesDescriptionWithoutDeclaredMetadataFormat(t *testing.T) {
state := newACPLiveState()
applyACPConfigOptionsResult(&state, json.RawMessage(`{
"configOptions": [{
"id":"model",
"currentValue":"ordinary-provider",
"options":[{
"value":"ordinary-provider",
"name":"Ordinary Provider",
"description":"Frontier model · x0.71 credits",
"consumptionMultiplier":"9.99"
}]
}]
}`), "model", "")
options := extractModelOptionsFromRuntimeDescriptorsForTest(state.configOptionDescriptors)
if len(options) != 1 || options[0]["description"] != "Frontier model · x0.71 credits" {
t.Fatalf("model options = %#v, want provider description preserved", options)
}
if _, present := options[0]["consumptionMultiplier"]; present {
t.Fatalf("undeclared config option consumption metadata should not be inferred: %#v", options[0])
}
}
func TestNewStandardACPAdapterRejectsUnknownModelDescriptionMetadataFormat(t *testing.T) {
_, err := NewStandardACPAdapter(StandardACPAdapterConfig{
Provider: "acp:example",
Command: []string{"example", "--acp"},
ModelDescriptionFormat: "extension-supplied-parser",
}, nil, LegacyHostMetadata())
if err == nil {
t.Fatal("NewStandardACPAdapter() error = nil, want unsupported metadata format rejection")
}
}
func TestApplyACPModelsResultPreservesDynamicModelMetadata(t *testing.T) {
state := newACPLiveState()
applyACPModelsResult(&state, json.RawMessage(`{
"models": {
"availableModels": [
{
"modelId":"reasoning-model",
"name":"Reasoning Model",
"supportsReasoningEffort":true,
"reasoningEffort":"deep",
"reasoningEfforts":[
{"value":"brief","label":"Brief","description":"Fast"},
{"value":"deep","label":"Deep","default":true}
],
"supportsImageInput":true
},
{
"modelId":"plain-model",
"name":"Plain Model",
"_meta":{
"supportsReasoningEffort":false,
"reasoningEfforts":[],
"supportsImageInput":false
}
}
],
"currentModelId":"reasoning-model"
}
}`), "")
options := extractModelOptionsFromRuntimeDescriptorsForTest(state.configOptionDescriptors)
if len(options) != 2 {
t.Fatalf("model options = %#v, want two", options)
}
if options[0]["supportsReasoningEffort"] != true || options[0]["reasoningEffort"] != "deep" || options[0]["supportsImageInput"] != true {
t.Fatalf("reasoning model metadata = %#v", options[0])
}
efforts, ok := options[0]["reasoningEfforts"].([]any)
if !ok || len(efforts) != 2 {
t.Fatalf("reasoning efforts = %#v, want two", options[0]["reasoningEfforts"])
}
brief, _ := efforts[0].(map[string]any)
if brief["value"] != "brief" || brief["label"] != "Brief" || brief["description"] != "Fast" {
t.Fatalf("brief effort = %#v", brief)
}
if options[1]["supportsReasoningEffort"] != false || options[1]["supportsImageInput"] != false {
t.Fatalf("plain model metadata = %#v", options[1])
}
if efforts, ok := options[1]["reasoningEfforts"].([]any); !ok || len(efforts) != 0 {
t.Fatalf("plain reasoning efforts = %#v, want advertised empty list", options[1]["reasoningEfforts"])
}
}
func TestApplyACPModelsResultToleratesAlternateMetadataShapes(t *testing.T) {
state := newACPLiveState()
applyACPModelsResult(&state, json.RawMessage(`{
"models": {
"availableModels": [
{
"modelId":"string-efforts",
"name":"String Efforts",
"supportsReasoningEffort":{"unexpected":true},
"reasoningEffort":42,
"reasoningEfforts":["low",{"id":"high","name":"High","default":true}],
"supportsImageInput":"yes",
"_meta":{
"supportsReasoningEffort":true,
"reasoningEffort":"high",
"supportsImageInput":true
}
},
{
"modelId":"unknown-metadata",
"name":"Unknown Metadata",
"reasoningEfforts":{"unexpected":true},
"_meta":"unexpected"
}
],
"currentModelId":"string-efforts"
}
}`), "")
if !state.modelsAPI {
t.Fatal("modelsAPI = false, want true")
}
options := extractModelOptionsFromRuntimeDescriptorsForTest(state.configOptionDescriptors)
if len(options) != 2 {
t.Fatalf("model options = %#v, want both models preserved", options)
}
if options[0]["supportsReasoningEffort"] != true || options[0]["reasoningEffort"] != "high" || options[0]["supportsImageInput"] != true {
t.Fatalf("fallback metadata = %#v", options[0])
}
efforts, ok := options[0]["reasoningEfforts"].([]any)
if !ok || len(efforts) != 2 {
t.Fatalf("reasoning efforts = %#v, want string and object entries", options[0]["reasoningEfforts"])
}
low, _ := efforts[0].(map[string]any)
high, _ := efforts[1].(map[string]any)
if low["value"] != "low" || high["value"] != "high" || high["label"] != "High" || high["default"] != true {
t.Fatalf("normalized efforts = %#v", efforts)
}
if options[1]["value"] != "unknown-metadata" {
t.Fatalf("unknown metadata model = %#v", options[1])
}
if _, advertised := options[1]["reasoningEfforts"]; advertised {
t.Fatalf("invalid reasoning efforts should be ignored: %#v", options[1])
}
}
func extractModelOptionsFromRuntimeDescriptorsForTest(descriptors []map[string]any) []map[string]any {
for _, descriptor := range descriptors {
if descriptor["id"] != "model" {
continue
}
raw, _ := descriptor["options"].([]any)
result := make([]map[string]any, 0, len(raw))
for _, item := range raw {
if option, ok := item.(map[string]any); ok {
result = append(result, option)
}
}
return result
}
return nil
}