mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00:00
a74015fc85
Fixes CODAGT-175 Addresses a review finding in https://github.com/coder/coder/pull/23827 that the nil-guards for both `database.Store` and `chatID` are both dead code in practice in the `chattool` package. - Modifies the return signatures require passing both `database.Store` and `chatID` explicitly as positional arguments instead of just parameter struct keys. - Drops the nil-guards for `database.Store` and `chatID`.
184 lines
5.6 KiB
Go
184 lines
5.6 KiB
Go
package chattool_test
|
|
|
|
import (
|
|
"database/sql"
|
|
"encoding/json"
|
|
"testing"
|
|
|
|
"charm.land/fantasy"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/coder/coder/v2/coderd/database"
|
|
"github.com/coder/coder/v2/coderd/database/dbgen"
|
|
"github.com/coder/coder/v2/coderd/database/dbtestutil"
|
|
"github.com/coder/coder/v2/coderd/x/chatd/chattool"
|
|
"github.com/coder/coder/v2/testutil"
|
|
)
|
|
|
|
func TestReadTemplate_IncludesPresets(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
db, _ := dbtestutil.NewDB(t)
|
|
user := dbgen.User(t, db, database.User{})
|
|
org := dbgen.Organization(t, db, database.Organization{})
|
|
_ = dbgen.OrganizationMember(t, db, database.OrganizationMember{
|
|
UserID: user.ID,
|
|
OrganizationID: org.ID,
|
|
})
|
|
|
|
tv := dbgen.TemplateVersion(t, db, database.TemplateVersion{
|
|
OrganizationID: org.ID,
|
|
CreatedBy: user.ID,
|
|
})
|
|
tmpl := dbgen.Template(t, db, database.Template{
|
|
OrganizationID: org.ID,
|
|
CreatedBy: user.ID,
|
|
ActiveVersionID: tv.ID,
|
|
})
|
|
|
|
// Create a preset with parameters.
|
|
const usEastLargeDesiredPrebuildInstances = 3
|
|
preset := dbgen.Preset(t, db, database.InsertPresetParams{
|
|
TemplateVersionID: tv.ID,
|
|
Name: "us-east-large",
|
|
IsDefault: true,
|
|
Description: "US East large instance",
|
|
Icon: "/icon/us.png",
|
|
DesiredInstances: sql.NullInt32{
|
|
Int32: usEastLargeDesiredPrebuildInstances,
|
|
Valid: true,
|
|
},
|
|
})
|
|
_ = dbgen.PresetParameter(t, db, database.InsertPresetParametersParams{
|
|
TemplateVersionPresetID: preset.ID,
|
|
Names: []string{"region", "instance_type"},
|
|
Values: []string{"us-east", "large"},
|
|
})
|
|
|
|
// Create a second preset without parameters.
|
|
_ = dbgen.Preset(t, db, database.InsertPresetParams{
|
|
TemplateVersionID: tv.ID,
|
|
Name: "empty-preset",
|
|
})
|
|
|
|
ctx := testutil.Context(t, testutil.WaitShort)
|
|
tool := chattool.ReadTemplate(db, org.ID, chattool.ReadTemplateOptions{
|
|
OwnerID: user.ID,
|
|
})
|
|
|
|
resp, err := tool.Run(ctx, fantasy.ToolCall{
|
|
ID: "call-1",
|
|
Name: "read_template",
|
|
Input: `{"template_id":"` + tmpl.ID.String() + `"}`,
|
|
})
|
|
require.NoError(t, err)
|
|
require.False(t, resp.IsError, "unexpected error: %s", resp.Content)
|
|
|
|
var result map[string]any
|
|
require.NoError(t, json.Unmarshal([]byte(resp.Content), &result))
|
|
|
|
// Verify template info is present.
|
|
tmplInfo, ok := result["template"].(map[string]any)
|
|
require.True(t, ok)
|
|
require.Equal(t, tmpl.ID.String(), tmplInfo["id"])
|
|
|
|
// Verify presets are present.
|
|
presetsRaw, ok := result["presets"].([]any)
|
|
require.True(t, ok, "expected presets in response")
|
|
require.Len(t, presetsRaw, 2)
|
|
|
|
// Find the preset with parameters.
|
|
var foundPreset map[string]any
|
|
for _, p := range presetsRaw {
|
|
pm := p.(map[string]any)
|
|
if pm["name"] == "us-east-large" {
|
|
foundPreset = pm
|
|
break
|
|
}
|
|
}
|
|
require.NotNil(t, foundPreset, "expected to find us-east-large preset")
|
|
require.Equal(t, preset.ID.String(), foundPreset["id"])
|
|
require.Equal(t, true, foundPreset["default"])
|
|
require.Equal(t, "US East large instance", foundPreset["description"])
|
|
require.Equal(t, "/icon/us.png", foundPreset["icon"])
|
|
// Prebuild count round-trips so the LLM can prefer presets
|
|
// backed by prebuilt workspaces.
|
|
require.EqualValues(t, usEastLargeDesiredPrebuildInstances, foundPreset["desired_prebuild_instances"])
|
|
|
|
// Verify preset parameters.
|
|
presetParamsRaw, ok := foundPreset["parameters"].([]any)
|
|
require.True(t, ok)
|
|
require.Len(t, presetParamsRaw, 2)
|
|
|
|
paramMap := make(map[string]string)
|
|
for _, pp := range presetParamsRaw {
|
|
ppm := pp.(map[string]any)
|
|
paramMap[ppm["name"].(string)] = ppm["value"].(string)
|
|
}
|
|
require.Equal(t, "us-east", paramMap["region"])
|
|
require.Equal(t, "large", paramMap["instance_type"])
|
|
|
|
// Verify the empty preset has correct defaults.
|
|
var emptyPreset map[string]any
|
|
for _, p := range presetsRaw {
|
|
pm := p.(map[string]any)
|
|
if pm["name"] == "empty-preset" {
|
|
emptyPreset = pm
|
|
break
|
|
}
|
|
}
|
|
require.NotNil(t, emptyPreset, "expected to find empty-preset")
|
|
require.Equal(t, false, emptyPreset["default"])
|
|
_, hasDesc := emptyPreset["description"]
|
|
require.False(t, hasDesc, "empty-preset should not have description")
|
|
_, hasIcon := emptyPreset["icon"]
|
|
require.False(t, hasIcon, "empty-preset should not have icon")
|
|
_, hasPrebuilds := emptyPreset["desired_prebuild_instances"]
|
|
require.False(t, hasPrebuilds, "empty-preset should not have desired_prebuild_instances")
|
|
emptyParams, ok := emptyPreset["parameters"].([]any)
|
|
require.True(t, ok)
|
|
require.Empty(t, emptyParams, "empty-preset should have no parameters")
|
|
}
|
|
|
|
func TestReadTemplate_NoPresets(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
db, _ := dbtestutil.NewDB(t)
|
|
user := dbgen.User(t, db, database.User{})
|
|
org := dbgen.Organization(t, db, database.Organization{})
|
|
_ = dbgen.OrganizationMember(t, db, database.OrganizationMember{
|
|
UserID: user.ID,
|
|
OrganizationID: org.ID,
|
|
})
|
|
|
|
tv := dbgen.TemplateVersion(t, db, database.TemplateVersion{
|
|
OrganizationID: org.ID,
|
|
CreatedBy: user.ID,
|
|
})
|
|
tmpl := dbgen.Template(t, db, database.Template{
|
|
OrganizationID: org.ID,
|
|
CreatedBy: user.ID,
|
|
ActiveVersionID: tv.ID,
|
|
})
|
|
|
|
ctx := testutil.Context(t, testutil.WaitShort)
|
|
tool := chattool.ReadTemplate(db, org.ID, chattool.ReadTemplateOptions{
|
|
OwnerID: user.ID,
|
|
})
|
|
|
|
resp, err := tool.Run(ctx, fantasy.ToolCall{
|
|
ID: "call-2",
|
|
Name: "read_template",
|
|
Input: `{"template_id":"` + tmpl.ID.String() + `"}`,
|
|
})
|
|
require.NoError(t, err)
|
|
require.False(t, resp.IsError)
|
|
|
|
var result map[string]any
|
|
require.NoError(t, json.Unmarshal([]byte(resp.Content), &result))
|
|
|
|
// Presets key should be absent when there are no presets.
|
|
_, hasPresets := result["presets"]
|
|
require.False(t, hasPresets, "presets key should be absent when there are none")
|
|
}
|