Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit198ae96

Browse files
committed
task title and workspace name endpoint
1 parentbe4f5ef commit198ae96

File tree

3 files changed

+181
-0
lines changed

3 files changed

+181
-0
lines changed

‎coderd/coderd.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1494,6 +1494,10 @@ func New(options *Options) *API {
14941494
r.Use(apiKeyMiddleware)
14951495
r.Get("/",api.tailnetRPCConn)
14961496
})
1497+
r.Route("/ai-tasks",func(r chi.Router) {
1498+
r.Use(apiKeyMiddleware)
1499+
r.Get("/name",api.TaskTitleAndWorkspaceName)
1500+
})
14971501
})
14981502

14991503
ifoptions.SwaggerEndpoint {

‎coderd/tasks.go

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
package coderd
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"io"
7+
"net/http"
8+
9+
"github.com/kylecarbs/aisdk-go"
10+
"golang.org/x/xerrors"
11+
12+
"cdr.dev/slog"
13+
14+
"github.com/mitchellh/mapstructure"
15+
16+
"github.com/coder/coder/v2/coderd/ai"
17+
"github.com/coder/coder/v2/coderd/httpapi"
18+
"github.com/coder/coder/v2/codersdk"
19+
)
20+
21+
constsystemPrompt=`You are a helpful assistant that can create Coder workspaces. Coder workspaces are ephemeral development environments created for specific coding tasks.
22+
23+
Whenever you name a workspace based on a task prompt, use the following examples as a guide:
24+
25+
# Example 1
26+
27+
Task prompt: make the background purple
28+
Workspace name: purple-bg
29+
Task title: Make the background purple
30+
31+
# Example 2
32+
33+
Task prompt: refactor the UI components to use MUI
34+
Workspace name: refactor-ui-to-mui
35+
Task title: MUI Refactor
36+
37+
# Example 3
38+
39+
Task prompt: hey look through the repository and find all the places where we use postgres. then use that as a guide to refactor the app to use supabase.
40+
Workspace name: migrate-pg-supabase
41+
Task title: Supabase Migration
42+
43+
# Example 4
44+
45+
Task prompt: Look through our BigQuery dataset and generate a report on the top deployments using the prebuilds feature.
46+
Workspace name: bq-prebuilds-report
47+
Task title: BigQuery Prebuilds Report
48+
49+
# Example 5
50+
51+
Task prompt: address this issue: https://github.com/coder/coder/issues/18159
52+
Workspace name: gh-issue-18159
53+
Task title: GitHub Issue coder/coder#18159`
54+
55+
typecreateWorkspaceToolArgsstruct {
56+
WorkspaceNamestring`mapstructure:"name"`
57+
TaskTitlestring`mapstructure:"task_title"`
58+
}
59+
60+
constcreateWorkspaceToolName="create_workspace"
61+
62+
varcreateWorkspaceTool= aisdk.Tool{
63+
Name:createWorkspaceToolName,
64+
Description:"Create a workspace",
65+
Schema: aisdk.Schema{
66+
Required: []string{"name","task_title"},
67+
Properties:map[string]any{
68+
"name":map[string]any{
69+
"type":"string",
70+
"description":"Name of the workspace to create.",
71+
},
72+
"task_title":map[string]any{
73+
"type":"string",
74+
"description":"Title of the task to create the workspace for. Max 48 characters.",
75+
},
76+
},
77+
},
78+
}
79+
80+
funcgenerateNameAndTitle(ctx context.Context,logger slog.Logger,provider*ai.LanguageModel,modelIDstring,taskPromptstring) (createWorkspaceToolArgs,error) {
81+
stream,err:=provider.StreamFunc(ctx, ai.StreamOptions{
82+
Model:modelID,
83+
SystemPrompt:systemPrompt,
84+
Tools: []aisdk.Tool{createWorkspaceTool},
85+
Messages: []aisdk.Message{
86+
{
87+
Role:"user",
88+
Parts: []aisdk.Part{
89+
{
90+
Type:aisdk.PartTypeText,
91+
Text:fmt.Sprintf("Use the create_workspace tool to create a workspace based on the following task prompt:\n```\n%s\n```",taskPrompt),
92+
},
93+
},
94+
},
95+
},
96+
})
97+
iferr!=nil {
98+
returncreateWorkspaceToolArgs{},xerrors.Errorf("failed to generate workspace name: %w",err)
99+
}
100+
result:=createWorkspaceToolArgs{}
101+
stream=stream.WithToolCalling(func(toolCall aisdk.ToolCall) aisdk.ToolCallResult {
102+
iftoolCall.Name==createWorkspaceToolName {
103+
err:=mapstructure.Decode(toolCall.Args,&result)
104+
iferr!=nil {
105+
logger.Error(ctx,"failed to decode tool call args",slog.Error(err))
106+
returnnil
107+
}
108+
}
109+
returnnil
110+
})
111+
iferr:=stream.Pipe(io.Discard);err!=nil {
112+
returncreateWorkspaceToolArgs{},xerrors.Errorf("failed to pipe stream: %w",err)
113+
}
114+
ifresult== (createWorkspaceToolArgs{}) {
115+
returncreateWorkspaceToolArgs{},xerrors.New("no tool call found in the AI response")
116+
}
117+
returnresult,nil
118+
}
119+
120+
// @Summary Generate a task title and workspace name based on a task prompt
121+
// @ID generate-task-title-and-workspace-name-by-task-prompt
122+
// @Security CoderSessionToken
123+
// @Produce json
124+
// @Tags Tasks
125+
// @Param task_prompt query string true "Task prompt"
126+
// @Success 200 {object} codersdk.TaskTitleAndWorkspaceNameResponse
127+
// @Router /ai-tasks/name [get]
128+
func (api*API)TaskTitleAndWorkspaceName(rw http.ResponseWriter,r*http.Request) {
129+
var (
130+
ctx=r.Context()
131+
taskPrompt=r.URL.Query().Get("task_prompt")
132+
)
133+
iftaskPrompt=="" {
134+
httpapi.Write(ctx,rw,http.StatusBadRequest, codersdk.Response{
135+
Message:"Task prompt is required",
136+
})
137+
return
138+
}
139+
140+
modelID:="gpt-4.1-nano"
141+
provider,ok:=api.LanguageModels[modelID]
142+
if!ok {
143+
httpapi.Write(ctx,rw,http.StatusServiceUnavailable, codersdk.Response{
144+
Message:fmt.Sprintf("Language model %s not found",modelID),
145+
})
146+
return
147+
}
148+
149+
// Limit the task prompt to avoid burning tokens. The first 1024 characters
150+
// are likely enough to generate a good workspace name and task title.
151+
iflen(taskPrompt)>1024 {
152+
taskPrompt=taskPrompt[:1024]
153+
}
154+
155+
result,err:=generateNameAndTitle(ctx,api.Logger,&provider,modelID,taskPrompt)
156+
iferr!=nil {
157+
httpapi.Write(ctx,rw,http.StatusInternalServerError, codersdk.Response{
158+
Message:"Failed to generate workspace name and task title",
159+
Detail:err.Error(),
160+
})
161+
return
162+
}
163+
truncatedTaskTitle:=result.TaskTitle
164+
iflen(truncatedTaskTitle)>64 {
165+
truncatedTaskTitle=truncatedTaskTitle[:64]
166+
}
167+
httpapi.Write(ctx,rw,http.StatusOK, codersdk.TaskTitleAndWorkspaceNameResponse{
168+
TaskTitle:truncatedTaskTitle,
169+
WorkspaceName:result.WorkspaceName,
170+
})
171+
}

‎codersdk/tasks.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package codersdk
2+
3+
typeTaskTitleAndWorkspaceNameResponsestruct {
4+
TaskTitlestring`json:"task_title"`
5+
WorkspaceNamestring`json:"workspace_name"`
6+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp