summaryrefslogtreecommitdiff
path: root/spec/test_models.lua
blob: 56d087730befdc463df2cac8840573209df3fe3f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
-- subagents/models.lua: the three catalog query forms.
--
-- The fake host answers by query shape, so each case checks both what the tool
-- asked the host for (`handle.models_queries`) and how it rendered the answer.

local fake = require("spec.fake_ext")
local models = require("subagents.models")

local function has(text, needle)
    assert(type(text) == "string", "expected a string result, got " .. type(text))
    assert(text:find(needle, 1, true), "expected to find " .. needle .. " in:\n" .. tostring(text))
end

local function catalog(query)
    if query.model then
        if query.model == "anthropic:sonnet" then
            return {
                found = true,
                ref = "anthropic:sonnet",
                wire_model = "claude-sonnet-4-6",
                reasoning_default = "medium",
                reasoning_levels = { "low", "medium", "high" },
                context_window = 200000,
                max_tokens = 64000,
            }
        end
        return { found = false }
    end
    if query.provider or query.query then
        return {
            matches = {
                { ref = "anthropic:sonnet", wire_model = "claude-sonnet-4-6", reasoning_default = "medium" },
                { ref = "anthropic:opus", wire_model = "claude-opus-4-6" },
            },
            truncated = true,
        }
    end
    return {
        model = "anthropic:sonnet",
        reasoning = "medium",
        providers = { { name = "anthropic", style = "messages", models = 7 } },
    }
end

local function with_host(fn)
    local handle = fake.install({ models_response = catalog })
    local ok, err = pcall(fn, handle)
    handle.restore()
    if not ok then
        error(err, 0)
    end
end

return {
    { "no arguments reports the inherited model and provider counts", function()
        with_host(function(handle, profiles)
            local text = models.handle({}, profiles)
            has(text, "inherited model: anthropic:sonnet")
            has(text, "inherited reasoning: medium")
            has(text, "anthropic (messages, 7 models)")
            assert(next(handle.models_queries[1]) == nil, "the overview query carries no fields")
        end)
    end },

    { "an exact model lookup reports its reasoning levels", function()
        with_host(function(handle, profiles)
            local text = models.handle({ model = "anthropic:sonnet" }, profiles)
            has(text, "model: anthropic:sonnet")
            has(text, "wire model: claude-sonnet-4-6")
            has(text, "default reasoning: medium")
            has(text, "reasoning levels: low, medium, high")
            has(text, "context window: 200000")
            assert(handle.models_queries[1].model == "anthropic:sonnet")
        end)
    end },

    { "an unknown model says so and suggests a search", function()
        with_host(function(handle, profiles)
            local text = models.handle({ model = "acme:turbo" }, profiles)
            has(text, "No configured model matches 'acme:turbo'")
            has(text, "subagents.models")
        end)
    end },

    { "a search reports matches and says when more exist", function()
        with_host(function(handle, profiles)
            local text = models.handle({ query = "son" }, profiles)
            has(text, "2 match(es):")
            has(text, "anthropic:sonnet — wire claude-sonnet-4-6, default reasoning medium")
            has(text, "more exist — refine the query")
            assert(handle.models_queries[1].limit == 10, "the default limit is 10")
        end)
    end },

    { "limit is clamped to 1..50", function()
        with_host(function(handle, profiles)
            models.handle({ query = "son", limit = 500 }, profiles)
            assert(handle.models_queries[1].limit == 50, tostring(handle.models_queries[1].limit))
            models.handle({ provider = "anthropic", limit = 0 }, profiles)
            assert(handle.models_queries[2].limit == 1, tostring(handle.models_queries[2].limit))
            models.handle({ query = "son", limit = 7.6 }, profiles)
            assert(handle.models_queries[3].limit == 7, "a fractional limit is floored")
        end)
    end },

    { "a non-string field is refused", function()
        with_host(function(handle, profiles)
            has(models.handle({ query = 12 }, profiles), "Error: `query` must be a non-empty string")
            has(models.handle({ model = "" }, profiles), "Error: `model` must be a non-empty string")
            assert(#handle.models_queries == 0, "a refused call never reaches the host")
        end)
    end },
}