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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy