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:
Danielle Maywood
2025-11-25 15:24:25 +00:00
committed by GitHub
parent 37fc6646ad
commit b255827a52
23 changed files with 903 additions and 838 deletions
+25 -53
View File
@@ -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
View File
@@ -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",
})
+288 -267
View File
@@ -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": [
+260 -253
View File
@@ -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": [
+1 -2
View File
@@ -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,
})
+22
View File
@@ -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 {
+1 -2
View File
@@ -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",
})