fix: complete Tasks GA promotion (docs, site) (#20927)

## Summary

Completes the Coder Tasks GA promotion by updating swagger tags and
regenerating API documentation and updating the frontend API structure.

## Related

Follows #20923 and #20921 which promoted Tasks from Beta/Experimental to
GA.

---

🤖 This change was written by Claude Sonnet 4.5 Thinking using
[mux](https://github.com/coder/mux) and reviewed by a human 🏂
This commit is contained in:
Mathias Fredriksson
2025-11-25 16:46:13 +00:00
committed by GitHub
parent 2f399eafae
commit e189dc1f81
19 changed files with 118 additions and 129 deletions
+7 -7
View File
@@ -35,7 +35,7 @@ import (
// @Security CoderSessionToken
// @Accept json
// @Produce json
// @Tags Experimental
// @Tags Tasks
// @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
@@ -401,7 +401,7 @@ func deriveTaskCurrentState(
// @ID list-ai-tasks
// @Security CoderSessionToken
// @Produce json
// @Tags Experimental
// @Tags Tasks
// @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 /tasks [get]
@@ -501,7 +501,7 @@ func (api *API) convertTasks(ctx context.Context, requesterID uuid.UUID, dbTasks
// @ID get-ai-task-by-id-or-name
// @Security CoderSessionToken
// @Produce json
// @Tags Experimental
// @Tags Tasks
// @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
@@ -573,7 +573,7 @@ func (api *API) taskGet(rw http.ResponseWriter, r *http.Request) {
// @Summary Delete AI task
// @ID delete-ai-task
// @Security CoderSessionToken
// @Tags Experimental
// @Tags Tasks
// @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
@@ -642,7 +642,7 @@ func (api *API) taskDelete(rw http.ResponseWriter, r *http.Request) {
// @ID update-ai-task-input
// @Security CoderSessionToken
// @Accept json
// @Tags Experimental
// @Tags Tasks
// @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"
@@ -722,7 +722,7 @@ func (api *API) taskUpdateInput(rw http.ResponseWriter, r *http.Request) {
// @ID send-input-to-ai-task
// @Security CoderSessionToken
// @Accept json
// @Tags Experimental
// @Tags Tasks
// @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"
@@ -791,7 +791,7 @@ func (api *API) taskSend(rw http.ResponseWriter, r *http.Request) {
// @ID get-ai-task-logs
// @Security CoderSessionToken
// @Produce json
// @Tags Experimental
// @Tags Tasks
// @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
+7 -7
View File
@@ -5463,7 +5463,7 @@ const docTemplate = `{
"application/json"
],
"tags": [
"Experimental"
"Tasks"
],
"summary": "List AI tasks",
"operationId": "list-ai-tasks",
@@ -5499,7 +5499,7 @@ const docTemplate = `{
"application/json"
],
"tags": [
"Experimental"
"Tasks"
],
"summary": "Create a new AI task",
"operationId": "create-a-new-ai-task",
@@ -5542,7 +5542,7 @@ const docTemplate = `{
"application/json"
],
"tags": [
"Experimental"
"Tasks"
],
"summary": "Get AI task by ID or name",
"operationId": "get-ai-task-by-id-or-name",
@@ -5578,7 +5578,7 @@ const docTemplate = `{
}
],
"tags": [
"Experimental"
"Tasks"
],
"summary": "Delete AI task",
"operationId": "delete-ai-task",
@@ -5616,7 +5616,7 @@ const docTemplate = `{
"application/json"
],
"tags": [
"Experimental"
"Tasks"
],
"summary": "Update AI task input",
"operationId": "update-ai-task-input",
@@ -5663,7 +5663,7 @@ const docTemplate = `{
"application/json"
],
"tags": [
"Experimental"
"Tasks"
],
"summary": "Get AI task logs",
"operationId": "get-ai-task-logs",
@@ -5704,7 +5704,7 @@ const docTemplate = `{
"application/json"
],
"tags": [
"Experimental"
"Tasks"
],
"summary": "Send input to AI task",
"operationId": "send-input-to-ai-task",
+7 -7
View File
@@ -4819,7 +4819,7 @@
}
],
"produces": ["application/json"],
"tags": ["Experimental"],
"tags": ["Tasks"],
"summary": "List AI tasks",
"operationId": "list-ai-tasks",
"parameters": [
@@ -4849,7 +4849,7 @@
],
"consumes": ["application/json"],
"produces": ["application/json"],
"tags": ["Experimental"],
"tags": ["Tasks"],
"summary": "Create a new AI task",
"operationId": "create-a-new-ai-task",
"parameters": [
@@ -4888,7 +4888,7 @@
}
],
"produces": ["application/json"],
"tags": ["Experimental"],
"tags": ["Tasks"],
"summary": "Get AI task by ID or name",
"operationId": "get-ai-task-by-id-or-name",
"parameters": [
@@ -4922,7 +4922,7 @@
"CoderSessionToken": []
}
],
"tags": ["Experimental"],
"tags": ["Tasks"],
"summary": "Delete AI task",
"operationId": "delete-ai-task",
"parameters": [
@@ -4956,7 +4956,7 @@
}
],
"consumes": ["application/json"],
"tags": ["Experimental"],
"tags": ["Tasks"],
"summary": "Update AI task input",
"operationId": "update-ai-task-input",
"parameters": [
@@ -4999,7 +4999,7 @@
}
],
"produces": ["application/json"],
"tags": ["Experimental"],
"tags": ["Tasks"],
"summary": "Get AI task logs",
"operationId": "get-ai-task-logs",
"parameters": [
@@ -5036,7 +5036,7 @@
}
],
"consumes": ["application/json"],
"tags": ["Experimental"],
"tags": ["Tasks"],
"summary": "Send input to AI task",
"operationId": "send-input-to-ai-task",
"parameters": [
+4 -4
View File
@@ -1166,10 +1166,6 @@
"title": "Enterprise",
"path": "./reference/api/enterprise.md"
},
{
"title": "Experimental",
"path": "./reference/api/experimental.md"
},
{
"title": "Files",
"path": "./reference/api/files.md"
@@ -1214,6 +1210,10 @@
"title": "Schemas",
"path": "./reference/api/schemas.md"
},
{
"title": "Tasks",
"path": "./reference/api/tasks.md"
},
{
"title": "Templates",
"path": "./reference/api/templates.md"
@@ -1,4 +1,4 @@
# Experimental
# Tasks
## List AI tasks
+16 -16
View File
@@ -2644,22 +2644,6 @@ class ApiMethods {
markAllInboxNotificationsAsRead = async () => {
await this.axios.put<void>("/api/v2/notifications/inbox/mark-all-as-read");
};
}
// Experimental API methods call endpoints under the /api/experimental/ prefix.
// These endpoints are not stable and may change or be removed at any time.
//
// All methods must be defined with arrow function syntax. See the docstring
// above the ApiMethods class for a full explanation.
export type TaskFeedbackRating = "good" | "okay" | "bad";
export type CreateTaskFeedbackRequest = {
rate: TaskFeedbackRating;
comment?: string;
};
class ExperimentalApiMethods {
constructor(protected readonly axios: AxiosInstance) {}
createTask = async (
user: string,
@@ -2716,6 +2700,22 @@ class ExperimentalApiMethods {
setTimeout(() => res(), 500);
});
};
}
export type TaskFeedbackRating = "good" | "okay" | "bad";
export type CreateTaskFeedbackRequest = {
rate: TaskFeedbackRating;
comment?: string;
};
// Experimental API methods call endpoints under the /api/experimental/ prefix.
// These endpoints are not stable and may change or be removed at any time.
//
// All methods must be defined with arrow function syntax. See the docstring
// above the ApiMethods class for a full explanation.
class ExperimentalApiMethods {
constructor(protected readonly axios: AxiosInstance) {}
getAIBridgeInterceptions = async (options: SearchParamOptions) => {
const url = getURLWithSearchParams(
@@ -207,7 +207,7 @@ const TasksNavItem: FC<TasksNavItemProps> = ({ user }) => {
};
const { data: idleCount } = useQuery({
queryKey: ["tasks", filter],
queryFn: () => API.experimental.getTasks(filter),
queryFn: () => API.getTasks(filter),
refetchInterval: 1_000 * 60,
enabled: canSeeTasks,
refetchOnWindowFocus: true,
@@ -27,7 +27,7 @@ export const DeleteTaskSuccess: Story = {
},
},
beforeEach: () => {
spyOn(API.experimental, "deleteTask").mockResolvedValue();
spyOn(API, "deleteTask").mockResolvedValue();
},
play: async ({ canvasElement, step }) => {
const body = within(canvasElement.ownerDocument.body);
@@ -39,7 +39,7 @@ export const DeleteTaskSuccess: Story = {
await userEvent.click(confirmButton);
await step("Confirm delete", async () => {
await waitFor(() => {
expect(API.experimental.deleteTask).toHaveBeenCalledWith(
expect(API.deleteTask).toHaveBeenCalledWith(
MockTask.owner_name,
MockTask.id,
);
@@ -20,7 +20,7 @@ export const TaskDeleteDialog: FC<TaskDeleteDialogProps> = ({
}) => {
const queryClient = new QueryClient();
const deleteTaskMutation = useMutation({
mutationFn: () => API.experimental.deleteTask(task.owner_name, task.id),
mutationFn: () => API.deleteTask(task.owner_name, task.id),
onSuccess: async () => {
await queryClient.invalidateQueries({ queryKey: ["tasks"] });
},
@@ -21,7 +21,7 @@ export const Idle: Story = {};
export const Submitting: Story = {
beforeEach: async () => {
spyOn(API.experimental, "createTaskFeedback").mockImplementation(() => {
spyOn(API, "createTaskFeedback").mockImplementation(() => {
return new Promise(() => {});
});
},
@@ -53,7 +53,7 @@ export const Success: Story = {
},
decorators: [withGlobalSnackbar],
beforeEach: async () => {
spyOn(API.experimental, "createTaskFeedback").mockResolvedValue();
spyOn(API, "createTaskFeedback").mockResolvedValue();
},
play: async ({ canvasElement, step }) => {
const body = within(canvasElement.ownerDocument.body);
@@ -77,20 +77,17 @@ export const Success: Story = {
step("submitted successfully", async () => {
await body.findByText("Feedback submitted successfully");
expect(API.experimental.createTaskFeedback).toHaveBeenCalledWith(
MockTask.id,
{
rate: "regular",
comment: "This is my comment",
},
);
expect(API.createTaskFeedback).toHaveBeenCalledWith(MockTask.id, {
rate: "regular",
comment: "This is my comment",
});
});
},
};
export const Failure: Story = {
beforeEach: async () => {
spyOn(API.experimental, "createTaskFeedback").mockRejectedValue(
spyOn(API, "createTaskFeedback").mockRejectedValue(
mockApiError({
message: "Failed to submit feedback",
detail: "Server is down",
@@ -42,7 +42,7 @@ export const TaskFeedbackDialog: FC<TaskFeedbackDialogProps> = ({
isPending,
} = useMutation({
mutationFn: (req: CreateTaskFeedbackRequest) =>
API.experimental.createTaskFeedback(taskId, req),
API.createTaskFeedback(taskId, req),
onSuccess: () => {
displaySuccess("Feedback submitted successfully");
},
@@ -114,7 +114,7 @@ export const SubmitDisabledWhenPromptEmpty: Story = {
export const Submitting: Story = {
decorators: [withGlobalSnackbar],
beforeEach: () => {
spyOn(API.experimental, "createTask").mockImplementation(
spyOn(API, "createTask").mockImplementation(
() =>
// Never resolve to keep the component in the submitting state for visual testing.
new Promise(() => {}),
@@ -153,7 +153,7 @@ export const OnSuccess: Story = {
...MockTemplate,
active_version_id: activeVersionId,
});
spyOn(API.experimental, "createTask").mockResolvedValue(MockTask);
spyOn(API, "createTask").mockResolvedValue(MockTask);
},
play: async ({ canvasElement, step }) => {
const canvas = within(canvasElement);
@@ -167,14 +167,11 @@ export const OnSuccess: Story = {
});
await step("Uses latest template version", () => {
expect(API.experimental.createTask).toHaveBeenCalledWith(
MockUserOwner.id,
{
input: MockNewTaskData.initial_prompt,
template_version_id: `${MockTemplate.active_version_id}-latest`,
template_version_preset_id: undefined,
},
);
expect(API.createTask).toHaveBeenCalledWith(MockUserOwner.id, {
input: MockNewTaskData.initial_prompt,
template_version_id: `${MockTemplate.active_version_id}-latest`,
template_version_preset_id: undefined,
});
});
await step("Displays success message", async () => {
@@ -232,7 +229,7 @@ export const ChangeTemplate: Story = {
}
return Promise.resolve([]);
});
spyOn(API.experimental, "createTask").mockResolvedValue(MockTask);
spyOn(API, "createTask").mockResolvedValue(MockTask);
},
play: async ({ canvasElement, step }) => {
const canvas = within(canvasElement);
@@ -268,7 +265,7 @@ export const SelectTemplateVersion: Story = {
name: "v1.0.0",
},
]);
spyOn(API.experimental, "createTask").mockResolvedValue(MockTask);
spyOn(API, "createTask").mockResolvedValue(MockTask);
},
play: async ({ canvasElement, step }) => {
const canvas = within(canvasElement);
@@ -295,14 +292,11 @@ export const SelectTemplateVersion: Story = {
});
await step("Uses selected version", () => {
expect(API.experimental.createTask).toHaveBeenCalledWith(
MockUserOwner.id,
{
input: MockNewTaskData.initial_prompt,
template_version_id: "test-template-version-2",
template_version_preset_id: undefined,
},
);
expect(API.createTask).toHaveBeenCalledWith(MockUserOwner.id, {
input: MockNewTaskData.initial_prompt,
template_version_id: "test-template-version-2",
template_version_preset_id: undefined,
});
});
await step("Displays success message", async () => {
@@ -317,8 +311,8 @@ export const OnError: Story = {
decorators: [withGlobalSnackbar],
beforeEach: () => {
spyOn(API, "getTemplate").mockResolvedValue(MockTemplate);
spyOn(API.experimental, "getTasks").mockResolvedValue(MockTasks);
spyOn(API.experimental, "createTask").mockRejectedValue(
spyOn(API, "getTasks").mockResolvedValue(MockTasks);
spyOn(API, "createTask").mockRejectedValue(
mockApiError({
message: "Failed to create task",
detail: "You don't have permission to create tasks.",
@@ -344,10 +338,10 @@ export const OnError: Story = {
export const AuthenticatedExternalAuth: Story = {
beforeEach: () => {
spyOn(API.experimental, "getTasks")
spyOn(API, "getTasks")
.mockResolvedValueOnce(MockTasks)
.mockResolvedValue([MockNewTaskData, ...MockTasks]);
spyOn(API.experimental, "createTask").mockResolvedValue(MockTask);
spyOn(API, "createTask").mockResolvedValue(MockTask);
spyOn(API, "getTemplateVersionExternalAuth").mockResolvedValue([
MockTemplateVersionExternalAuthGithubAuthenticated,
]);
@@ -370,10 +364,10 @@ export const AuthenticatedExternalAuth: Story = {
export const MissingExternalAuth: Story = {
beforeEach: () => {
spyOn(API.experimental, "getTasks")
spyOn(API, "getTasks")
.mockResolvedValueOnce(MockTasks)
.mockResolvedValue([MockNewTaskData, ...MockTasks]);
spyOn(API.experimental, "createTask").mockResolvedValue(MockTask);
spyOn(API, "createTask").mockResolvedValue(MockTask);
spyOn(API, "getTemplateVersionExternalAuth").mockResolvedValue([
MockTemplateVersionExternalAuthGithub,
]);
@@ -396,10 +390,10 @@ export const MissingExternalAuth: Story = {
export const ExternalAuthError: Story = {
beforeEach: () => {
spyOn(API.experimental, "getTasks")
spyOn(API, "getTasks")
.mockResolvedValueOnce(MockTasks)
.mockResolvedValue([MockNewTaskData, ...MockTasks]);
spyOn(API.experimental, "createTask").mockResolvedValue(MockTask);
spyOn(API, "createTask").mockResolvedValue(MockTask);
spyOn(API, "getTemplateVersionExternalAuth").mockRejectedValue(
mockApiError({
message: "Failed to load external auth",
@@ -193,7 +193,7 @@ const CreateTaskForm: FC<CreateTaskFormProps> = ({ templates, onSuccess }) => {
mutationFn: async ({ prompt }: CreateTaskMutationFnProps) => {
// Users with updateTemplates permission can select the version to use.
if (permissions.updateTemplates) {
return API.experimental.createTask(user.id, {
return API.createTask(user.id, {
input: prompt,
template_version_id: selectedVersionId,
template_version_preset_id: selectedPresetId,
@@ -453,7 +453,7 @@ async function createTaskWithLatestTemplateVersion(
presetId: string | undefined,
): Promise<Task> {
const template = await API.getTemplate(templateId);
return API.experimental.createTask(userId, {
return API.createTask(userId, {
input,
template_version_id: template.active_version_id,
template_version_preset_id: presetId,
@@ -49,13 +49,13 @@ type Story = StoryObj<typeof TasksSidebar>;
export const Loading: Story = {
beforeEach: () => {
spyOn(API.experimental, "getTasks").mockReturnValue(new Promise(() => {}));
spyOn(API, "getTasks").mockReturnValue(new Promise(() => {}));
},
};
export const Failed: Story = {
beforeEach: () => {
spyOn(API.experimental, "getTasks").mockRejectedValue(
spyOn(API, "getTasks").mockRejectedValue(
mockApiError({
message: "Failed to fetch tasks",
}),
@@ -65,7 +65,7 @@ export const Failed: Story = {
export const Loaded: Story = {
beforeEach: () => {
spyOn(API.experimental, "getTasks").mockResolvedValue(MockTasks);
spyOn(API, "getTasks").mockResolvedValue(MockTasks);
},
};
@@ -82,13 +82,13 @@ export const DisplayName: Story = {
export const Empty: Story = {
beforeEach: () => {
spyOn(API.experimental, "getTasks").mockResolvedValue([]);
spyOn(API, "getTasks").mockResolvedValue([]);
},
};
export const Closed: Story = {
beforeEach: () => {
spyOn(API.experimental, "getTasks").mockResolvedValue(MockTasks);
spyOn(API, "getTasks").mockResolvedValue(MockTasks);
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
@@ -99,7 +99,7 @@ export const Closed: Story = {
export const OpenOptionsMenu: Story = {
beforeEach: () => {
spyOn(API.experimental, "getTasks").mockResolvedValue(MockTasks);
spyOn(API, "getTasks").mockResolvedValue(MockTasks);
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
@@ -112,7 +112,7 @@ export const OpenOptionsMenu: Story = {
export const OpenDeleteDialog: Story = {
beforeEach: () => {
spyOn(API.experimental, "getTasks").mockResolvedValue(MockTasks);
spyOn(API, "getTasks").mockResolvedValue(MockTasks);
},
play: async ({ canvasElement, step }) => {
await step("Open menu", async () => {
@@ -135,7 +135,7 @@ const TasksSidebarGroup: FC<TasksSidebarGroupProps> = ({ owner }) => {
const filter: TasksFilter = { owner };
const tasksQuery = useQuery({
queryKey: ["tasks", filter],
queryFn: () => API.experimental.getTasks(filter),
queryFn: () => API.getTasks(filter),
refetchInterval: 10_000,
});
+23 -25
View File
@@ -66,7 +66,7 @@ const meta: Meta<typeof TaskPage> = {
component: TaskPage,
decorators: [withProxyProvider(), withAuthProvider],
beforeEach: () => {
spyOn(API.experimental, "getTasks").mockResolvedValue(MockTasks);
spyOn(API, "getTasks").mockResolvedValue(MockTasks);
},
parameters: {
layout: "fullscreen",
@@ -88,13 +88,11 @@ type Story = StoryObj<typeof TaskPage>;
export const LoadingTask: Story = {
beforeEach: () => {
spyOn(API.experimental, "getTask").mockImplementation(
() => new Promise(() => {}),
);
spyOn(API, "getTask").mockImplementation(() => new Promise(() => {}));
},
play: async () => {
await waitFor(() => {
expect(API.experimental.getTask).toHaveBeenCalledWith(
expect(API.getTask).toHaveBeenCalledWith(
MockTask.owner_name,
MockTask.id,
);
@@ -104,7 +102,7 @@ export const LoadingTask: Story = {
export const LoadingWorkspace: Story = {
beforeEach: () => {
spyOn(API.experimental, "getTask").mockResolvedValue(MockTask);
spyOn(API, "getTask").mockResolvedValue(MockTask);
spyOn(API, "getWorkspaceByOwnerAndName").mockImplementation(
() => new Promise(() => {}),
);
@@ -113,7 +111,7 @@ export const LoadingWorkspace: Story = {
export const LoadingTaskError: Story = {
beforeEach: () => {
spyOn(API.experimental, "getTask").mockRejectedValue(
spyOn(API, "getTask").mockRejectedValue(
mockApiError({
message: "Failed to load task",
detail: "You don't have permission to access this resource.",
@@ -124,7 +122,7 @@ export const LoadingTaskError: Story = {
export const LoadingWorkspaceError: Story = {
beforeEach: () => {
spyOn(API.experimental, "getTask").mockResolvedValue(MockTask);
spyOn(API, "getTask").mockResolvedValue(MockTask);
spyOn(API, "getWorkspaceByOwnerAndName").mockRejectedValue(
mockApiError({
message: "Failed to load workspace",
@@ -136,7 +134,7 @@ export const LoadingWorkspaceError: Story = {
export const WaitingOnBuild: Story = {
beforeEach: () => {
spyOn(API.experimental, "getTask").mockResolvedValue(MockTask);
spyOn(API, "getTask").mockResolvedValue(MockTask);
spyOn(API, "getWorkspaceByOwnerAndName").mockResolvedValue(
MockStartingWorkspace,
);
@@ -145,7 +143,7 @@ export const WaitingOnBuild: Story = {
export const FailedBuild: Story = {
beforeEach: () => {
spyOn(API.experimental, "getTask").mockResolvedValue(MockTask);
spyOn(API, "getTask").mockResolvedValue(MockTask);
spyOn(API, "getWorkspaceByOwnerAndName").mockResolvedValue(
MockFailedWorkspace,
);
@@ -154,7 +152,7 @@ export const FailedBuild: Story = {
export const TerminatedBuild: Story = {
beforeEach: () => {
spyOn(API.experimental, "getTask").mockResolvedValue(MockTask);
spyOn(API, "getTask").mockResolvedValue(MockTask);
spyOn(API, "getWorkspaceByOwnerAndName").mockResolvedValue(
MockStoppedWorkspace,
);
@@ -163,7 +161,7 @@ export const TerminatedBuild: Story = {
export const TerminatedBuildWithStatus: Story = {
beforeEach: () => {
spyOn(API.experimental, "getTask").mockResolvedValue(MockTask);
spyOn(API, "getTask").mockResolvedValue(MockTask);
spyOn(API, "getWorkspaceByOwnerAndName").mockResolvedValue({
...MockStoppedWorkspace,
latest_app_status: MockWorkspaceAppStatus,
@@ -173,7 +171,7 @@ export const TerminatedBuildWithStatus: Story = {
export const DeletedWorkspace: Story = {
beforeEach: () => {
spyOn(API.experimental, "getTask").mockResolvedValue(MockTask);
spyOn(API, "getTask").mockResolvedValue(MockTask);
spyOn(API, "getWorkspaceByOwnerAndName").mockResolvedValue(
MockDeletedWorkspace,
);
@@ -182,7 +180,7 @@ export const DeletedWorkspace: Story = {
export const WaitingStartupScripts: Story = {
beforeEach: () => {
spyOn(API.experimental, "getTask").mockResolvedValue(MockTask);
spyOn(API, "getTask").mockResolvedValue(MockTask);
spyOn(API, "getWorkspaceByOwnerAndName").mockResolvedValue({
...MockWorkspace,
latest_build: {
@@ -336,7 +334,7 @@ export const SidebarAppNotFound: Story = {
MockClaudeCodeApp,
MockVSCodeApp,
);
spyOn(API.experimental, "getTask").mockResolvedValue({
spyOn(API, "getTask").mockResolvedValue({
...task,
workspace_app_id: null,
});
@@ -350,7 +348,7 @@ export const SidebarAppHealthDisabled: Story = {
{ ...MockClaudeCodeApp, health: "disabled" },
MockVSCodeApp,
);
spyOn(API.experimental, "getTask").mockResolvedValue(task);
spyOn(API, "getTask").mockResolvedValue(task);
spyOn(API, "getWorkspaceByOwnerAndName").mockResolvedValue(workspace);
},
};
@@ -361,7 +359,7 @@ export const SidebarAppInitializing: Story = {
{ ...MockClaudeCodeApp, health: "initializing" },
MockVSCodeApp,
);
spyOn(API.experimental, "getTask").mockResolvedValue(task);
spyOn(API, "getTask").mockResolvedValue(task);
spyOn(API, "getWorkspaceByOwnerAndName").mockResolvedValue(workspace);
},
};
@@ -372,7 +370,7 @@ export const SidebarAppHealthy: Story = {
{ ...MockClaudeCodeApp, health: "healthy" },
MockVSCodeApp,
);
spyOn(API.experimental, "getTask").mockResolvedValue(task);
spyOn(API, "getTask").mockResolvedValue(task);
spyOn(API, "getWorkspaceByOwnerAndName").mockResolvedValue(workspace);
},
};
@@ -383,7 +381,7 @@ export const SidebarAppUnhealthy: Story = {
{ ...MockClaudeCodeApp, health: "unhealthy" },
MockVSCodeApp,
);
spyOn(API.experimental, "getTask").mockResolvedValue(task);
spyOn(API, "getTask").mockResolvedValue(task);
spyOn(API, "getWorkspaceByOwnerAndName").mockResolvedValue(workspace);
},
};
@@ -394,7 +392,7 @@ const mainAppHealthStory = (health: WorkspaceApp["health"]) => ({
...MockVSCodeApp,
health,
});
spyOn(API.experimental, "getTask").mockResolvedValue(task);
spyOn(API, "getTask").mockResolvedValue(task);
spyOn(API, "getWorkspaceByOwnerAndName").mockResolvedValue(workspace);
},
});
@@ -410,7 +408,7 @@ export const Active: Story = {
MockClaudeCodeApp,
MockVSCodeApp,
);
spyOn(API.experimental, "getTask").mockResolvedValue(task);
spyOn(API, "getTask").mockResolvedValue(task);
spyOn(API, "getWorkspaceByOwnerAndName").mockResolvedValue(workspace);
},
play: async ({ canvasElement }) => {
@@ -433,7 +431,7 @@ export const ActivePreview: Story = {
MockClaudeCodeApp,
MockVSCodeApp,
);
spyOn(API.experimental, "getTask").mockResolvedValue(task);
spyOn(API, "getTask").mockResolvedValue(task);
spyOn(API, "getWorkspaceByOwnerAndName").mockResolvedValue(workspace);
},
play: async ({ canvasElement }) => {
@@ -446,7 +444,7 @@ export const ActivePreview: Story = {
export const WorkspaceStarting: Story = {
decorators: [withGlobalSnackbar],
beforeEach: () => {
spyOn(API.experimental, "getTask").mockResolvedValue(MockTask);
spyOn(API, "getTask").mockResolvedValue(MockTask);
spyOn(API, "getWorkspaceByOwnerAndName").mockResolvedValue(
MockStoppedWorkspace,
);
@@ -484,7 +482,7 @@ export const WorkspaceStarting: Story = {
export const WorkspaceStartFailure: Story = {
decorators: [withGlobalSnackbar],
beforeEach: () => {
spyOn(API.experimental, "getTask").mockResolvedValue(MockTask);
spyOn(API, "getTask").mockResolvedValue(MockTask);
spyOn(API, "getWorkspaceByOwnerAndName").mockResolvedValue(
MockStoppedWorkspace,
);
@@ -522,7 +520,7 @@ export const WorkspaceStartFailure: Story = {
export const WorkspaceStartFailureWithDialog: Story = {
beforeEach: () => {
spyOn(API.experimental, "getTask").mockResolvedValue(MockTask);
spyOn(API, "getTask").mockResolvedValue(MockTask);
spyOn(API, "getWorkspaceByOwnerAndName").mockResolvedValue(
MockStoppedWorkspace,
);
+1 -1
View File
@@ -62,7 +62,7 @@ const TaskPage = () => {
};
const { data: task, ...taskQuery } = useQuery({
queryKey: ["tasks", username, taskId],
queryFn: () => API.experimental.getTask(username, taskId),
queryFn: () => API.getTask(username, taskId),
refetchInterval: ({ state }) => {
return state.error ? false : 5_000;
},
@@ -83,7 +83,7 @@ export const LoadingTemplatesError: Story = {
export const LoadingTasks: Story = {
beforeEach: () => {
spyOn(API, "getTemplates").mockResolvedValue([MockTemplate]);
spyOn(API.experimental, "getTasks").mockImplementation(
spyOn(API, "getTasks").mockImplementation(
() => new Promise(() => 1000 * 60 * 60),
);
},
@@ -101,7 +101,7 @@ export const LoadingTasks: Story = {
export const LoadingTasksError: Story = {
beforeEach: () => {
spyOn(API, "getTemplates").mockResolvedValue([MockTemplate]);
spyOn(API.experimental, "getTasks").mockRejectedValue(
spyOn(API, "getTasks").mockRejectedValue(
mockApiError({
message: "Failed to load tasks",
}),
@@ -112,14 +112,14 @@ export const LoadingTasksError: Story = {
export const EmptyTasks: Story = {
beforeEach: () => {
spyOn(API, "getTemplates").mockResolvedValue([MockTemplate]);
spyOn(API.experimental, "getTasks").mockResolvedValue([]);
spyOn(API, "getTasks").mockResolvedValue([]);
},
};
export const LoadedTasks: Story = {
beforeEach: () => {
spyOn(API, "getTemplates").mockResolvedValue([MockTemplate]);
spyOn(API.experimental, "getTasks").mockResolvedValue(MockTasks);
spyOn(API, "getTasks").mockResolvedValue(MockTasks);
},
};
@@ -142,7 +142,7 @@ export const LoadedTasksWaitingForInputTab: Story = {
beforeEach: () => {
const [firstTask, ...otherTasks] = MockTasks;
spyOn(API, "getTemplates").mockResolvedValue([MockTemplate]);
spyOn(API.experimental, "getTasks").mockResolvedValue([
spyOn(API, "getTasks").mockResolvedValue([
{
...firstTask,
current_state: {
@@ -173,7 +173,7 @@ export const NonAdmin: Story = {
},
beforeEach: () => {
spyOn(API, "getTemplates").mockResolvedValue([MockTemplate]);
spyOn(API.experimental, "getTasks").mockResolvedValue(MockTasks);
spyOn(API, "getTasks").mockResolvedValue(MockTasks);
},
play: async ({ canvasElement, step }) => {
const canvas = within(canvasElement);
@@ -190,7 +190,7 @@ export const NonAdmin: Story = {
export const OpenDeleteDialog: Story = {
beforeEach: () => {
spyOn(API, "getTemplates").mockResolvedValue([MockTemplate]);
spyOn(API.experimental, "getTasks").mockResolvedValue(MockTasks);
spyOn(API, "getTasks").mockResolvedValue(MockTasks);
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
+1 -1
View File
@@ -40,7 +40,7 @@ const TasksPage: FC = () => {
};
const tasksQuery = useQuery({
queryKey: ["tasks", filter],
queryFn: () => API.experimental.getTasks(filter),
queryFn: () => API.getTasks(filter),
refetchInterval: 10_000,
});
const idleTasks = tasksQuery.data?.filter(