Content-Length: 7718 | pFad | http://github.com/coder/coder/pull/18919.diff

thub.com diff --git a/coderd/aitasks.go b/coderd/aitasks.go index a982ccc39b26b..6d91098b63a81 100644 --- a/coderd/aitasks.go +++ b/coderd/aitasks.go @@ -61,3 +61,19 @@ func (api *API) aiTasksPrompts(rw http.ResponseWriter, r *http.Request) { Prompts: promptsByBuildID, }) } + +// This endpoint is experimental and not guaranteed to be stable, so we're not +// generating public-facing documentation for it. +func (api *API) aiTasksStats(rw http.ResponseWriter, r *http.Request) { + ctx := r.Context() + _ = api // Suppress unused receiver warning + + stats := codersdk.AITasksStatsResponse{ + ActiveTasks: 3, + CompletedTasks: 15, + FailedTasks: 2, + TotalWorkspacesWithTasks: 8, + } + + httpapi.Write(ctx, rw, http.StatusOK, stats) +} diff --git a/coderd/coderd.go b/coderd/coderd.go index c3c1fb09cc6cc..89572ada29fba 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -979,6 +979,7 @@ func New(options *Options) *API { r.Use(apiKeyMiddleware) r.Route("/aitasks", func(r chi.Router) { r.Get("/prompts", api.aiTasksPrompts) + r.Get("/stats", api.aiTasksStats) }) r.Route("/mcp", func(r chi.Router) { r.Use( diff --git a/codersdk/aitasks.go b/codersdk/aitasks.go index 89ca9c948f272..3876db0e07d28 100644 --- a/codersdk/aitasks.go +++ b/codersdk/aitasks.go @@ -18,6 +18,13 @@ type AITasksPromptsResponse struct { Prompts map[string]string `json:"prompts"` } +type AITasksStatsResponse struct { + ActiveTasks int `json:"active_tasks"` + CompletedTasks int `json:"completed_tasks"` + FailedTasks int `json:"failed_tasks"` + TotalWorkspacesWithTasks int `json:"total_workspaces_with_tasks"` +} + // AITaskPrompts returns prompts for multiple workspace builds by their IDs. func (c *ExperimentalClient) AITaskPrompts(ctx context.Context, buildIDs []uuid.UUID) (AITasksPromptsResponse, error) { if len(buildIDs) == 0 { diff --git a/site/src/api/api.ts b/site/src/api/api.ts index 013c018d5c656..34d5eb6451ff4 100644 --- a/site/src/api/api.ts +++ b/site/src/api/api.ts @@ -2596,6 +2596,13 @@ class ApiMethods { markAllInboxNotificationsAsRead = async () => { await this.axios.put("/api/v2/notifications/inbox/mark-all-as-read"); }; + + getAITasksStats = async (): Promise => { + const response = await this.axios.get( + "/api/experimental/aitasks/stats", + ); + return response.data; + }; } // Experimental API methods call endpoints under the /api/experimental/ prefix. @@ -2701,9 +2708,12 @@ interface ClientApi extends ApiMethods { } class Api extends ApiMethods implements ClientApi { + experimental: ExperimentalApiMethods; + constructor() { const scopedAxiosInstance = getConfiguredAxiosInstance(); super(scopedAxiosInstance); + this.experimental = new ExperimentalApiMethods(scopedAxiosInstance); } // As with ApiMethods, all public methods should be defined with arrow diff --git a/site/src/api/queries/aitasks.ts b/site/src/api/queries/aitasks.ts new file mode 100644 index 0000000000000..76aedf8a2a738 --- /dev/null +++ b/site/src/api/queries/aitasks.ts @@ -0,0 +1,9 @@ +import type { UseQueryOptions } from "react-query"; +import { API } from "../api"; +import type * as TypesGen from "../typesGenerated"; + +export const aiTasksStats = + (): UseQueryOptions => ({ + queryKey: ["aitasks", "stats"], + queryFn: API.getAITasksStats, + }); diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index b4df5654824bc..ffb27624ed3ba 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -14,6 +14,14 @@ export interface AITasksPromptsResponse { readonly prompts: Record; } +// From codersdk/aitasks.go +export interface AITasksStatsResponse { + readonly active_tasks: number; + readonly completed_tasks: number; + readonly failed_tasks: number; + readonly total_workspaces_with_tasks: number; +} + // From codersdk/apikey.go export interface APIKey { readonly id: string; diff --git a/site/src/modules/dashboard/DeploymentBanner/DeploymentBanner.tsx b/site/src/modules/dashboard/DeploymentBanner/DeploymentBanner.tsx index 189e1b8039cd6..b3d8303e5fd12 100644 --- a/site/src/modules/dashboard/DeploymentBanner/DeploymentBanner.tsx +++ b/site/src/modules/dashboard/DeploymentBanner/DeploymentBanner.tsx @@ -1,5 +1,6 @@ +import { aiTasksStats } from "api/queries/aitasks"; import { health } from "api/queries/debug"; -import { deploymentStats } from "api/queries/deployment"; +import { deploymentConfig, deploymentStats } from "api/queries/deployment"; import { useAuthenticated } from "hooks"; import type { FC } from "react"; import { useQuery } from "react-query"; @@ -19,10 +20,20 @@ const HIDE_DEPLOYMENT_BANNER_PATHS = [ export const DeploymentBanner: FC = () => { const { permissions } = useAuthenticated(); const deploymentStatsQuery = useQuery(deploymentStats()); + const deploymentConfigQuery = useQuery({ + ...deploymentConfig(), + enabled: permissions.viewDeploymentConfig, + }); const healthQuery = useQuery({ ...health(), enabled: permissions.viewDeploymentConfig, }); + const aiTasksQuery = useQuery({ + ...aiTasksStats(), + enabled: + permissions.viewDeploymentConfig && + !deploymentConfigQuery.data?.config.hide_ai_tasks, + }); const location = useLocation(); const isHidden = HIDE_DEPLOYMENT_BANNER_PATHS.some((regex) => regex.test(location.pathname), @@ -40,6 +51,7 @@ export const DeploymentBanner: FC = () => { deploymentStatsQuery.refetch()} /> ); diff --git a/site/src/modules/dashboard/DeploymentBanner/DeploymentBannerView.tsx b/site/src/modules/dashboard/DeploymentBanner/DeploymentBannerView.tsx index 1a5ef6ebb4cfb..dd9cd8b909617 100644 --- a/site/src/modules/dashboard/DeploymentBanner/DeploymentBannerView.tsx +++ b/site/src/modules/dashboard/DeploymentBanner/DeploymentBannerView.tsx @@ -4,6 +4,7 @@ import Button from "@mui/material/Button"; import Link from "@mui/material/Link"; import Tooltip from "@mui/material/Tooltip"; import type { + AITasksStatsResponse, DeploymentStats, HealthcheckReport, WorkspaceStatus, @@ -41,12 +42,14 @@ const bannerHeight = 36; interface DeploymentBannerViewProps { health?: HealthcheckReport; stats?: DeploymentStats; + aiTasksStats?: AITasksStatsResponse; fetchStats?: () => void; } export const DeploymentBannerView: FC = ({ health, stats, + aiTasksStats, fetchStats, }) => { const theme = useTheme(); @@ -278,6 +281,34 @@ export const DeploymentBannerView: FC = ({ + {aiTasksStats && ( +
+
AI Tasks
+
+ +
+ + {aiTasksStats.active_tasks} +
+
+ + +
+ + {aiTasksStats.completed_tasks} +
+
+ + +
+ + {aiTasksStats.failed_tasks} +
+
+
+
+ )} +








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/coder/coder/pull/18919.diff

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy