Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 22 additions & 8 deletions coderd/aitasks.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,15 +113,29 @@ func (api *API) tasksCreate(rw http.ResponseWriter, r *http.Request) {
return
}

taskName := taskname.GenerateFallback()
if anthropicAPIKey := taskname.GetAnthropicAPIKeyFromEnv(); anthropicAPIKey != "" {
anthropicModel := taskname.GetAnthropicModelFromEnv()
taskName := req.Name
if taskName != "" {
if err := codersdk.NameValid(taskName); err != nil {
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
Message: "Unable to create a Task with the provided name.",
Detail: err.Error(),
})
return
}
}

generatedName, err := taskname.Generate(ctx, req.Prompt, taskname.WithAPIKey(anthropicAPIKey), taskname.WithModel(anthropicModel))
if err != nil {
api.Logger.Error(ctx, "unable to generate task name", slog.Error(err))
} else {
taskName = generatedName
if taskName == "" {
taskName = taskname.GenerateFallback()

if anthropicAPIKey := taskname.GetAnthropicAPIKeyFromEnv(); anthropicAPIKey != "" {
anthropicModel := taskname.GetAnthropicModelFromEnv()

generatedName, err := taskname.Generate(ctx, req.Prompt, taskname.WithAPIKey(anthropicAPIKey), taskname.WithModel(anthropicModel))
if err != nil {
api.Logger.Error(ctx, "unable to generate task name", slog.Error(err))
} else {
taskName = generatedName
}
}
}

Expand Down
74 changes: 74 additions & 0 deletions coderd/aitasks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,80 @@ func TestTasksCreate(t *testing.T) {
assert.Equal(t, taskPrompt, parameters[0].Value)
})

t.Run("CustomNames", func(t *testing.T) {
t.Parallel()

tests := []struct {
name string
taskName string
expectFallbackName bool
expectError string
}{
{
name: "ValidName",
taskName: "a-valid-task-name",
},
{
name: "NotValidName",
taskName: "this is not a valid task name",
expectError: "Unable to create a Task with the provided name.",
},
{
name: "NoNameProvided",
taskName: "",
expectFallbackName: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()

var (
ctx = testutil.Context(t, testutil.WaitShort)
client = coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
expClient = codersdk.NewExperimentalClient(client)
user = coderdtest.CreateFirstUser(t, client)
version = coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
Parse: echo.ParseComplete,
ProvisionApply: echo.ApplyComplete,
ProvisionPlan: []*proto.Response{
{Type: &proto.Response_Plan{Plan: &proto.PlanComplete{
Parameters: []*proto.RichParameter{{Name: "AI Prompt", Type: "string"}},
HasAiTasks: true,
}}},
},
})
template = coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
)

coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)

// When: We attempt to create a Task.
task, err := expClient.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
TemplateVersionID: template.ActiveVersionID,
Prompt: "Some prompt",
Name: tt.taskName,
})
if tt.expectError == "" {
require.NoError(t, err)
require.True(t, task.WorkspaceID.Valid)

// Then: We expect the correct name to have been picked.
err = codersdk.NameValid(task.Name)
require.NoError(t, err, "Generated task name should be valid")

require.NotEmpty(t, task.Name)
if !tt.expectFallbackName {
require.Equal(t, tt.taskName, task.Name)
}
} else {
require.ErrorContains(t, err, tt.expectError)
}
})
}
})

t.Run("FailsOnNonTaskTemplate", func(t *testing.T) {
t.Parallel()

Expand Down
1 change: 1 addition & 0 deletions codersdk/aitasks.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ type CreateTaskRequest struct {
TemplateVersionID uuid.UUID `json:"template_version_id" format:"uuid"`
TemplateVersionPresetID uuid.UUID `json:"template_version_preset_id,omitempty" format:"uuid"`
Prompt string `json:"prompt"`
Name string `json:"name,omitempty"`
}

func (c *ExperimentalClient) CreateTask(ctx context.Context, user string, request CreateTaskRequest) (Task, error) {
Expand Down
1 change: 1 addition & 0 deletions site/src/api/typesGenerated.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading