mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00:00
chore: promote tasks to stable from experimental (#20921)
- Promote tasks from `/api/experimental` to `/api/v2`. - Move sdk from `ExperimentalClient` to `Client`. - Update swagger
This commit is contained in:
+2
-3
@@ -111,8 +111,7 @@ func (r *RootCmd) taskCreate() *serpent.Command {
|
||||
}
|
||||
|
||||
var (
|
||||
ctx = inv.Context()
|
||||
expClient = codersdk.NewExperimentalClient(client)
|
||||
ctx = inv.Context()
|
||||
|
||||
taskInput string
|
||||
templateVersionID uuid.UUID
|
||||
@@ -208,7 +207,7 @@ func (r *RootCmd) taskCreate() *serpent.Command {
|
||||
templateVersionPresetID = preset.ID
|
||||
}
|
||||
|
||||
task, err := expClient.CreateTask(ctx, ownerArg, codersdk.CreateTaskRequest{
|
||||
task, err := client.CreateTask(ctx, ownerArg, codersdk.CreateTaskRequest{
|
||||
Name: taskName,
|
||||
TemplateVersionID: templateVersionID,
|
||||
TemplateVersionPresetID: templateVersionPresetID,
|
||||
|
||||
@@ -69,7 +69,7 @@ func TestTaskCreate(t *testing.T) {
|
||||
ActiveVersionID: templateVersionID,
|
||||
},
|
||||
})
|
||||
case fmt.Sprintf("/api/experimental/tasks/%s", username):
|
||||
case fmt.Sprintf("/api/v2/tasks/%s", username):
|
||||
var req codersdk.CreateTaskRequest
|
||||
if !httpapi.Read(ctx, w, r, &req) {
|
||||
return
|
||||
|
||||
+2
-3
@@ -44,11 +44,10 @@ func (r *RootCmd) taskDelete() *serpent.Command {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
exp := codersdk.NewExperimentalClient(client)
|
||||
|
||||
var tasks []codersdk.Task
|
||||
for _, identifier := range inv.Args {
|
||||
task, err := exp.TaskByIdentifier(ctx, identifier)
|
||||
task, err := client.TaskByIdentifier(ctx, identifier)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("resolve task %q: %w", identifier, err)
|
||||
}
|
||||
@@ -71,7 +70,7 @@ func (r *RootCmd) taskDelete() *serpent.Command {
|
||||
|
||||
for i, task := range tasks {
|
||||
display := displayList[i]
|
||||
if err := exp.DeleteTask(ctx, task.OwnerName, task.ID); err != nil {
|
||||
if err := client.DeleteTask(ctx, task.OwnerName, task.ID); err != nil {
|
||||
return xerrors.Errorf("delete task %q: %w", display, err)
|
||||
}
|
||||
_, _ = fmt.Fprintln(
|
||||
|
||||
+11
-11
@@ -56,7 +56,7 @@ func TestExpTaskDelete(t *testing.T) {
|
||||
taskID := uuid.MustParse(id1)
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
switch {
|
||||
case r.Method == http.MethodGet && r.URL.Path == "/api/experimental/tasks/me/exists":
|
||||
case r.Method == http.MethodGet && r.URL.Path == "/api/v2/tasks/me/exists":
|
||||
c.nameResolves.Add(1)
|
||||
httpapi.Write(r.Context(), w, http.StatusOK,
|
||||
codersdk.Task{
|
||||
@@ -64,7 +64,7 @@ func TestExpTaskDelete(t *testing.T) {
|
||||
Name: "exists",
|
||||
OwnerName: "me",
|
||||
})
|
||||
case r.Method == http.MethodDelete && r.URL.Path == "/api/experimental/tasks/me/"+id1:
|
||||
case r.Method == http.MethodDelete && r.URL.Path == "/api/v2/tasks/me/"+id1:
|
||||
c.deleteCalls.Add(1)
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
default:
|
||||
@@ -82,13 +82,13 @@ func TestExpTaskDelete(t *testing.T) {
|
||||
buildHandler: func(c *testCounters) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
switch {
|
||||
case r.Method == http.MethodGet && r.URL.Path == "/api/experimental/tasks/me/"+id2:
|
||||
case r.Method == http.MethodGet && r.URL.Path == "/api/v2/tasks/me/"+id2:
|
||||
httpapi.Write(r.Context(), w, http.StatusOK, codersdk.Task{
|
||||
ID: uuid.MustParse(id2),
|
||||
OwnerName: "me",
|
||||
Name: "uuid-task",
|
||||
})
|
||||
case r.Method == http.MethodDelete && r.URL.Path == "/api/experimental/tasks/me/"+id2:
|
||||
case r.Method == http.MethodDelete && r.URL.Path == "/api/v2/tasks/me/"+id2:
|
||||
c.deleteCalls.Add(1)
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
default:
|
||||
@@ -104,24 +104,24 @@ func TestExpTaskDelete(t *testing.T) {
|
||||
buildHandler: func(c *testCounters) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
switch {
|
||||
case r.Method == http.MethodGet && r.URL.Path == "/api/experimental/tasks/me/first":
|
||||
case r.Method == http.MethodGet && r.URL.Path == "/api/v2/tasks/me/first":
|
||||
c.nameResolves.Add(1)
|
||||
httpapi.Write(r.Context(), w, http.StatusOK, codersdk.Task{
|
||||
ID: uuid.MustParse(id3),
|
||||
Name: "first",
|
||||
OwnerName: "me",
|
||||
})
|
||||
case r.Method == http.MethodGet && r.URL.Path == "/api/experimental/tasks/me/"+id4:
|
||||
case r.Method == http.MethodGet && r.URL.Path == "/api/v2/tasks/me/"+id4:
|
||||
c.nameResolves.Add(1)
|
||||
httpapi.Write(r.Context(), w, http.StatusOK, codersdk.Task{
|
||||
ID: uuid.MustParse(id4),
|
||||
OwnerName: "me",
|
||||
Name: "uuid-task-4",
|
||||
})
|
||||
case r.Method == http.MethodDelete && r.URL.Path == "/api/experimental/tasks/me/"+id3:
|
||||
case r.Method == http.MethodDelete && r.URL.Path == "/api/v2/tasks/me/"+id3:
|
||||
c.deleteCalls.Add(1)
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
case r.Method == http.MethodDelete && r.URL.Path == "/api/experimental/tasks/me/"+id4:
|
||||
case r.Method == http.MethodDelete && r.URL.Path == "/api/v2/tasks/me/"+id4:
|
||||
c.deleteCalls.Add(1)
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
default:
|
||||
@@ -140,7 +140,7 @@ func TestExpTaskDelete(t *testing.T) {
|
||||
buildHandler: func(_ *testCounters) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
switch {
|
||||
case r.Method == http.MethodGet && r.URL.Path == "/api/experimental/tasks" && r.URL.Query().Get("q") == "owner:\"me\"":
|
||||
case r.Method == http.MethodGet && r.URL.Path == "/api/v2/tasks" && r.URL.Query().Get("q") == "owner:\"me\"":
|
||||
httpapi.Write(r.Context(), w, http.StatusOK, struct {
|
||||
Tasks []codersdk.Task `json:"tasks"`
|
||||
Count int `json:"count"`
|
||||
@@ -163,14 +163,14 @@ func TestExpTaskDelete(t *testing.T) {
|
||||
taskID := uuid.MustParse(id5)
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
switch {
|
||||
case r.Method == http.MethodGet && r.URL.Path == "/api/experimental/tasks/me/bad":
|
||||
case r.Method == http.MethodGet && r.URL.Path == "/api/v2/tasks/me/bad":
|
||||
c.nameResolves.Add(1)
|
||||
httpapi.Write(r.Context(), w, http.StatusOK, codersdk.Task{
|
||||
ID: taskID,
|
||||
Name: "bad",
|
||||
OwnerName: "me",
|
||||
})
|
||||
case r.Method == http.MethodDelete && r.URL.Path == "/api/experimental/tasks/me/bad":
|
||||
case r.Method == http.MethodDelete && r.URL.Path == "/api/v2/tasks/me/bad":
|
||||
httpapi.InternalServerError(w, xerrors.New("boom"))
|
||||
default:
|
||||
httpapi.InternalServerError(w, xerrors.New("unwanted path: "+r.Method+" "+r.URL.Path))
|
||||
|
||||
+1
-2
@@ -135,14 +135,13 @@ func (r *RootCmd) taskList() *serpent.Command {
|
||||
}
|
||||
|
||||
ctx := inv.Context()
|
||||
exp := codersdk.NewExperimentalClient(client)
|
||||
|
||||
targetUser := strings.TrimSpace(user)
|
||||
if targetUser == "" && !all {
|
||||
targetUser = codersdk.Me
|
||||
}
|
||||
|
||||
tasks, err := exp.Tasks(ctx, &codersdk.TasksFilter{
|
||||
tasks, err := client.Tasks(ctx, &codersdk.TasksFilter{
|
||||
Owner: targetUser,
|
||||
Status: codersdk.TaskStatus(statusFilter),
|
||||
})
|
||||
|
||||
+2
-3
@@ -41,16 +41,15 @@ func (r *RootCmd) taskLogs() *serpent.Command {
|
||||
|
||||
var (
|
||||
ctx = inv.Context()
|
||||
exp = codersdk.NewExperimentalClient(client)
|
||||
identifier = inv.Args[0]
|
||||
)
|
||||
|
||||
task, err := exp.TaskByIdentifier(ctx, identifier)
|
||||
task, err := client.TaskByIdentifier(ctx, identifier)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("resolve task %q: %w", identifier, err)
|
||||
}
|
||||
|
||||
logs, err := exp.TaskLogs(ctx, codersdk.Me, task.ID)
|
||||
logs, err := client.TaskLogs(ctx, codersdk.Me, task.ID)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("get task logs: %w", err)
|
||||
}
|
||||
|
||||
+2
-3
@@ -39,7 +39,6 @@ func (r *RootCmd) taskSend() *serpent.Command {
|
||||
|
||||
var (
|
||||
ctx = inv.Context()
|
||||
exp = codersdk.NewExperimentalClient(client)
|
||||
identifier = inv.Args[0]
|
||||
|
||||
taskInput string
|
||||
@@ -60,12 +59,12 @@ func (r *RootCmd) taskSend() *serpent.Command {
|
||||
taskInput = inv.Args[1]
|
||||
}
|
||||
|
||||
task, err := exp.TaskByIdentifier(ctx, identifier)
|
||||
task, err := client.TaskByIdentifier(ctx, identifier)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("resolve task: %w", err)
|
||||
}
|
||||
|
||||
if err = exp.TaskSend(ctx, codersdk.Me, task.ID, codersdk.TaskSendRequest{Input: taskInput}); err != nil {
|
||||
if err = client.TaskSend(ctx, codersdk.Me, task.ID, codersdk.TaskSendRequest{Input: taskInput}); err != nil {
|
||||
return xerrors.Errorf("send input to task: %w", err)
|
||||
}
|
||||
|
||||
|
||||
+2
-3
@@ -83,10 +83,9 @@ func (r *RootCmd) taskStatus() *serpent.Command {
|
||||
}
|
||||
|
||||
ctx := i.Context()
|
||||
exp := codersdk.NewExperimentalClient(client)
|
||||
identifier := i.Args[0]
|
||||
|
||||
task, err := exp.TaskByIdentifier(ctx, identifier)
|
||||
task, err := client.TaskByIdentifier(ctx, identifier)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -107,7 +106,7 @@ func (r *RootCmd) taskStatus() *serpent.Command {
|
||||
// TODO: implement streaming updates instead of polling
|
||||
lastStatusRow := tsr
|
||||
for range t.C {
|
||||
task, err := exp.TaskByID(ctx, task.ID)
|
||||
task, err := client.TaskByID(ctx, task.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ func Test_TaskStatus(t *testing.T) {
|
||||
hf: func(ctx context.Context, _ time.Time) func(w http.ResponseWriter, r *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.URL.Path {
|
||||
case "/api/experimental/tasks/me/doesnotexist":
|
||||
case "/api/v2/tasks/me/doesnotexist":
|
||||
httpapi.ResourceNotFound(w)
|
||||
return
|
||||
default:
|
||||
@@ -52,7 +52,7 @@ func Test_TaskStatus(t *testing.T) {
|
||||
hf: func(ctx context.Context, now time.Time) func(w http.ResponseWriter, r *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.URL.Path {
|
||||
case "/api/experimental/tasks/me/exists":
|
||||
case "/api/v2/tasks/me/exists":
|
||||
httpapi.Write(ctx, w, http.StatusOK, codersdk.Task{
|
||||
ID: uuid.MustParse("11111111-1111-1111-1111-111111111111"),
|
||||
WorkspaceStatus: codersdk.WorkspaceStatusRunning,
|
||||
@@ -88,7 +88,7 @@ func Test_TaskStatus(t *testing.T) {
|
||||
var calls atomic.Int64
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.URL.Path {
|
||||
case "/api/experimental/tasks/me/exists":
|
||||
case "/api/v2/tasks/me/exists":
|
||||
httpapi.Write(ctx, w, http.StatusOK, codersdk.Task{
|
||||
ID: uuid.MustParse("11111111-1111-1111-1111-111111111111"),
|
||||
Name: "exists",
|
||||
@@ -103,7 +103,7 @@ func Test_TaskStatus(t *testing.T) {
|
||||
Status: codersdk.TaskStatusPending,
|
||||
})
|
||||
return
|
||||
case "/api/experimental/tasks/me/11111111-1111-1111-1111-111111111111":
|
||||
case "/api/v2/tasks/me/11111111-1111-1111-1111-111111111111":
|
||||
defer calls.Add(1)
|
||||
switch calls.Load() {
|
||||
case 0:
|
||||
@@ -219,7 +219,7 @@ func Test_TaskStatus(t *testing.T) {
|
||||
ts := time.Date(2025, 8, 26, 12, 34, 56, 0, time.UTC)
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.URL.Path {
|
||||
case "/api/experimental/tasks/me/exists":
|
||||
case "/api/v2/tasks/me/exists":
|
||||
httpapi.Write(ctx, w, http.StatusOK, codersdk.Task{
|
||||
ID: uuid.MustParse("11111111-1111-1111-1111-111111111111"),
|
||||
Name: "exists",
|
||||
|
||||
+2
-4
@@ -122,8 +122,7 @@ func Test_Tasks(t *testing.T) {
|
||||
assertFn: func(stdout string, userClient *codersdk.Client) {
|
||||
// The task should eventually no longer show up in the list of tasks
|
||||
testutil.Eventually(ctx, t, func(ctx context.Context) bool {
|
||||
expClient := codersdk.NewExperimentalClient(userClient)
|
||||
tasks, err := expClient.Tasks(ctx, &codersdk.TasksFilter{})
|
||||
tasks, err := userClient.Tasks(ctx, &codersdk.TasksFilter{})
|
||||
if !assert.NoError(t, err) {
|
||||
return false
|
||||
}
|
||||
@@ -248,8 +247,7 @@ func setupCLITaskTest(ctx context.Context, t *testing.T, agentAPIHandlers map[st
|
||||
template := createAITaskTemplate(t, client, owner.OrganizationID, withSidebarURL(fakeAPI.URL()), withAgentToken(authToken))
|
||||
|
||||
wantPrompt := "test prompt"
|
||||
exp := codersdk.NewExperimentalClient(userClient)
|
||||
task, err := exp.CreateTask(ctx, codersdk.Me, codersdk.CreateTaskRequest{
|
||||
task, err := userClient.CreateTask(ctx, codersdk.Me, codersdk.CreateTaskRequest{
|
||||
TemplateVersionID: template.ActiveVersionID,
|
||||
Input: wantPrompt,
|
||||
Name: "test-task",
|
||||
|
||||
+25
-53
@@ -31,17 +31,15 @@ import (
|
||||
)
|
||||
|
||||
// @Summary Create a new AI task
|
||||
// @Description: EXPERIMENTAL: this endpoint is experimental and not guaranteed to be stable.
|
||||
// @ID create-task
|
||||
// @ID create-a-new-ai-task
|
||||
// @Security CoderSessionToken
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Tags Experimental
|
||||
// @Param user path string true "Username, user ID, or 'me' for the authenticated user"
|
||||
// @Param request body codersdk.CreateTaskRequest true "Create task request"
|
||||
// @Success 201 {object} codersdk.Task
|
||||
// @Router /api/experimental/tasks/{user} [post]
|
||||
//
|
||||
// EXPERIMENTAL: This endpoint is experimental and not guaranteed to be stable.
|
||||
// This endpoint creates a new task for the given user.
|
||||
// @Router /tasks/{user} [post]
|
||||
func (api *API) tasksCreate(rw http.ResponseWriter, r *http.Request) {
|
||||
var (
|
||||
ctx = r.Context()
|
||||
@@ -400,16 +398,13 @@ func deriveTaskCurrentState(
|
||||
}
|
||||
|
||||
// @Summary List AI tasks
|
||||
// @Description: EXPERIMENTAL: this endpoint is experimental and not guaranteed to be stable.
|
||||
// @ID list-tasks
|
||||
// @ID list-ai-tasks
|
||||
// @Security CoderSessionToken
|
||||
// @Produce json
|
||||
// @Tags Experimental
|
||||
// @Param q query string false "Search query for filtering tasks. Supports: owner:<username/uuid/me>, organization:<org-name/uuid>, status:<status>"
|
||||
// @Success 200 {object} codersdk.TasksListResponse
|
||||
// @Router /api/experimental/tasks [get]
|
||||
//
|
||||
// EXPERIMENTAL: This endpoint is experimental and not guaranteed to be stable.
|
||||
// tasksList is an experimental endpoint to list tasks.
|
||||
// @Router /tasks [get]
|
||||
func (api *API) tasksList(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
apiKey := httpmw.APIKey(r)
|
||||
@@ -502,20 +497,15 @@ func (api *API) convertTasks(ctx context.Context, requesterID uuid.UUID, dbTasks
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// @Summary Get AI task by ID
|
||||
// @Description: EXPERIMENTAL: this endpoint is experimental and not guaranteed to be stable.
|
||||
// @ID get-task
|
||||
// @Summary Get AI task by ID or name
|
||||
// @ID get-ai-task-by-id-or-name
|
||||
// @Security CoderSessionToken
|
||||
// @Produce json
|
||||
// @Tags Experimental
|
||||
// @Param user path string true "Username, user ID, or 'me' for the authenticated user"
|
||||
// @Param task path string true "Task ID, or task name"
|
||||
// @Success 200 {object} codersdk.Task
|
||||
// @Router /api/experimental/tasks/{user}/{task} [get]
|
||||
//
|
||||
// EXPERIMENTAL: This endpoint is experimental and not guaranteed to be stable.
|
||||
// taskGet is an experimental endpoint to fetch a single AI task by ID
|
||||
// (workspace ID). It returns a synthesized task response including
|
||||
// prompt and status.
|
||||
// @Router /tasks/{user}/{task} [get]
|
||||
func (api *API) taskGet(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
apiKey := httpmw.APIKey(r)
|
||||
@@ -580,20 +570,14 @@ func (api *API) taskGet(rw http.ResponseWriter, r *http.Request) {
|
||||
httpapi.Write(ctx, rw, http.StatusOK, taskResp)
|
||||
}
|
||||
|
||||
// @Summary Delete AI task by ID
|
||||
// @Description: EXPERIMENTAL: this endpoint is experimental and not guaranteed to be stable.
|
||||
// @ID delete-task
|
||||
// @Summary Delete AI task
|
||||
// @ID delete-ai-task
|
||||
// @Security CoderSessionToken
|
||||
// @Tags Experimental
|
||||
// @Param user path string true "Username, user ID, or 'me' for the authenticated user"
|
||||
// @Param task path string true "Task ID, or task name"
|
||||
// @Success 202 "Task deletion initiated"
|
||||
// @Router /api/experimental/tasks/{user}/{task} [delete]
|
||||
//
|
||||
// EXPERIMENTAL: This endpoint is experimental and not guaranteed to be stable.
|
||||
// taskDelete is an experimental endpoint to delete a task by ID.
|
||||
// It creates a delete workspace build and returns 202 Accepted if the build was
|
||||
// created.
|
||||
// @Success 202
|
||||
// @Router /tasks/{user}/{task} [delete]
|
||||
func (api *API) taskDelete(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
apiKey := httpmw.APIKey(r)
|
||||
@@ -655,18 +639,15 @@ func (api *API) taskDelete(rw http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// @Summary Update AI task input
|
||||
// @Description: EXPERIMENTAL: this endpoint is experimental and not guaranteed to be stable.
|
||||
// @ID update-task-input
|
||||
// @ID update-ai-task-input
|
||||
// @Security CoderSessionToken
|
||||
// @Accept json
|
||||
// @Tags Experimental
|
||||
// @Param user path string true "Username, user ID, or 'me' for the authenticated user"
|
||||
// @Param task path string true "Task ID, or task name"
|
||||
// @Param request body codersdk.UpdateTaskInputRequest true "Update task input request"
|
||||
// @Success 204
|
||||
// @Router /api/experimental/tasks/{user}/{task}/input [patch]
|
||||
//
|
||||
// EXPERIMENTAL: This endpoint is experimental and not guaranteed to be stable.
|
||||
// taskUpdateInput allows modifying a task's prompt before the agent executes it.
|
||||
// @Router /tasks/{user}/{task}/input [patch]
|
||||
func (api *API) taskUpdateInput(rw http.ResponseWriter, r *http.Request) {
|
||||
var (
|
||||
ctx = r.Context()
|
||||
@@ -738,20 +719,15 @@ func (api *API) taskUpdateInput(rw http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// @Summary Send input to AI task
|
||||
// @Description: EXPERIMENTAL: this endpoint is experimental and not guaranteed to be stable.
|
||||
// @ID send-task-input
|
||||
// @ID send-input-to-ai-task
|
||||
// @Security CoderSessionToken
|
||||
// @Accept json
|
||||
// @Tags Experimental
|
||||
// @Param user path string true "Username, user ID, or 'me' for the authenticated user"
|
||||
// @Param task path string true "Task ID, or task name"
|
||||
// @Param request body codersdk.TaskSendRequest true "Task input request"
|
||||
// @Success 204 "Input sent successfully"
|
||||
// @Router /api/experimental/tasks/{user}/{task}/send [post]
|
||||
//
|
||||
// EXPERIMENTAL: This endpoint is experimental and not guaranteed to be stable.
|
||||
// taskSend submits task input to the task app by dialing the agent
|
||||
// directly over the tailnet. We enforce ApplicationConnect RBAC on the
|
||||
// workspace and validate the task app health.
|
||||
// @Success 204
|
||||
// @Router /tasks/{user}/{task}/send [post]
|
||||
func (api *API) taskSend(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
task := httpmw.TaskParam(r)
|
||||
@@ -812,18 +788,14 @@ func (api *API) taskSend(rw http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// @Summary Get AI task logs
|
||||
// @Description: EXPERIMENTAL: this endpoint is experimental and not guaranteed to be stable.
|
||||
// @ID get-task-logs
|
||||
// @ID get-ai-task-logs
|
||||
// @Security CoderSessionToken
|
||||
// @Produce json
|
||||
// @Tags Experimental
|
||||
// @Param user path string true "Username, user ID, or 'me' for the authenticated user"
|
||||
// @Param task path string true "Task ID, or task name"
|
||||
// @Success 200 {object} codersdk.TaskLogsResponse
|
||||
// @Router /api/experimental/tasks/{user}/{task}/logs [get]
|
||||
//
|
||||
// EXPERIMENTAL: This endpoint is experimental and not guaranteed to be stable.
|
||||
// taskLogs reads task output by dialing the agent directly over the tailnet.
|
||||
// We enforce ApplicationConnect RBAC on the workspace and validate the task app health.
|
||||
// @Router /tasks/{user}/{task}/logs [get]
|
||||
func (api *API) taskLogs(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
task := httpmw.TaskParam(r)
|
||||
|
||||
+56
-91
@@ -124,8 +124,7 @@ func TestTasks(t *testing.T) {
|
||||
|
||||
// Create a task with a specific prompt using the new data model.
|
||||
wantPrompt := "build me a web app"
|
||||
exp := codersdk.NewExperimentalClient(client)
|
||||
task, err := exp.CreateTask(ctx, codersdk.Me, codersdk.CreateTaskRequest{
|
||||
task, err := client.CreateTask(ctx, codersdk.Me, codersdk.CreateTaskRequest{
|
||||
TemplateVersionID: template.ActiveVersionID,
|
||||
Input: wantPrompt,
|
||||
})
|
||||
@@ -141,7 +140,7 @@ func TestTasks(t *testing.T) {
|
||||
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID)
|
||||
|
||||
// List tasks via experimental API and verify the prompt and status mapping.
|
||||
tasks, err := exp.Tasks(ctx, &codersdk.TasksFilter{Owner: codersdk.Me})
|
||||
tasks, err := client.Tasks(ctx, &codersdk.TasksFilter{Owner: codersdk.Me})
|
||||
require.NoError(t, err)
|
||||
|
||||
got, ok := slice.Find(tasks, func(t codersdk.Task) bool { return t.ID == task.ID })
|
||||
@@ -164,10 +163,9 @@ func TestTasks(t *testing.T) {
|
||||
anotherUser, _ = coderdtest.CreateAnotherUser(t, client, user.OrganizationID)
|
||||
template = createAITemplate(t, client, user)
|
||||
wantPrompt = "review my code"
|
||||
exp = codersdk.NewExperimentalClient(client)
|
||||
)
|
||||
|
||||
task, err := exp.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
task, err := client.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
TemplateVersionID: template.ActiveVersionID,
|
||||
Input: wantPrompt,
|
||||
})
|
||||
@@ -201,7 +199,7 @@ func TestTasks(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// Fetch the task by ID via experimental API and verify fields.
|
||||
updated, err := exp.TaskByID(ctx, task.ID)
|
||||
updated, err := client.TaskByID(ctx, task.ID)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, task.ID, updated.ID, "task ID should match")
|
||||
@@ -215,19 +213,18 @@ func TestTasks(t *testing.T) {
|
||||
assert.NotEmpty(t, updated.WorkspaceStatus, "task status should not be empty")
|
||||
|
||||
// Fetch the task by name and verify the same result
|
||||
byName, err := exp.TaskByOwnerAndName(ctx, codersdk.Me, task.Name)
|
||||
byName, err := client.TaskByOwnerAndName(ctx, codersdk.Me, task.Name)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, byName, updated)
|
||||
|
||||
// Another member user should not be able to fetch the task
|
||||
otherClient := codersdk.NewExperimentalClient(anotherUser)
|
||||
_, err = otherClient.TaskByID(ctx, task.ID)
|
||||
_, err = anotherUser.TaskByID(ctx, task.ID)
|
||||
require.Error(t, err, "fetching task should fail by ID for another member user")
|
||||
var sdkErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &sdkErr)
|
||||
require.Equal(t, http.StatusNotFound, sdkErr.StatusCode())
|
||||
// Also test by name
|
||||
_, err = otherClient.TaskByOwnerAndName(ctx, task.OwnerName, task.Name)
|
||||
_, err = anotherUser.TaskByOwnerAndName(ctx, task.OwnerName, task.Name)
|
||||
require.Error(t, err, "fetching task should fail by name for another member user")
|
||||
require.ErrorAs(t, err, &sdkErr)
|
||||
require.Equal(t, http.StatusNotFound, sdkErr.StatusCode())
|
||||
@@ -236,7 +233,7 @@ func TestTasks(t *testing.T) {
|
||||
coderdtest.MustTransitionWorkspace(t, client, task.WorkspaceID.UUID, codersdk.WorkspaceTransitionStart, codersdk.WorkspaceTransitionStop)
|
||||
|
||||
// Verify that the previous status still remains
|
||||
updated, err = exp.TaskByID(ctx, task.ID)
|
||||
updated, err = client.TaskByID(ctx, task.ID)
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, updated.CurrentState, "current state should not be nil")
|
||||
assert.Equal(t, "all done", updated.CurrentState.Message)
|
||||
@@ -248,7 +245,7 @@ func TestTasks(t *testing.T) {
|
||||
|
||||
// Verify that the status from the previous build has been cleared
|
||||
// and replaced by the agent initialization status.
|
||||
updated, err = exp.TaskByID(ctx, task.ID)
|
||||
updated, err = client.TaskByID(ctx, task.ID)
|
||||
require.NoError(t, err)
|
||||
assert.NotEqual(t, previousCurrentState, updated.CurrentState)
|
||||
assert.Equal(t, codersdk.TaskStateWorking, updated.CurrentState.State)
|
||||
@@ -267,8 +264,7 @@ func TestTasks(t *testing.T) {
|
||||
|
||||
ctx := testutil.Context(t, testutil.WaitLong)
|
||||
|
||||
exp := codersdk.NewExperimentalClient(client)
|
||||
task, err := exp.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
task, err := client.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
TemplateVersionID: template.ActiveVersionID,
|
||||
Input: "delete me",
|
||||
})
|
||||
@@ -281,7 +277,7 @@ func TestTasks(t *testing.T) {
|
||||
}
|
||||
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, ws.LatestBuild.ID)
|
||||
|
||||
err = exp.DeleteTask(ctx, "me", task.ID)
|
||||
err = client.DeleteTask(ctx, "me", task.ID)
|
||||
require.NoError(t, err, "delete task request should be accepted")
|
||||
|
||||
// Poll until the workspace is deleted.
|
||||
@@ -303,8 +299,7 @@ func TestTasks(t *testing.T) {
|
||||
|
||||
ctx := testutil.Context(t, testutil.WaitShort)
|
||||
|
||||
exp := codersdk.NewExperimentalClient(client)
|
||||
err := exp.DeleteTask(ctx, "me", uuid.New())
|
||||
err := client.DeleteTask(ctx, "me", uuid.New())
|
||||
|
||||
var sdkErr *codersdk.Error
|
||||
require.Error(t, err, "expected an error for non-existent task")
|
||||
@@ -330,8 +325,7 @@ func TestTasks(t *testing.T) {
|
||||
}
|
||||
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, ws.LatestBuild.ID)
|
||||
|
||||
exp := codersdk.NewExperimentalClient(client)
|
||||
err := exp.DeleteTask(ctx, "me", ws.ID)
|
||||
err := client.DeleteTask(ctx, "me", ws.ID)
|
||||
|
||||
var sdkErr *codersdk.Error
|
||||
require.Error(t, err, "expected an error for non-task workspace delete via tasks endpoint")
|
||||
@@ -350,8 +344,7 @@ func TestTasks(t *testing.T) {
|
||||
|
||||
ctx := testutil.Context(t, testutil.WaitShort)
|
||||
|
||||
exp := codersdk.NewExperimentalClient(client)
|
||||
task, err := exp.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
task, err := client.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
TemplateVersionID: template.ActiveVersionID,
|
||||
Input: "delete me not",
|
||||
})
|
||||
@@ -363,10 +356,9 @@ func TestTasks(t *testing.T) {
|
||||
|
||||
// Another regular org member without elevated permissions.
|
||||
otherClient, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
|
||||
expOther := codersdk.NewExperimentalClient(otherClient)
|
||||
|
||||
// Attempt to delete the owner's task as a non-owner without permissions.
|
||||
err = expOther.DeleteTask(ctx, "me", task.ID)
|
||||
err = otherClient.DeleteTask(ctx, "me", task.ID)
|
||||
|
||||
var authErr *codersdk.Error
|
||||
require.Error(t, err, "expected an authorization error when deleting another user's task")
|
||||
@@ -384,8 +376,7 @@ func TestTasks(t *testing.T) {
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
template := createAITemplate(t, client, user)
|
||||
ctx := testutil.Context(t, testutil.WaitLong)
|
||||
exp := codersdk.NewExperimentalClient(client)
|
||||
task, err := exp.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
task, err := client.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
TemplateVersionID: template.ActiveVersionID,
|
||||
Input: "delete me",
|
||||
})
|
||||
@@ -404,9 +395,9 @@ func TestTasks(t *testing.T) {
|
||||
// Provisionerdserver will attempt delete the related task when deleting a workspace.
|
||||
// This test ensures that we can still handle the case where, for some reason, the
|
||||
// task has not been marked as deleted, but the workspace has.
|
||||
task, err = exp.TaskByID(ctx, task.ID)
|
||||
task, err = client.TaskByID(ctx, task.ID)
|
||||
require.NoError(t, err, "fetching a task should still work if its related workspace is deleted")
|
||||
err = exp.DeleteTask(ctx, task.OwnerID.String(), task.ID)
|
||||
err = client.DeleteTask(ctx, task.OwnerID.String(), task.ID)
|
||||
require.NoError(t, err, "should be possible to delete a task with no workspace")
|
||||
})
|
||||
|
||||
@@ -419,8 +410,7 @@ func TestTasks(t *testing.T) {
|
||||
|
||||
ctx := testutil.Context(t, testutil.WaitLong)
|
||||
|
||||
exp := codersdk.NewExperimentalClient(client)
|
||||
task, err := exp.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
task, err := client.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
TemplateVersionID: template.ActiveVersionID,
|
||||
Input: "delete me",
|
||||
})
|
||||
@@ -436,7 +426,7 @@ func TestTasks(t *testing.T) {
|
||||
// When; the task workspace is deleted
|
||||
coderdtest.MustTransitionWorkspace(t, client, ws.ID, codersdk.WorkspaceTransitionStart, codersdk.WorkspaceTransitionDelete)
|
||||
// Then: the task associated with the workspace is also deleted
|
||||
_, err = exp.TaskByID(ctx, task.ID)
|
||||
_, err = client.TaskByID(ctx, task.ID)
|
||||
require.Error(t, err, "expected an error fetching the task")
|
||||
var sdkErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &sdkErr, "expected a codersdk.Error")
|
||||
@@ -495,10 +485,9 @@ func TestTasks(t *testing.T) {
|
||||
userClient, _ = coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
|
||||
agentAuthToken = uuid.NewString()
|
||||
template = createAITemplate(t, client, owner, withAgentToken(agentAuthToken), withSidebarURL(srv.URL))
|
||||
exp = codersdk.NewExperimentalClient(userClient)
|
||||
)
|
||||
|
||||
task, err := exp.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
task, err := userClient.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
TemplateVersionID: template.ActiveVersionID,
|
||||
Input: "send me food",
|
||||
})
|
||||
@@ -511,7 +500,7 @@ func TestTasks(t *testing.T) {
|
||||
coderdtest.AwaitWorkspaceBuildJobCompleted(t, userClient, ws.LatestBuild.ID)
|
||||
|
||||
// Fetch the task by ID via experimental API and verify fields.
|
||||
task, err = exp.TaskByID(ctx, task.ID)
|
||||
task, err = client.TaskByID(ctx, task.ID)
|
||||
require.NoError(t, err)
|
||||
require.NotZero(t, task.WorkspaceBuildNumber)
|
||||
require.True(t, task.WorkspaceAgentID.Valid)
|
||||
@@ -537,7 +526,7 @@ func TestTasks(t *testing.T) {
|
||||
coderdtest.NewWorkspaceAgentWaiter(t, userClient, ws.ID).WaitFor(coderdtest.AgentsReady)
|
||||
|
||||
// Fetch the task by ID via experimental API and verify fields.
|
||||
task, err = exp.TaskByID(ctx, task.ID)
|
||||
task, err = client.TaskByID(ctx, task.ID)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Make the sidebar app unhealthy initially.
|
||||
@@ -547,7 +536,7 @@ func TestTasks(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
err = exp.TaskSend(ctx, "me", task.ID, codersdk.TaskSendRequest{
|
||||
err = client.TaskSend(ctx, "me", task.ID, codersdk.TaskSendRequest{
|
||||
Input: "Hello, Agent!",
|
||||
})
|
||||
require.Error(t, err, "wanted error due to unhealthy sidebar app")
|
||||
@@ -561,7 +550,7 @@ func TestTasks(t *testing.T) {
|
||||
|
||||
statusResponse = agentapisdk.AgentStatus("bad")
|
||||
|
||||
err = exp.TaskSend(ctx, "me", task.ID, codersdk.TaskSendRequest{
|
||||
err = client.TaskSend(ctx, "me", task.ID, codersdk.TaskSendRequest{
|
||||
Input: "Hello, Agent!",
|
||||
})
|
||||
require.Error(t, err, "wanted error due to bad status")
|
||||
@@ -570,7 +559,7 @@ func TestTasks(t *testing.T) {
|
||||
|
||||
//nolint:tparallel // Not intended to run in parallel.
|
||||
t.Run("SendOK", func(t *testing.T) {
|
||||
err = exp.TaskSend(ctx, "me", task.ID, codersdk.TaskSendRequest{
|
||||
err = client.TaskSend(ctx, "me", task.ID, codersdk.TaskSendRequest{
|
||||
Input: "Hello, Agent!",
|
||||
})
|
||||
require.NoError(t, err, "wanted no error due to healthy sidebar app and stable status")
|
||||
@@ -578,7 +567,7 @@ func TestTasks(t *testing.T) {
|
||||
|
||||
//nolint:tparallel // Not intended to run in parallel.
|
||||
t.Run("MissingContent", func(t *testing.T) {
|
||||
err = exp.TaskSend(ctx, "me", task.ID, codersdk.TaskSendRequest{
|
||||
err = client.TaskSend(ctx, "me", task.ID, codersdk.TaskSendRequest{
|
||||
Input: "",
|
||||
})
|
||||
require.Error(t, err, "wanted error due to missing content")
|
||||
@@ -596,8 +585,7 @@ func TestTasks(t *testing.T) {
|
||||
_ = coderdtest.CreateFirstUser(t, client)
|
||||
ctx := testutil.Context(t, testutil.WaitShort)
|
||||
|
||||
exp := codersdk.NewExperimentalClient(client)
|
||||
err := exp.TaskSend(ctx, "me", uuid.New(), codersdk.TaskSendRequest{
|
||||
err := client.TaskSend(ctx, "me", uuid.New(), codersdk.TaskSendRequest{
|
||||
Input: "hi",
|
||||
})
|
||||
|
||||
@@ -663,10 +651,9 @@ func TestTasks(t *testing.T) {
|
||||
owner = coderdtest.CreateFirstUser(t, client)
|
||||
agentAuthToken = uuid.NewString()
|
||||
template = createAITemplate(t, client, owner, withAgentToken(agentAuthToken), withSidebarURL(srv.URL))
|
||||
exp = codersdk.NewExperimentalClient(client)
|
||||
)
|
||||
|
||||
task, err := exp.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
task, err := client.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
TemplateVersionID: template.ActiveVersionID,
|
||||
Input: "show logs",
|
||||
})
|
||||
@@ -679,7 +666,7 @@ func TestTasks(t *testing.T) {
|
||||
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, ws.LatestBuild.ID)
|
||||
|
||||
// Fetch the task by ID via experimental API and verify fields.
|
||||
task, err = exp.TaskByIdentifier(ctx, task.ID.String())
|
||||
task, err = client.TaskByIdentifier(ctx, task.ID.String())
|
||||
require.NoError(t, err)
|
||||
require.NotZero(t, task.WorkspaceBuildNumber)
|
||||
require.True(t, task.WorkspaceAgentID.Valid)
|
||||
@@ -705,13 +692,13 @@ func TestTasks(t *testing.T) {
|
||||
coderdtest.NewWorkspaceAgentWaiter(t, client, ws.ID).WaitFor(coderdtest.AgentsReady)
|
||||
|
||||
// Fetch the task by ID via experimental API and verify fields.
|
||||
task, err = exp.TaskByID(ctx, task.ID)
|
||||
task, err = client.TaskByID(ctx, task.ID)
|
||||
require.NoError(t, err)
|
||||
|
||||
//nolint:tparallel // Not intended to run in parallel.
|
||||
t.Run("OK", func(t *testing.T) {
|
||||
// Fetch logs.
|
||||
resp, err := exp.TaskLogs(ctx, "me", task.ID)
|
||||
resp, err := client.TaskLogs(ctx, "me", task.ID)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, resp.Logs, 3)
|
||||
assert.Equal(t, 0, resp.Logs[0].ID)
|
||||
@@ -731,7 +718,7 @@ func TestTasks(t *testing.T) {
|
||||
t.Run("UpstreamError", func(t *testing.T) {
|
||||
shouldReturnError = true
|
||||
t.Cleanup(func() { shouldReturnError = false })
|
||||
_, err := exp.TaskLogs(ctx, "me", task.ID)
|
||||
_, err := client.TaskLogs(ctx, "me", task.ID)
|
||||
|
||||
var sdkErr *codersdk.Error
|
||||
require.Error(t, err)
|
||||
@@ -811,8 +798,7 @@ func TestTasks(t *testing.T) {
|
||||
}
|
||||
|
||||
// Given: We create a task
|
||||
exp := codersdk.NewExperimentalClient(client)
|
||||
task, err := exp.CreateTask(ctx, codersdk.Me, codersdk.CreateTaskRequest{
|
||||
task, err := client.CreateTask(ctx, codersdk.Me, codersdk.CreateTaskRequest{
|
||||
TemplateVersionID: template.ActiveVersionID,
|
||||
Input: "initial prompt",
|
||||
})
|
||||
@@ -844,17 +830,17 @@ func TestTasks(t *testing.T) {
|
||||
}
|
||||
|
||||
if tt.deleteTask {
|
||||
err = exp.DeleteTask(ctx, codersdk.Me, task.ID)
|
||||
err = client.DeleteTask(ctx, codersdk.Me, task.ID)
|
||||
require.NoError(t, err)
|
||||
} else {
|
||||
// Given: Task has expected status
|
||||
task, err = exp.TaskByID(ctx, task.ID)
|
||||
task, err = client.TaskByID(ctx, task.ID)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tt.wantStatus, task.Status)
|
||||
}
|
||||
|
||||
// When: We attempt to update the task input
|
||||
err = exp.UpdateTaskInput(ctx, task.OwnerName, task.ID, codersdk.UpdateTaskInputRequest{
|
||||
err = client.UpdateTaskInput(ctx, task.OwnerName, task.ID, codersdk.UpdateTaskInputRequest{
|
||||
Input: tt.taskInput,
|
||||
})
|
||||
if tt.wantErr != "" {
|
||||
@@ -868,7 +854,7 @@ func TestTasks(t *testing.T) {
|
||||
|
||||
if !tt.deleteTask {
|
||||
// Then: We expect the input to **not** be updated
|
||||
task, err = exp.TaskByID(ctx, task.ID)
|
||||
task, err = client.TaskByID(ctx, task.ID)
|
||||
require.NoError(t, err)
|
||||
require.NotEqual(t, tt.taskInput, task.InitialPrompt)
|
||||
}
|
||||
@@ -877,7 +863,7 @@ func TestTasks(t *testing.T) {
|
||||
|
||||
if !tt.deleteTask {
|
||||
// Then: We expect the input to be updated
|
||||
task, err = exp.TaskByID(ctx, task.ID)
|
||||
task, err = client.TaskByID(ctx, task.ID)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tt.taskInput, task.InitialPrompt)
|
||||
}
|
||||
@@ -892,10 +878,8 @@ func TestTasks(t *testing.T) {
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
ctx := testutil.Context(t, testutil.WaitShort)
|
||||
|
||||
exp := codersdk.NewExperimentalClient(client)
|
||||
|
||||
// Attempt to update prompt for non-existent task
|
||||
err := exp.UpdateTaskInput(ctx, user.UserID.String(), uuid.New(), codersdk.UpdateTaskInputRequest{
|
||||
err := client.UpdateTaskInput(ctx, user.UserID.String(), uuid.New(), codersdk.UpdateTaskInputRequest{
|
||||
Input: "Should fail",
|
||||
})
|
||||
require.Error(t, err)
|
||||
@@ -915,8 +899,7 @@ func TestTasks(t *testing.T) {
|
||||
template := createAITemplate(t, client, user)
|
||||
|
||||
// Create a task as the first user
|
||||
exp := codersdk.NewExperimentalClient(client)
|
||||
task, err := exp.CreateTask(ctx, codersdk.Me, codersdk.CreateTaskRequest{
|
||||
task, err := client.CreateTask(ctx, codersdk.Me, codersdk.CreateTaskRequest{
|
||||
TemplateVersionID: template.ActiveVersionID,
|
||||
Input: "initial prompt",
|
||||
})
|
||||
@@ -933,8 +916,7 @@ func TestTasks(t *testing.T) {
|
||||
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, build.ID)
|
||||
|
||||
// Attempt to update prompt as another user should fail with 404 Not Found
|
||||
otherExp := codersdk.NewExperimentalClient(anotherUser)
|
||||
err = otherExp.UpdateTaskInput(ctx, task.OwnerName, task.ID, codersdk.UpdateTaskInputRequest{
|
||||
err = anotherUser.UpdateTaskInput(ctx, task.OwnerName, task.ID, codersdk.UpdateTaskInputRequest{
|
||||
Input: "Should fail - unauthorized",
|
||||
})
|
||||
require.Error(t, err)
|
||||
@@ -972,9 +954,7 @@ func TestTasksCreate(t *testing.T) {
|
||||
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
|
||||
expClient := codersdk.NewExperimentalClient(client)
|
||||
|
||||
task, err := expClient.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
task, err := client.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
TemplateVersionID: template.ActiveVersionID,
|
||||
Input: taskPrompt,
|
||||
})
|
||||
@@ -1019,10 +999,8 @@ func TestTasksCreate(t *testing.T) {
|
||||
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
|
||||
expClient := codersdk.NewExperimentalClient(client)
|
||||
|
||||
// When: We attempt to create a Task.
|
||||
task, err := expClient.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
task, err := client.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
TemplateVersionID: template.ActiveVersionID,
|
||||
Input: taskPrompt,
|
||||
})
|
||||
@@ -1107,11 +1085,10 @@ func TestTasksCreate(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{
|
||||
ctx = testutil.Context(t, testutil.WaitShort)
|
||||
client = coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
||||
user = coderdtest.CreateFirstUser(t, client)
|
||||
version = coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
Parse: echo.ParseComplete,
|
||||
ProvisionApply: echo.ApplyComplete,
|
||||
ProvisionPlan: []*proto.Response{
|
||||
@@ -1126,7 +1103,7 @@ func TestTasksCreate(t *testing.T) {
|
||||
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
|
||||
|
||||
// When: We attempt to create a Task.
|
||||
task, err := expClient.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
task, err := client.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
TemplateVersionID: template.ActiveVersionID,
|
||||
Input: "Some prompt",
|
||||
Name: tt.taskName,
|
||||
@@ -1177,10 +1154,8 @@ func TestTasksCreate(t *testing.T) {
|
||||
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
|
||||
expClient := codersdk.NewExperimentalClient(client)
|
||||
|
||||
// When: We attempt to create a Task.
|
||||
_, err := expClient.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
_, err := client.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
TemplateVersionID: template.ActiveVersionID,
|
||||
Input: taskPrompt,
|
||||
})
|
||||
@@ -1209,10 +1184,8 @@ func TestTasksCreate(t *testing.T) {
|
||||
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
|
||||
_ = coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
|
||||
expClient := codersdk.NewExperimentalClient(client)
|
||||
|
||||
// When: We attempt to create a Task with an invalid template version ID.
|
||||
_, err := expClient.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
_, err := client.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
TemplateVersionID: uuid.New(),
|
||||
Input: taskPrompt,
|
||||
})
|
||||
@@ -1248,9 +1221,7 @@ func TestTasksCreate(t *testing.T) {
|
||||
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
|
||||
expClient := codersdk.NewExperimentalClient(client)
|
||||
|
||||
task, err := expClient.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
task, err := client.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
TemplateVersionID: template.ActiveVersionID,
|
||||
Input: taskPrompt,
|
||||
})
|
||||
@@ -1307,9 +1278,7 @@ func TestTasksCreate(t *testing.T) {
|
||||
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
|
||||
expClient := codersdk.NewExperimentalClient(client)
|
||||
|
||||
task, err := expClient.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
task, err := client.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
TemplateVersionID: template.ActiveVersionID,
|
||||
Input: taskPrompt,
|
||||
Name: taskName,
|
||||
@@ -1343,16 +1312,14 @@ func TestTasksCreate(t *testing.T) {
|
||||
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
|
||||
expClient := codersdk.NewExperimentalClient(client)
|
||||
|
||||
task1, err := expClient.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
task1, err := client.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
TemplateVersionID: template.ActiveVersionID,
|
||||
Input: "First task",
|
||||
Name: "task-1",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
task2, err := expClient.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
task2, err := client.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
TemplateVersionID: template.ActiveVersionID,
|
||||
Input: "Second task",
|
||||
Name: "task-2",
|
||||
@@ -1406,11 +1373,9 @@ func TestTasksCreate(t *testing.T) {
|
||||
}, template.ID)
|
||||
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version2.ID)
|
||||
|
||||
expClient := codersdk.NewExperimentalClient(client)
|
||||
|
||||
// Create a task using version 2 to verify the template_version_id is
|
||||
// stored correctly.
|
||||
task, err := expClient.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
task, err := client.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
TemplateVersionID: version2.ID,
|
||||
Input: "Use version 2",
|
||||
})
|
||||
|
||||
Generated
+288
-267
@@ -136,273 +136,6 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/experimental/tasks": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Experimental"
|
||||
],
|
||||
"summary": "List AI tasks",
|
||||
"operationId": "list-tasks",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Search query for filtering tasks. Supports: owner:\u003cusername/uuid/me\u003e, organization:\u003corg-name/uuid\u003e, status:\u003cstatus\u003e",
|
||||
"name": "q",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.TasksListResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/experimental/tasks/{user}": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Experimental"
|
||||
],
|
||||
"summary": "Create a new AI task",
|
||||
"operationId": "create-task",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Username, user ID, or 'me' for the authenticated user",
|
||||
"name": "user",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"description": "Create task request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.CreateTaskRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "Created",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.Task"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/experimental/tasks/{user}/{task}": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Experimental"
|
||||
],
|
||||
"summary": "Get AI task by ID",
|
||||
"operationId": "get-task",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Username, user ID, or 'me' for the authenticated user",
|
||||
"name": "user",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Task ID, or task name",
|
||||
"name": "task",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.Task"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Experimental"
|
||||
],
|
||||
"summary": "Delete AI task by ID",
|
||||
"operationId": "delete-task",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Username, user ID, or 'me' for the authenticated user",
|
||||
"name": "user",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Task ID, or task name",
|
||||
"name": "task",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"202": {
|
||||
"description": "Task deletion initiated"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/experimental/tasks/{user}/{task}/input": {
|
||||
"patch": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Experimental"
|
||||
],
|
||||
"summary": "Update AI task input",
|
||||
"operationId": "update-task-input",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Username, user ID, or 'me' for the authenticated user",
|
||||
"name": "user",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Task ID, or task name",
|
||||
"name": "task",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"description": "Update task input request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.UpdateTaskInputRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "No Content"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/experimental/tasks/{user}/{task}/logs": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Experimental"
|
||||
],
|
||||
"summary": "Get AI task logs",
|
||||
"operationId": "get-task-logs",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Username, user ID, or 'me' for the authenticated user",
|
||||
"name": "user",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Task ID, or task name",
|
||||
"name": "task",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.TaskLogsResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/experimental/tasks/{user}/{task}/send": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Experimental"
|
||||
],
|
||||
"summary": "Send input to AI task",
|
||||
"operationId": "send-task-input",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Username, user ID, or 'me' for the authenticated user",
|
||||
"name": "user",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Task ID, or task name",
|
||||
"name": "task",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"description": "Task input request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.TaskSendRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "Input sent successfully"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/appearance": {
|
||||
"get": {
|
||||
"security": [
|
||||
@@ -5719,6 +5452,294 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/tasks": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Experimental"
|
||||
],
|
||||
"summary": "List AI tasks",
|
||||
"operationId": "list-ai-tasks",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Search query for filtering tasks. Supports: owner:\u003cusername/uuid/me\u003e, organization:\u003corg-name/uuid\u003e, status:\u003cstatus\u003e",
|
||||
"name": "q",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.TasksListResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/tasks/{user}": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Experimental"
|
||||
],
|
||||
"summary": "Create a new AI task",
|
||||
"operationId": "create-a-new-ai-task",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Username, user ID, or 'me' for the authenticated user",
|
||||
"name": "user",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"description": "Create task request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.CreateTaskRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "Created",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.Task"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/tasks/{user}/{task}": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Experimental"
|
||||
],
|
||||
"summary": "Get AI task by ID or name",
|
||||
"operationId": "get-ai-task-by-id-or-name",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Username, user ID, or 'me' for the authenticated user",
|
||||
"name": "user",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Task ID, or task name",
|
||||
"name": "task",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.Task"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Experimental"
|
||||
],
|
||||
"summary": "Delete AI task",
|
||||
"operationId": "delete-ai-task",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Username, user ID, or 'me' for the authenticated user",
|
||||
"name": "user",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Task ID, or task name",
|
||||
"name": "task",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"202": {
|
||||
"description": "Accepted"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/tasks/{user}/{task}/input": {
|
||||
"patch": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Experimental"
|
||||
],
|
||||
"summary": "Update AI task input",
|
||||
"operationId": "update-ai-task-input",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Username, user ID, or 'me' for the authenticated user",
|
||||
"name": "user",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Task ID, or task name",
|
||||
"name": "task",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"description": "Update task input request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.UpdateTaskInputRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "No Content"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/tasks/{user}/{task}/logs": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Experimental"
|
||||
],
|
||||
"summary": "Get AI task logs",
|
||||
"operationId": "get-ai-task-logs",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Username, user ID, or 'me' for the authenticated user",
|
||||
"name": "user",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Task ID, or task name",
|
||||
"name": "task",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.TaskLogsResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/tasks/{user}/{task}/send": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Experimental"
|
||||
],
|
||||
"summary": "Send input to AI task",
|
||||
"operationId": "send-input-to-ai-task",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Username, user ID, or 'me' for the authenticated user",
|
||||
"name": "user",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Task ID, or task name",
|
||||
"name": "task",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"description": "Task input request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.TaskSendRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "No Content"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/templates": {
|
||||
"get": {
|
||||
"security": [
|
||||
|
||||
Generated
+260
-253
@@ -112,259 +112,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/experimental/tasks": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"tags": ["Experimental"],
|
||||
"summary": "List AI tasks",
|
||||
"operationId": "list-tasks",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Search query for filtering tasks. Supports: owner:\u003cusername/uuid/me\u003e, organization:\u003corg-name/uuid\u003e, status:\u003cstatus\u003e",
|
||||
"name": "q",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.TasksListResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/experimental/tasks/{user}": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"tags": ["Experimental"],
|
||||
"summary": "Create a new AI task",
|
||||
"operationId": "create-task",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Username, user ID, or 'me' for the authenticated user",
|
||||
"name": "user",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"description": "Create task request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.CreateTaskRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "Created",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.Task"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/experimental/tasks/{user}/{task}": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"tags": ["Experimental"],
|
||||
"summary": "Get AI task by ID",
|
||||
"operationId": "get-task",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Username, user ID, or 'me' for the authenticated user",
|
||||
"name": "user",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Task ID, or task name",
|
||||
"name": "task",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.Task"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"tags": ["Experimental"],
|
||||
"summary": "Delete AI task by ID",
|
||||
"operationId": "delete-task",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Username, user ID, or 'me' for the authenticated user",
|
||||
"name": "user",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Task ID, or task name",
|
||||
"name": "task",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"202": {
|
||||
"description": "Task deletion initiated"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/experimental/tasks/{user}/{task}/input": {
|
||||
"patch": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"tags": ["Experimental"],
|
||||
"summary": "Update AI task input",
|
||||
"operationId": "update-task-input",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Username, user ID, or 'me' for the authenticated user",
|
||||
"name": "user",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Task ID, or task name",
|
||||
"name": "task",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"description": "Update task input request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.UpdateTaskInputRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "No Content"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/experimental/tasks/{user}/{task}/logs": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"tags": ["Experimental"],
|
||||
"summary": "Get AI task logs",
|
||||
"operationId": "get-task-logs",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Username, user ID, or 'me' for the authenticated user",
|
||||
"name": "user",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Task ID, or task name",
|
||||
"name": "task",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.TaskLogsResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/experimental/tasks/{user}/{task}/send": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"tags": ["Experimental"],
|
||||
"summary": "Send input to AI task",
|
||||
"operationId": "send-task-input",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Username, user ID, or 'me' for the authenticated user",
|
||||
"name": "user",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Task ID, or task name",
|
||||
"name": "task",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"description": "Task input request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.TaskSendRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "Input sent successfully"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/appearance": {
|
||||
"get": {
|
||||
"security": [
|
||||
@@ -5064,6 +4811,266 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/tasks": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"produces": ["application/json"],
|
||||
"tags": ["Experimental"],
|
||||
"summary": "List AI tasks",
|
||||
"operationId": "list-ai-tasks",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Search query for filtering tasks. Supports: owner:\u003cusername/uuid/me\u003e, organization:\u003corg-name/uuid\u003e, status:\u003cstatus\u003e",
|
||||
"name": "q",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.TasksListResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/tasks/{user}": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"consumes": ["application/json"],
|
||||
"produces": ["application/json"],
|
||||
"tags": ["Experimental"],
|
||||
"summary": "Create a new AI task",
|
||||
"operationId": "create-a-new-ai-task",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Username, user ID, or 'me' for the authenticated user",
|
||||
"name": "user",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"description": "Create task request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.CreateTaskRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "Created",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.Task"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/tasks/{user}/{task}": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"produces": ["application/json"],
|
||||
"tags": ["Experimental"],
|
||||
"summary": "Get AI task by ID or name",
|
||||
"operationId": "get-ai-task-by-id-or-name",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Username, user ID, or 'me' for the authenticated user",
|
||||
"name": "user",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Task ID, or task name",
|
||||
"name": "task",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.Task"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"tags": ["Experimental"],
|
||||
"summary": "Delete AI task",
|
||||
"operationId": "delete-ai-task",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Username, user ID, or 'me' for the authenticated user",
|
||||
"name": "user",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Task ID, or task name",
|
||||
"name": "task",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"202": {
|
||||
"description": "Accepted"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/tasks/{user}/{task}/input": {
|
||||
"patch": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"consumes": ["application/json"],
|
||||
"tags": ["Experimental"],
|
||||
"summary": "Update AI task input",
|
||||
"operationId": "update-ai-task-input",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Username, user ID, or 'me' for the authenticated user",
|
||||
"name": "user",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Task ID, or task name",
|
||||
"name": "task",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"description": "Update task input request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.UpdateTaskInputRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "No Content"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/tasks/{user}/{task}/logs": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"produces": ["application/json"],
|
||||
"tags": ["Experimental"],
|
||||
"summary": "Get AI task logs",
|
||||
"operationId": "get-ai-task-logs",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Username, user ID, or 'me' for the authenticated user",
|
||||
"name": "user",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Task ID, or task name",
|
||||
"name": "task",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.TaskLogsResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/tasks/{user}/{task}/send": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"consumes": ["application/json"],
|
||||
"tags": ["Experimental"],
|
||||
"summary": "Send input to AI task",
|
||||
"operationId": "send-input-to-ai-task",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Username, user ID, or 'me' for the authenticated user",
|
||||
"name": "user",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Task ID, or task name",
|
||||
"name": "task",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"description": "Task input request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.TaskSendRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "No Content"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/templates": {
|
||||
"get": {
|
||||
"security": [
|
||||
|
||||
@@ -1830,8 +1830,7 @@ func TestExecutorTaskWorkspace(t *testing.T) {
|
||||
createTaskWorkspace := func(t *testing.T, client *codersdk.Client, template codersdk.Template, ctx context.Context, input string) codersdk.Workspace {
|
||||
t.Helper()
|
||||
|
||||
exp := codersdk.NewExperimentalClient(client)
|
||||
task, err := exp.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
task, err := client.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
|
||||
TemplateVersionID: template.ActiveVersionID,
|
||||
Input: input,
|
||||
})
|
||||
|
||||
@@ -1023,6 +1023,9 @@ func New(options *Options) *API {
|
||||
httpmw.ReportCLITelemetry(api.Logger, options.Telemetry),
|
||||
)
|
||||
|
||||
// NOTE(DanielleMaywood):
|
||||
// Tasks have been promoted to stable, but we have guaranteed a single release transition period
|
||||
// where these routes must remain. These should be removed no earlier than Coder v2.30.0
|
||||
r.Route("/tasks", func(r chi.Router) {
|
||||
r.Use(apiKeyMiddleware)
|
||||
|
||||
@@ -1650,6 +1653,25 @@ func New(options *Options) *API {
|
||||
r.Route("/init-script", func(r chi.Router) {
|
||||
r.Get("/{os}/{arch}", api.initScript)
|
||||
})
|
||||
r.Route("/tasks", func(r chi.Router) {
|
||||
r.Use(apiKeyMiddleware)
|
||||
|
||||
r.Get("/", api.tasksList)
|
||||
|
||||
r.Route("/{user}", func(r chi.Router) {
|
||||
r.Use(httpmw.ExtractOrganizationMembersParam(options.Database, api.HTTPAuth.Authorize))
|
||||
r.Post("/", api.tasksCreate)
|
||||
|
||||
r.Route("/{task}", func(r chi.Router) {
|
||||
r.Use(httpmw.ExtractTaskParam(options.Database))
|
||||
r.Get("/", api.taskGet)
|
||||
r.Delete("/", api.taskDelete)
|
||||
r.Patch("/input", api.taskUpdateInput)
|
||||
r.Post("/send", api.taskSend)
|
||||
r.Get("/logs", api.taskLogs)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
if options.SwaggerEndpoint {
|
||||
|
||||
@@ -4800,7 +4800,6 @@ func TestWorkspaceListTasks(t *testing.T) {
|
||||
ctx := testutil.Context(t, testutil.WaitShort)
|
||||
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
expClient := codersdk.NewExperimentalClient(client)
|
||||
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
|
||||
Parse: echo.ParseComplete,
|
||||
@@ -4823,7 +4822,7 @@ func TestWorkspaceListTasks(t *testing.T) {
|
||||
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspaceWithoutTask.LatestBuild.ID)
|
||||
|
||||
// Given: a workspace associated with a task
|
||||
task, err := expClient.CreateTask(ctx, codersdk.Me, codersdk.CreateTaskRequest{
|
||||
task, err := client.CreateTask(ctx, codersdk.Me, codersdk.CreateTaskRequest{
|
||||
TemplateVersionID: template.ActiveVersionID,
|
||||
Input: "Some task prompt",
|
||||
})
|
||||
|
||||
+20
-60
@@ -28,8 +28,6 @@ import (
|
||||
const AITaskPromptParameterName = provider.TaskPromptParameterName
|
||||
|
||||
// CreateTaskRequest represents the request to create a new task.
|
||||
//
|
||||
// Experimental: This type is experimental and may change in the future.
|
||||
type CreateTaskRequest struct {
|
||||
TemplateVersionID uuid.UUID `json:"template_version_id" format:"uuid"`
|
||||
TemplateVersionPresetID uuid.UUID `json:"template_version_preset_id,omitempty" format:"uuid"`
|
||||
@@ -39,10 +37,8 @@ type CreateTaskRequest struct {
|
||||
}
|
||||
|
||||
// CreateTask creates a new task.
|
||||
//
|
||||
// Experimental: This method is experimental and may change in the future.
|
||||
func (c *ExperimentalClient) CreateTask(ctx context.Context, user string, request CreateTaskRequest) (Task, error) {
|
||||
res, err := c.Request(ctx, http.MethodPost, fmt.Sprintf("/api/experimental/tasks/%s", user), request)
|
||||
func (c *Client) CreateTask(ctx context.Context, user string, request CreateTaskRequest) (Task, error) {
|
||||
res, err := c.Request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/tasks/%s", user), request)
|
||||
if err != nil {
|
||||
return Task{}, err
|
||||
}
|
||||
@@ -61,8 +57,6 @@ func (c *ExperimentalClient) CreateTask(ctx context.Context, user string, reques
|
||||
}
|
||||
|
||||
// TaskStatus represents the status of a task.
|
||||
//
|
||||
// Experimental: This type is experimental and may change in the future.
|
||||
type TaskStatus string
|
||||
|
||||
const (
|
||||
@@ -99,8 +93,6 @@ func AllTaskStatuses() []TaskStatus {
|
||||
}
|
||||
|
||||
// TaskState represents the high-level lifecycle of a task.
|
||||
//
|
||||
// Experimental: This type is experimental and may change in the future.
|
||||
type TaskState string
|
||||
|
||||
// TaskState enums.
|
||||
@@ -120,8 +112,6 @@ const (
|
||||
)
|
||||
|
||||
// Task represents a task.
|
||||
//
|
||||
// Experimental: This type is experimental and may change in the future.
|
||||
type Task struct {
|
||||
ID uuid.UUID `json:"id" format:"uuid" table:"id"`
|
||||
OrganizationID uuid.UUID `json:"organization_id" format:"uuid" table:"organization id"`
|
||||
@@ -151,8 +141,6 @@ type Task struct {
|
||||
}
|
||||
|
||||
// TaskStateEntry represents a single entry in the task's state history.
|
||||
//
|
||||
// Experimental: This type is experimental and may change in the future.
|
||||
type TaskStateEntry struct {
|
||||
Timestamp time.Time `json:"timestamp" format:"date-time" table:"-"`
|
||||
State TaskState `json:"state" enum:"working,idle,completed,failed" table:"state"`
|
||||
@@ -161,8 +149,6 @@ type TaskStateEntry struct {
|
||||
}
|
||||
|
||||
// TasksFilter filters the list of tasks.
|
||||
//
|
||||
// Experimental: This type is experimental and may change in the future.
|
||||
type TasksFilter struct {
|
||||
// Owner can be a username, UUID, or "me".
|
||||
Owner string `json:"owner,omitempty"`
|
||||
@@ -175,8 +161,6 @@ type TasksFilter struct {
|
||||
}
|
||||
|
||||
// TaskListResponse is the response shape for tasks list.
|
||||
//
|
||||
// Experimental response shape for tasks list (server returns []Task).
|
||||
type TasksListResponse struct {
|
||||
Tasks []Task `json:"tasks"`
|
||||
Count int `json:"count"`
|
||||
@@ -208,14 +192,12 @@ func (f TasksFilter) asRequestOption() RequestOption {
|
||||
}
|
||||
|
||||
// Tasks lists all tasks belonging to the user or specified owner.
|
||||
//
|
||||
// Experimental: This method is experimental and may change in the future.
|
||||
func (c *ExperimentalClient) Tasks(ctx context.Context, filter *TasksFilter) ([]Task, error) {
|
||||
func (c *Client) Tasks(ctx context.Context, filter *TasksFilter) ([]Task, error) {
|
||||
if filter == nil {
|
||||
filter = &TasksFilter{}
|
||||
}
|
||||
|
||||
res, err := c.Request(ctx, http.MethodGet, "/api/experimental/tasks", nil, filter.asRequestOption())
|
||||
res, err := c.Request(ctx, http.MethodGet, "/api/v2/tasks", nil, filter.asRequestOption())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -232,12 +214,10 @@ func (c *ExperimentalClient) Tasks(ctx context.Context, filter *TasksFilter) ([]
|
||||
return tres.Tasks, nil
|
||||
}
|
||||
|
||||
// TaskByID fetches a single experimental task by its ID.
|
||||
// TaskByID fetches a single task by its ID.
|
||||
// Only tasks owned by codersdk.Me are supported.
|
||||
//
|
||||
// Experimental: This method is experimental and may change in the future.
|
||||
func (c *ExperimentalClient) TaskByID(ctx context.Context, id uuid.UUID) (Task, error) {
|
||||
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/experimental/tasks/%s/%s", "me", id.String()), nil)
|
||||
func (c *Client) TaskByID(ctx context.Context, id uuid.UUID) (Task, error) {
|
||||
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/tasks/%s/%s", "me", id.String()), nil)
|
||||
if err != nil {
|
||||
return Task{}, err
|
||||
}
|
||||
@@ -254,14 +234,12 @@ func (c *ExperimentalClient) TaskByID(ctx context.Context, id uuid.UUID) (Task,
|
||||
return task, nil
|
||||
}
|
||||
|
||||
// TaskByOwnerAndName fetches a single experimental task by its owner and name.
|
||||
//
|
||||
// Experimental: This method is experimental and may change in the future.
|
||||
func (c *ExperimentalClient) TaskByOwnerAndName(ctx context.Context, owner, ident string) (Task, error) {
|
||||
// TaskByOwnerAndName fetches a single task by its owner and name.
|
||||
func (c *Client) TaskByOwnerAndName(ctx context.Context, owner, ident string) (Task, error) {
|
||||
if owner == "" {
|
||||
owner = Me
|
||||
}
|
||||
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/experimental/tasks/%s/%s", owner, ident), nil)
|
||||
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/tasks/%s/%s", owner, ident), nil)
|
||||
if err != nil {
|
||||
return Task{}, err
|
||||
}
|
||||
@@ -300,7 +278,7 @@ func splitTaskIdentifier(identifier string) (owner string, taskName string, err
|
||||
//
|
||||
// Since there is no TaskByOwnerAndName endpoint yet, this function uses the
|
||||
// list endpoint with filtering when a name is provided.
|
||||
func (c *ExperimentalClient) TaskByIdentifier(ctx context.Context, identifier string) (Task, error) {
|
||||
func (c *Client) TaskByIdentifier(ctx context.Context, identifier string) (Task, error) {
|
||||
identifier = strings.TrimSpace(identifier)
|
||||
|
||||
// Try parsing as UUID first.
|
||||
@@ -318,10 +296,8 @@ func (c *ExperimentalClient) TaskByIdentifier(ctx context.Context, identifier st
|
||||
}
|
||||
|
||||
// DeleteTask deletes a task by its ID.
|
||||
//
|
||||
// Experimental: This method is experimental and may change in the future.
|
||||
func (c *ExperimentalClient) DeleteTask(ctx context.Context, user string, id uuid.UUID) error {
|
||||
res, err := c.Request(ctx, http.MethodDelete, fmt.Sprintf("/api/experimental/tasks/%s/%s", user, id.String()), nil)
|
||||
func (c *Client) DeleteTask(ctx context.Context, user string, id uuid.UUID) error {
|
||||
res, err := c.Request(ctx, http.MethodDelete, fmt.Sprintf("/api/v2/tasks/%s/%s", user, id.String()), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -333,17 +309,13 @@ func (c *ExperimentalClient) DeleteTask(ctx context.Context, user string, id uui
|
||||
}
|
||||
|
||||
// TaskSendRequest is used to send task input to the tasks sidebar app.
|
||||
//
|
||||
// Experimental: This type is experimental and may change in the future.
|
||||
type TaskSendRequest struct {
|
||||
Input string `json:"input"`
|
||||
}
|
||||
|
||||
// TaskSend submits task input to the tasks sidebar app.
|
||||
//
|
||||
// Experimental: This method is experimental and may change in the future.
|
||||
func (c *ExperimentalClient) TaskSend(ctx context.Context, user string, id uuid.UUID, req TaskSendRequest) error {
|
||||
res, err := c.Request(ctx, http.MethodPost, fmt.Sprintf("/api/experimental/tasks/%s/%s/send", user, id.String()), req)
|
||||
func (c *Client) TaskSend(ctx context.Context, user string, id uuid.UUID, req TaskSendRequest) error {
|
||||
res, err := c.Request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/tasks/%s/%s/send", user, id.String()), req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -355,17 +327,13 @@ func (c *ExperimentalClient) TaskSend(ctx context.Context, user string, id uuid.
|
||||
}
|
||||
|
||||
// UpdateTaskInputRequest is used to update a task's input.
|
||||
//
|
||||
// Experimental: This type is experimental and may change in the future.
|
||||
type UpdateTaskInputRequest struct {
|
||||
Input string `json:"input"`
|
||||
}
|
||||
|
||||
// UpdateTaskInput updates the task's input.
|
||||
//
|
||||
// Experimental: This method is experimental and may change in the future.
|
||||
func (c *ExperimentalClient) UpdateTaskInput(ctx context.Context, user string, id uuid.UUID, req UpdateTaskInputRequest) error {
|
||||
res, err := c.Request(ctx, http.MethodPatch, fmt.Sprintf("/api/experimental/tasks/%s/%s/input", user, id.String()), req)
|
||||
func (c *Client) UpdateTaskInput(ctx context.Context, user string, id uuid.UUID, req UpdateTaskInputRequest) error {
|
||||
res, err := c.Request(ctx, http.MethodPatch, fmt.Sprintf("/api/v2/tasks/%s/%s/input", user, id.String()), req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -377,8 +345,6 @@ func (c *ExperimentalClient) UpdateTaskInput(ctx context.Context, user string, i
|
||||
}
|
||||
|
||||
// TaskLogType indicates the source of a task log entry.
|
||||
//
|
||||
// Experimental: This type is experimental and may change in the future.
|
||||
type TaskLogType string
|
||||
|
||||
// TaskLogType enums.
|
||||
@@ -388,8 +354,6 @@ const (
|
||||
)
|
||||
|
||||
// TaskLogEntry represents a single log entry for a task.
|
||||
//
|
||||
// Experimental: This type is experimental and may change in the future.
|
||||
type TaskLogEntry struct {
|
||||
ID int `json:"id" table:"id"`
|
||||
Content string `json:"content" table:"content"`
|
||||
@@ -398,17 +362,13 @@ type TaskLogEntry struct {
|
||||
}
|
||||
|
||||
// TaskLogsResponse contains the logs for a task.
|
||||
//
|
||||
// Experimental: This type is experimental and may change in the future.
|
||||
type TaskLogsResponse struct {
|
||||
Logs []TaskLogEntry `json:"logs"`
|
||||
}
|
||||
|
||||
// TaskLogs retrieves logs from the task's sidebar app via the experimental API.
|
||||
//
|
||||
// Experimental: This method is experimental and may change in the future.
|
||||
func (c *ExperimentalClient) TaskLogs(ctx context.Context, user string, id uuid.UUID) (TaskLogsResponse, error) {
|
||||
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/experimental/tasks/%s/%s/logs", user, id.String()), nil)
|
||||
// TaskLogs retrieves logs from the task app.
|
||||
func (c *Client) TaskLogs(ctx context.Context, user string, id uuid.UUID) (TaskLogsResponse, error) {
|
||||
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/tasks/%s/%s/logs", user, id.String()), nil)
|
||||
if err != nil {
|
||||
return TaskLogsResponse{}, err
|
||||
}
|
||||
|
||||
@@ -1899,8 +1899,7 @@ var CreateTask = Tool[CreateTaskArgs, codersdk.Task]{
|
||||
args.User = codersdk.Me
|
||||
}
|
||||
|
||||
expClient := codersdk.NewExperimentalClient(deps.coderClient)
|
||||
task, err := expClient.CreateTask(ctx, args.User, codersdk.CreateTaskRequest{
|
||||
task, err := deps.coderClient.CreateTask(ctx, args.User, codersdk.CreateTaskRequest{
|
||||
Input: args.Input,
|
||||
TemplateVersionID: tvID,
|
||||
TemplateVersionPresetID: tvPresetID,
|
||||
@@ -1937,14 +1936,12 @@ var DeleteTask = Tool[DeleteTaskArgs, codersdk.Response]{
|
||||
return codersdk.Response{}, xerrors.New("task_id is required")
|
||||
}
|
||||
|
||||
expClient := codersdk.NewExperimentalClient(deps.coderClient)
|
||||
|
||||
task, err := expClient.TaskByIdentifier(ctx, args.TaskID)
|
||||
task, err := deps.coderClient.TaskByIdentifier(ctx, args.TaskID)
|
||||
if err != nil {
|
||||
return codersdk.Response{}, xerrors.Errorf("resolve task: %w", err)
|
||||
}
|
||||
|
||||
err = expClient.DeleteTask(ctx, task.OwnerName, task.ID)
|
||||
err = deps.coderClient.DeleteTask(ctx, task.OwnerName, task.ID)
|
||||
if err != nil {
|
||||
return codersdk.Response{}, xerrors.Errorf("delete task: %w", err)
|
||||
}
|
||||
@@ -1988,8 +1985,7 @@ var ListTasks = Tool[ListTasksArgs, ListTasksResponse]{
|
||||
args.User = codersdk.Me
|
||||
}
|
||||
|
||||
expClient := codersdk.NewExperimentalClient(deps.coderClient)
|
||||
tasks, err := expClient.Tasks(ctx, &codersdk.TasksFilter{
|
||||
tasks, err := deps.coderClient.Tasks(ctx, &codersdk.TasksFilter{
|
||||
Owner: args.User,
|
||||
Status: args.Status,
|
||||
})
|
||||
@@ -2032,9 +2028,7 @@ var GetTaskStatus = Tool[GetTaskStatusArgs, GetTaskStatusResponse]{
|
||||
return GetTaskStatusResponse{}, xerrors.New("task_id is required")
|
||||
}
|
||||
|
||||
expClient := codersdk.NewExperimentalClient(deps.coderClient)
|
||||
|
||||
task, err := expClient.TaskByIdentifier(ctx, args.TaskID)
|
||||
task, err := deps.coderClient.TaskByIdentifier(ctx, args.TaskID)
|
||||
if err != nil {
|
||||
return GetTaskStatusResponse{}, xerrors.Errorf("resolve task %q: %w", args.TaskID, err)
|
||||
}
|
||||
@@ -2079,14 +2073,12 @@ var SendTaskInput = Tool[SendTaskInputArgs, codersdk.Response]{
|
||||
return codersdk.Response{}, xerrors.New("input is required")
|
||||
}
|
||||
|
||||
expClient := codersdk.NewExperimentalClient(deps.coderClient)
|
||||
|
||||
task, err := expClient.TaskByIdentifier(ctx, args.TaskID)
|
||||
task, err := deps.coderClient.TaskByIdentifier(ctx, args.TaskID)
|
||||
if err != nil {
|
||||
return codersdk.Response{}, xerrors.Errorf("resolve task %q: %w", args.TaskID, err)
|
||||
}
|
||||
|
||||
err = expClient.TaskSend(ctx, task.OwnerName, task.ID, codersdk.TaskSendRequest{
|
||||
err = deps.coderClient.TaskSend(ctx, task.OwnerName, task.ID, codersdk.TaskSendRequest{
|
||||
Input: args.Input,
|
||||
})
|
||||
if err != nil {
|
||||
@@ -2123,14 +2115,12 @@ var GetTaskLogs = Tool[GetTaskLogsArgs, codersdk.TaskLogsResponse]{
|
||||
return codersdk.TaskLogsResponse{}, xerrors.New("task_id is required")
|
||||
}
|
||||
|
||||
expClient := codersdk.NewExperimentalClient(deps.coderClient)
|
||||
|
||||
task, err := expClient.TaskByIdentifier(ctx, args.TaskID)
|
||||
task, err := deps.coderClient.TaskByIdentifier(ctx, args.TaskID)
|
||||
if err != nil {
|
||||
return codersdk.TaskLogsResponse{}, err
|
||||
}
|
||||
|
||||
logs, err := expClient.TaskLogs(ctx, task.OwnerName, task.ID)
|
||||
logs, err := deps.coderClient.TaskLogs(ctx, task.OwnerName, task.ID)
|
||||
if err != nil {
|
||||
return codersdk.TaskLogsResponse{}, xerrors.Errorf("get task logs %q: %w", args.TaskID, err)
|
||||
}
|
||||
|
||||
@@ -1025,11 +1025,8 @@ func TestTools(t *testing.T) {
|
||||
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
|
||||
template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID)
|
||||
|
||||
expClient := codersdk.NewExperimentalClient(client)
|
||||
taskExpClient := codersdk.NewExperimentalClient(taskClient)
|
||||
|
||||
// This task should not show up since listing is user-scoped.
|
||||
_, err := expClient.CreateTask(ctx, member.Username, codersdk.CreateTaskRequest{
|
||||
_, err := client.CreateTask(ctx, member.Username, codersdk.CreateTaskRequest{
|
||||
TemplateVersionID: template.ActiveVersionID,
|
||||
Input: "task for member",
|
||||
Name: "list-task-workspace-member",
|
||||
@@ -1039,7 +1036,7 @@ func TestTools(t *testing.T) {
|
||||
// Create tasks for taskUser. These should show up in the list.
|
||||
for i := range 5 {
|
||||
taskName := fmt.Sprintf("list-task-workspace-%d", i)
|
||||
task, err := taskExpClient.CreateTask(ctx, codersdk.Me, codersdk.CreateTaskRequest{
|
||||
task, err := taskClient.CreateTask(ctx, codersdk.Me, codersdk.CreateTaskRequest{
|
||||
TemplateVersionID: template.ActiveVersionID,
|
||||
Input: fmt.Sprintf("task %d", i),
|
||||
Name: taskName,
|
||||
|
||||
Generated
+185
-26
@@ -6,12 +6,12 @@
|
||||
|
||||
```shell
|
||||
# Example request using curl
|
||||
curl -X GET http://coder-server:8080/api/v2/api/experimental/tasks \
|
||||
-H 'Accept: */*' \
|
||||
curl -X GET http://coder-server:8080/api/v2/tasks \
|
||||
-H 'Accept: application/json' \
|
||||
-H 'Coder-Session-Token: API_KEY'
|
||||
```
|
||||
|
||||
`GET /api/experimental/tasks`
|
||||
`GET /tasks`
|
||||
|
||||
### Parameters
|
||||
|
||||
@@ -23,6 +23,58 @@ curl -X GET http://coder-server:8080/api/v2/api/experimental/tasks \
|
||||
|
||||
> 200 Response
|
||||
|
||||
```json
|
||||
{
|
||||
"count": 0,
|
||||
"tasks": [
|
||||
{
|
||||
"created_at": "2019-08-24T14:15:22Z",
|
||||
"current_state": {
|
||||
"message": "string",
|
||||
"state": "working",
|
||||
"timestamp": "2019-08-24T14:15:22Z",
|
||||
"uri": "string"
|
||||
},
|
||||
"display_name": "string",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"initial_prompt": "string",
|
||||
"name": "string",
|
||||
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
|
||||
"owner_avatar_url": "string",
|
||||
"owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
|
||||
"owner_name": "string",
|
||||
"status": "pending",
|
||||
"template_display_name": "string",
|
||||
"template_icon": "string",
|
||||
"template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
|
||||
"template_name": "string",
|
||||
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
|
||||
"updated_at": "2019-08-24T14:15:22Z",
|
||||
"workspace_agent_health": {
|
||||
"healthy": false,
|
||||
"reason": "agent has lost connection"
|
||||
},
|
||||
"workspace_agent_id": {
|
||||
"uuid": "string",
|
||||
"valid": true
|
||||
},
|
||||
"workspace_agent_lifecycle": "created",
|
||||
"workspace_app_id": {
|
||||
"uuid": "string",
|
||||
"valid": true
|
||||
},
|
||||
"workspace_build_number": 0,
|
||||
"workspace_id": {
|
||||
"uuid": "string",
|
||||
"valid": true
|
||||
},
|
||||
"workspace_name": "string",
|
||||
"workspace_status": "pending"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Responses
|
||||
|
||||
| Status | Meaning | Description | Schema |
|
||||
@@ -37,13 +89,13 @@ To perform this operation, you must be authenticated. [Learn more](authenticatio
|
||||
|
||||
```shell
|
||||
# Example request using curl
|
||||
curl -X POST http://coder-server:8080/api/v2/api/experimental/tasks/{user} \
|
||||
curl -X POST http://coder-server:8080/api/v2/tasks/{user} \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Accept: */*' \
|
||||
-H 'Accept: application/json' \
|
||||
-H 'Coder-Session-Token: API_KEY'
|
||||
```
|
||||
|
||||
`POST /api/experimental/tasks/{user}`
|
||||
`POST /tasks/{user}`
|
||||
|
||||
> Body parameter
|
||||
|
||||
@@ -68,6 +120,53 @@ curl -X POST http://coder-server:8080/api/v2/api/experimental/tasks/{user} \
|
||||
|
||||
> 201 Response
|
||||
|
||||
```json
|
||||
{
|
||||
"created_at": "2019-08-24T14:15:22Z",
|
||||
"current_state": {
|
||||
"message": "string",
|
||||
"state": "working",
|
||||
"timestamp": "2019-08-24T14:15:22Z",
|
||||
"uri": "string"
|
||||
},
|
||||
"display_name": "string",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"initial_prompt": "string",
|
||||
"name": "string",
|
||||
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
|
||||
"owner_avatar_url": "string",
|
||||
"owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
|
||||
"owner_name": "string",
|
||||
"status": "pending",
|
||||
"template_display_name": "string",
|
||||
"template_icon": "string",
|
||||
"template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
|
||||
"template_name": "string",
|
||||
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
|
||||
"updated_at": "2019-08-24T14:15:22Z",
|
||||
"workspace_agent_health": {
|
||||
"healthy": false,
|
||||
"reason": "agent has lost connection"
|
||||
},
|
||||
"workspace_agent_id": {
|
||||
"uuid": "string",
|
||||
"valid": true
|
||||
},
|
||||
"workspace_agent_lifecycle": "created",
|
||||
"workspace_app_id": {
|
||||
"uuid": "string",
|
||||
"valid": true
|
||||
},
|
||||
"workspace_build_number": 0,
|
||||
"workspace_id": {
|
||||
"uuid": "string",
|
||||
"valid": true
|
||||
},
|
||||
"workspace_name": "string",
|
||||
"workspace_status": "pending"
|
||||
}
|
||||
```
|
||||
|
||||
### Responses
|
||||
|
||||
| Status | Meaning | Description | Schema |
|
||||
@@ -76,18 +175,18 @@ curl -X POST http://coder-server:8080/api/v2/api/experimental/tasks/{user} \
|
||||
|
||||
To perform this operation, you must be authenticated. [Learn more](authentication.md).
|
||||
|
||||
## Get AI task by ID
|
||||
## Get AI task by ID or name
|
||||
|
||||
### Code samples
|
||||
|
||||
```shell
|
||||
# Example request using curl
|
||||
curl -X GET http://coder-server:8080/api/v2/api/experimental/tasks/{user}/{task} \
|
||||
-H 'Accept: */*' \
|
||||
curl -X GET http://coder-server:8080/api/v2/tasks/{user}/{task} \
|
||||
-H 'Accept: application/json' \
|
||||
-H 'Coder-Session-Token: API_KEY'
|
||||
```
|
||||
|
||||
`GET /api/experimental/tasks/{user}/{task}`
|
||||
`GET /tasks/{user}/{task}`
|
||||
|
||||
### Parameters
|
||||
|
||||
@@ -100,6 +199,53 @@ curl -X GET http://coder-server:8080/api/v2/api/experimental/tasks/{user}/{task}
|
||||
|
||||
> 200 Response
|
||||
|
||||
```json
|
||||
{
|
||||
"created_at": "2019-08-24T14:15:22Z",
|
||||
"current_state": {
|
||||
"message": "string",
|
||||
"state": "working",
|
||||
"timestamp": "2019-08-24T14:15:22Z",
|
||||
"uri": "string"
|
||||
},
|
||||
"display_name": "string",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"initial_prompt": "string",
|
||||
"name": "string",
|
||||
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
|
||||
"owner_avatar_url": "string",
|
||||
"owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
|
||||
"owner_name": "string",
|
||||
"status": "pending",
|
||||
"template_display_name": "string",
|
||||
"template_icon": "string",
|
||||
"template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
|
||||
"template_name": "string",
|
||||
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
|
||||
"updated_at": "2019-08-24T14:15:22Z",
|
||||
"workspace_agent_health": {
|
||||
"healthy": false,
|
||||
"reason": "agent has lost connection"
|
||||
},
|
||||
"workspace_agent_id": {
|
||||
"uuid": "string",
|
||||
"valid": true
|
||||
},
|
||||
"workspace_agent_lifecycle": "created",
|
||||
"workspace_app_id": {
|
||||
"uuid": "string",
|
||||
"valid": true
|
||||
},
|
||||
"workspace_build_number": 0,
|
||||
"workspace_id": {
|
||||
"uuid": "string",
|
||||
"valid": true
|
||||
},
|
||||
"workspace_name": "string",
|
||||
"workspace_status": "pending"
|
||||
}
|
||||
```
|
||||
|
||||
### Responses
|
||||
|
||||
| Status | Meaning | Description | Schema |
|
||||
@@ -108,17 +254,17 @@ curl -X GET http://coder-server:8080/api/v2/api/experimental/tasks/{user}/{task}
|
||||
|
||||
To perform this operation, you must be authenticated. [Learn more](authentication.md).
|
||||
|
||||
## Delete AI task by ID
|
||||
## Delete AI task
|
||||
|
||||
### Code samples
|
||||
|
||||
```shell
|
||||
# Example request using curl
|
||||
curl -X DELETE http://coder-server:8080/api/v2/api/experimental/tasks/{user}/{task} \
|
||||
curl -X DELETE http://coder-server:8080/api/v2/tasks/{user}/{task} \
|
||||
-H 'Coder-Session-Token: API_KEY'
|
||||
```
|
||||
|
||||
`DELETE /api/experimental/tasks/{user}/{task}`
|
||||
`DELETE /tasks/{user}/{task}`
|
||||
|
||||
### Parameters
|
||||
|
||||
@@ -129,9 +275,9 @@ curl -X DELETE http://coder-server:8080/api/v2/api/experimental/tasks/{user}/{ta
|
||||
|
||||
### Responses
|
||||
|
||||
| Status | Meaning | Description | Schema |
|
||||
|--------|---------------------------------------------------------------|-------------------------|--------|
|
||||
| 202 | [Accepted](https://tools.ietf.org/html/rfc7231#section-6.3.3) | Task deletion initiated | |
|
||||
| Status | Meaning | Description | Schema |
|
||||
|--------|---------------------------------------------------------------|-------------|--------|
|
||||
| 202 | [Accepted](https://tools.ietf.org/html/rfc7231#section-6.3.3) | Accepted | |
|
||||
|
||||
To perform this operation, you must be authenticated. [Learn more](authentication.md).
|
||||
|
||||
@@ -141,12 +287,12 @@ To perform this operation, you must be authenticated. [Learn more](authenticatio
|
||||
|
||||
```shell
|
||||
# Example request using curl
|
||||
curl -X PATCH http://coder-server:8080/api/v2/api/experimental/tasks/{user}/{task}/input \
|
||||
curl -X PATCH http://coder-server:8080/api/v2/tasks/{user}/{task}/input \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Coder-Session-Token: API_KEY'
|
||||
```
|
||||
|
||||
`PATCH /api/experimental/tasks/{user}/{task}/input`
|
||||
`PATCH /tasks/{user}/{task}/input`
|
||||
|
||||
> Body parameter
|
||||
|
||||
@@ -178,12 +324,12 @@ To perform this operation, you must be authenticated. [Learn more](authenticatio
|
||||
|
||||
```shell
|
||||
# Example request using curl
|
||||
curl -X GET http://coder-server:8080/api/v2/api/experimental/tasks/{user}/{task}/logs \
|
||||
-H 'Accept: */*' \
|
||||
curl -X GET http://coder-server:8080/api/v2/tasks/{user}/{task}/logs \
|
||||
-H 'Accept: application/json' \
|
||||
-H 'Coder-Session-Token: API_KEY'
|
||||
```
|
||||
|
||||
`GET /api/experimental/tasks/{user}/{task}/logs`
|
||||
`GET /tasks/{user}/{task}/logs`
|
||||
|
||||
### Parameters
|
||||
|
||||
@@ -196,6 +342,19 @@ curl -X GET http://coder-server:8080/api/v2/api/experimental/tasks/{user}/{task}
|
||||
|
||||
> 200 Response
|
||||
|
||||
```json
|
||||
{
|
||||
"logs": [
|
||||
{
|
||||
"content": "string",
|
||||
"id": 0,
|
||||
"time": "2019-08-24T14:15:22Z",
|
||||
"type": "input"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Responses
|
||||
|
||||
| Status | Meaning | Description | Schema |
|
||||
@@ -210,12 +369,12 @@ To perform this operation, you must be authenticated. [Learn more](authenticatio
|
||||
|
||||
```shell
|
||||
# Example request using curl
|
||||
curl -X POST http://coder-server:8080/api/v2/api/experimental/tasks/{user}/{task}/send \
|
||||
curl -X POST http://coder-server:8080/api/v2/tasks/{user}/{task}/send \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Coder-Session-Token: API_KEY'
|
||||
```
|
||||
|
||||
`POST /api/experimental/tasks/{user}/{task}/send`
|
||||
`POST /tasks/{user}/{task}/send`
|
||||
|
||||
> Body parameter
|
||||
|
||||
@@ -235,8 +394,8 @@ curl -X POST http://coder-server:8080/api/v2/api/experimental/tasks/{user}/{task
|
||||
|
||||
### Responses
|
||||
|
||||
| Status | Meaning | Description | Schema |
|
||||
|--------|-----------------------------------------------------------------|-------------------------|--------|
|
||||
| 204 | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | Input sent successfully | |
|
||||
| Status | Meaning | Description | Schema |
|
||||
|--------|-----------------------------------------------------------------|-------------|--------|
|
||||
| 204 | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content | |
|
||||
|
||||
To perform this operation, you must be authenticated. [Learn more](authentication.md).
|
||||
|
||||
+4
-4
@@ -2666,7 +2666,7 @@ class ExperimentalApiMethods {
|
||||
req: TypesGen.CreateTaskRequest,
|
||||
): Promise<TypesGen.Task> => {
|
||||
const response = await this.axios.post<TypesGen.Task>(
|
||||
`/api/experimental/tasks/${user}`,
|
||||
`/api/v2/tasks/${user}`,
|
||||
req,
|
||||
);
|
||||
|
||||
@@ -2685,7 +2685,7 @@ class ExperimentalApiMethods {
|
||||
}
|
||||
|
||||
const res = await this.axios.get<TypesGen.TasksListResponse>(
|
||||
"/api/experimental/tasks",
|
||||
"/api/v2/tasks",
|
||||
{
|
||||
params: {
|
||||
q: query.join(", "),
|
||||
@@ -2698,14 +2698,14 @@ class ExperimentalApiMethods {
|
||||
|
||||
getTask = async (user: string, id: string): Promise<TypesGen.Task> => {
|
||||
const response = await this.axios.get<TypesGen.Task>(
|
||||
`/api/experimental/tasks/${user}/${id}`,
|
||||
`/api/v2/tasks/${user}/${id}`,
|
||||
);
|
||||
|
||||
return response.data;
|
||||
};
|
||||
|
||||
deleteTask = async (user: string, id: string): Promise<void> => {
|
||||
await this.axios.delete(`/api/experimental/tasks/${user}/${id}`);
|
||||
await this.axios.delete(`/api/v2/tasks/${user}/${id}`);
|
||||
};
|
||||
|
||||
createTaskFeedback = async (
|
||||
|
||||
Generated
-18
@@ -1195,8 +1195,6 @@ export interface CreateProvisionerKeyResponse {
|
||||
// From codersdk/aitasks.go
|
||||
/**
|
||||
* CreateTaskRequest represents the request to create a new task.
|
||||
*
|
||||
* Experimental: This type is experimental and may change in the future.
|
||||
*/
|
||||
export interface CreateTaskRequest {
|
||||
readonly template_version_id: string;
|
||||
@@ -4723,8 +4721,6 @@ export interface TailDERPRegion {
|
||||
// From codersdk/aitasks.go
|
||||
/**
|
||||
* Task represents a task.
|
||||
*
|
||||
* Experimental: This type is experimental and may change in the future.
|
||||
*/
|
||||
export interface Task {
|
||||
readonly id: string;
|
||||
@@ -4757,8 +4753,6 @@ export interface Task {
|
||||
// From codersdk/aitasks.go
|
||||
/**
|
||||
* TaskLogEntry represents a single log entry for a task.
|
||||
*
|
||||
* Experimental: This type is experimental and may change in the future.
|
||||
*/
|
||||
export interface TaskLogEntry {
|
||||
readonly id: number;
|
||||
@@ -4775,8 +4769,6 @@ export const TaskLogTypes: TaskLogType[] = ["input", "output"];
|
||||
// From codersdk/aitasks.go
|
||||
/**
|
||||
* TaskLogsResponse contains the logs for a task.
|
||||
*
|
||||
* Experimental: This type is experimental and may change in the future.
|
||||
*/
|
||||
export interface TaskLogsResponse {
|
||||
readonly logs: readonly TaskLogEntry[];
|
||||
@@ -4785,8 +4777,6 @@ export interface TaskLogsResponse {
|
||||
// From codersdk/aitasks.go
|
||||
/**
|
||||
* TaskSendRequest is used to send task input to the tasks sidebar app.
|
||||
*
|
||||
* Experimental: This type is experimental and may change in the future.
|
||||
*/
|
||||
export interface TaskSendRequest {
|
||||
readonly input: string;
|
||||
@@ -4798,8 +4788,6 @@ export type TaskState = "complete" | "failed" | "idle" | "working";
|
||||
// From codersdk/aitasks.go
|
||||
/**
|
||||
* TaskStateEntry represents a single entry in the task's state history.
|
||||
*
|
||||
* Experimental: This type is experimental and may change in the future.
|
||||
*/
|
||||
export interface TaskStateEntry {
|
||||
readonly timestamp: string;
|
||||
@@ -4836,8 +4824,6 @@ export const TaskStatuses: TaskStatus[] = [
|
||||
// From codersdk/aitasks.go
|
||||
/**
|
||||
* TasksFilter filters the list of tasks.
|
||||
*
|
||||
* Experimental: This type is experimental and may change in the future.
|
||||
*/
|
||||
export interface TasksFilter {
|
||||
/**
|
||||
@@ -4861,8 +4847,6 @@ export interface TasksFilter {
|
||||
// From codersdk/aitasks.go
|
||||
/**
|
||||
* TaskListResponse is the response shape for tasks list.
|
||||
*
|
||||
* Experimental response shape for tasks list (server returns []Task).
|
||||
*/
|
||||
export interface TasksListResponse {
|
||||
readonly tasks: readonly Task[];
|
||||
@@ -5376,8 +5360,6 @@ export interface UpdateRoles {
|
||||
// From codersdk/aitasks.go
|
||||
/**
|
||||
* UpdateTaskInputRequest is used to update a task's input.
|
||||
*
|
||||
* Experimental: This type is experimental and may change in the future.
|
||||
*/
|
||||
export interface UpdateTaskInputRequest {
|
||||
readonly input: string;
|
||||
|
||||
Reference in New Issue
Block a user