Skip to content

Commit 2521e73

Browse files
refactor: generate task name fallback on coderd (#19447)
Instead of generating the fallback task name on the website, we instead generate it on coderd.
1 parent 62fa731 commit 2521e73

File tree

7 files changed

+47
-21
lines changed

7 files changed

+47
-21
lines changed

coderd/aitasks.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ func (api *API) tasksCreate(rw http.ResponseWriter, r *http.Request) {
107107
return
108108
}
109109

110-
taskName := req.Name
110+
taskName := taskname.GenerateFallback()
111111
if anthropicAPIKey := taskname.GetAnthropicAPIKeyFromEnv(); anthropicAPIKey != "" {
112112
anthropicModel := taskname.GetAnthropicModelFromEnv()
113113

coderd/aitasks_test.go

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,6 @@ func TestTaskCreate(t *testing.T) {
151151
var (
152152
ctx = testutil.Context(t, testutil.WaitShort)
153153

154-
taskName = "task-foo-bar-baz"
155154
taskPrompt = "Some task prompt"
156155
)
157156

@@ -176,15 +175,14 @@ func TestTaskCreate(t *testing.T) {
176175

177176
// When: We attempt to create a Task.
178177
workspace, err := expClient.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
179-
Name: taskName,
180178
TemplateVersionID: template.ActiveVersionID,
181179
Prompt: taskPrompt,
182180
})
183181
require.NoError(t, err)
184182
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID)
185183

186184
// Then: We expect a workspace to have been created.
187-
assert.Equal(t, taskName, workspace.Name)
185+
assert.NotEmpty(t, workspace.Name)
188186
assert.Equal(t, template.ID, workspace.TemplateID)
189187

190188
// And: We expect it to have the "AI Prompt" parameter correctly set.
@@ -201,7 +199,6 @@ func TestTaskCreate(t *testing.T) {
201199
var (
202200
ctx = testutil.Context(t, testutil.WaitShort)
203201

204-
taskName = "task-foo-bar-baz"
205202
taskPrompt = "Some task prompt"
206203
)
207204

@@ -217,7 +214,6 @@ func TestTaskCreate(t *testing.T) {
217214

218215
// When: We attempt to create a Task.
219216
_, err := expClient.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
220-
Name: taskName,
221217
TemplateVersionID: template.ActiveVersionID,
222218
Prompt: taskPrompt,
223219
})
@@ -235,7 +231,6 @@ func TestTaskCreate(t *testing.T) {
235231
var (
236232
ctx = testutil.Context(t, testutil.WaitShort)
237233

238-
taskName = "task-foo-bar-baz"
239234
taskPrompt = "Some task prompt"
240235
)
241236

@@ -251,7 +246,6 @@ func TestTaskCreate(t *testing.T) {
251246

252247
// When: We attempt to create a Task with an invalid template version ID.
253248
_, err := expClient.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
254-
Name: taskName,
255249
TemplateVersionID: uuid.New(),
256250
Prompt: taskPrompt,
257251
})

coderd/taskname/taskname.go

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,15 @@ package taskname
22

33
import (
44
"context"
5+
"fmt"
56
"io"
7+
"math/rand/v2"
68
"os"
9+
"strings"
710

811
"github.com/anthropics/anthropic-sdk-go"
912
anthropicoption "github.com/anthropics/anthropic-sdk-go/option"
13+
"github.com/moby/moby/pkg/namesgenerator"
1014
"golang.org/x/xerrors"
1115

1216
"github.com/coder/aisdk-go"
@@ -20,19 +24,17 @@ const (
2024
Requirements:
2125
- Only lowercase letters, numbers, and hyphens
2226
- Start with "task-"
23-
- End with a random number between 0-99
24-
- Maximum 32 characters total
27+
- Maximum 28 characters total
2528
- Descriptive of the main task
2629
2730
Examples:
28-
- "Help me debug a Python script" → "task-python-debug-12"
29-
- "Create a React dashboard component" → "task-react-dashboard-93"
30-
- "Analyze sales data from Q3" → "task-analyze-q3-sales-37"
31-
- "Set up CI/CD pipeline" → "task-setup-cicd-44"
31+
- "Help me debug a Python script" → "task-python-debug"
32+
- "Create a React dashboard component" → "task-react-dashboard"
33+
- "Analyze sales data from Q3" → "task-analyze-q3-sales"
34+
- "Set up CI/CD pipeline" → "task-setup-cicd"
3235
3336
If you cannot create a suitable name:
34-
- Respond with "task-unnamed"
35-
- Do not end with a random number`
37+
- Respond with "task-unnamed"`
3638
)
3739

3840
var (
@@ -67,6 +69,32 @@ func GetAnthropicModelFromEnv() anthropic.Model {
6769
return anthropic.Model(os.Getenv("ANTHROPIC_MODEL"))
6870
}
6971

72+
// generateSuffix generates a random hex string between `0000` and `ffff`.
73+
func generateSuffix() string {
74+
numMin := 0x00000
75+
numMax := 0x10000
76+
//nolint:gosec // We don't need a cryptographically secure random number generator for generating a task name suffix.
77+
num := rand.IntN(numMax-numMin) + numMin
78+
79+
return fmt.Sprintf("%04x", num)
80+
}
81+
82+
func GenerateFallback() string {
83+
// We have a 32 character limit for the name.
84+
// We have a 5 character prefix `task-`.
85+
// We have a 5 character suffix `-ffff`.
86+
// This leaves us with 22 characters for the middle.
87+
//
88+
// Unfortunately, `namesgenerator.GetRandomName(0)` will
89+
// generate names that are longer than 22 characters, so
90+
// we just trim these down to length.
91+
name := strings.ReplaceAll(namesgenerator.GetRandomName(0), "_", "-")
92+
name = name[:min(len(name), 22)]
93+
name = strings.TrimSuffix(name, "-")
94+
95+
return fmt.Sprintf("task-%s-%s", name, generateSuffix())
96+
}
97+
7098
func Generate(ctx context.Context, prompt string, opts ...Option) (string, error) {
7199
o := options{}
72100
for _, opt := range opts {
@@ -127,7 +155,7 @@ func Generate(ctx context.Context, prompt string, opts ...Option) (string, error
127155
return "", ErrNoNameGenerated
128156
}
129157

130-
return generatedName, nil
158+
return fmt.Sprintf("%s-%s", generatedName, generateSuffix()), nil
131159
}
132160

133161
func anthropicDataStream(ctx context.Context, client anthropic.Client, model anthropic.Model, input []aisdk.Message) (aisdk.DataStream, error) {

coderd/taskname/taskname_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@ const (
1515
anthropicEnvVar = "ANTHROPIC_API_KEY"
1616
)
1717

18+
func TestGenerateFallback(t *testing.T) {
19+
t.Parallel()
20+
21+
name := taskname.GenerateFallback()
22+
err := codersdk.NameValid(name)
23+
require.NoErrorf(t, err, "expected fallback to be valid workspace name, instead found %s", name)
24+
}
25+
1826
func TestGenerateTaskName(t *testing.T) {
1927
t.Parallel()
2028

codersdk/aitasks.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ func (c *ExperimentalClient) AITaskPrompts(ctx context.Context, buildIDs []uuid.
4747
}
4848

4949
type CreateTaskRequest struct {
50-
Name string `json:"name"`
5150
TemplateVersionID uuid.UUID `json:"template_version_id" format:"uuid"`
5251
TemplateVersionPresetID uuid.UUID `json:"template_version_preset_id,omitempty" format:"uuid"`
5352
Prompt string `json:"prompt"`

site/src/api/typesGenerated.ts

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

site/src/pages/TasksPage/TasksPage.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ import { useAuthenticated } from "hooks";
5353
import { useExternalAuth } from "hooks/useExternalAuth";
5454
import { RedoIcon, RotateCcwIcon, SendIcon } from "lucide-react";
5555
import { AI_PROMPT_PARAMETER_NAME, type Task } from "modules/tasks/tasks";
56-
import { generateWorkspaceName } from "modules/workspaces/generateWorkspaceName";
5756
import { WorkspaceAppStatus } from "modules/workspaces/WorkspaceAppStatus/WorkspaceAppStatus";
5857
import { type FC, type ReactNode, useEffect, useState } from "react";
5958
import { Helmet } from "react-helmet-async";
@@ -741,7 +740,6 @@ export const data = {
741740
}
742741

743742
const workspace = await API.experimental.createTask(userId, {
744-
name: `task-${generateWorkspaceName()}`,
745743
template_version_id: templateVersionId,
746744
template_version_preset_id: preset_id || undefined,
747745
prompt,

0 commit comments

Comments
 (0)