Content-Length: 77989 | pFad | http://github.com/coder/coder/pull/18934.patch

thub.com From e54de1c75176a28995ed9ffdaee477202ec36a14 Mon Sep 17 00:00:00 2001 From: Michael Suchacz <203725896+ibetitsmike@users.noreply.github.com> Date: Thu, 17 Jul 2025 14:32:59 +0000 Subject: [PATCH 01/12] initial implementation --- .../LicensesSettingsPage.tsx | 1 + .../LicensesSettingsPageView.tsx | 20 +- .../ManagedAgentsConsumption.stories.tsx | 52 +++++ .../ManagedAgentsConsumption.tsx | 210 ++++++++++++++++++ 4 files changed, 282 insertions(+), 1 deletion(-) create mode 100644 site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.stories.tsx create mode 100644 site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx diff --git a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/LicensesSettingsPage.tsx b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/LicensesSettingsPage.tsx index 5f617412a0c04..535a08b8228c9 100644 --- a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/LicensesSettingsPage.tsx +++ b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/LicensesSettingsPage.tsx @@ -85,6 +85,7 @@ const LicensesSettingsPage: FC = () => { isRemovingLicense={isRemovingLicense} removeLicense={(licenseId: number) => removeLicenseApi(licenseId)} activeUsers={userStatusCount?.active} + entitlements={entitlementsQuery.data} refreshEntitlements={async () => { try { await refreshEntitlementsMutation.mutateAsync(); diff --git a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/LicensesSettingsPageView.tsx b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/LicensesSettingsPageView.tsx index eb60361883b72..95655025f5a00 100644 --- a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/LicensesSettingsPageView.tsx +++ b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/LicensesSettingsPageView.tsx @@ -4,7 +4,7 @@ import MuiLink from "@mui/material/Link"; import Skeleton from "@mui/material/Skeleton"; import Tooltip from "@mui/material/Tooltip"; import type { GetLicensesResponse } from "api/api"; -import type { UserStatusChangeCount } from "api/typesGenerated"; +import type { Entitlements, UserStatusChangeCount } from "api/typesGenerated"; import { Button } from "components/Button/Button"; import { SettingsHeader, @@ -20,6 +20,7 @@ import Confetti from "react-confetti"; import { Link } from "react-router-dom"; import { LicenseCard } from "./LicenseCard"; import { LicenseSeatConsumptionChart } from "./LicenseSeatConsumptionChart"; +import { ManagedAgentsConsumption } from "./ManagedAgentsConsumption"; type Props = { showConfetti: boolean; @@ -32,6 +33,7 @@ type Props = { removeLicense: (licenseId: number) => void; refreshEntitlements: () => void; activeUsers: UserStatusChangeCount[] | undefined; + entitlements?: Entitlements; }; const LicensesSettingsPageView: FC = ({ @@ -45,9 +47,14 @@ const LicensesSettingsPageView: FC = ({ removeLicense, refreshEntitlements, activeUsers, + entitlements, }) => { const theme = useTheme(); const { width, height } = useWindowSize(); + const managedAgentFeature = entitlements?.features?.managed_agent_limit; + const managedAgentLimitStarts = entitlements?.features?.managed_agent_limit?.usage_period?.start; + const managedAgentLimitExpires = entitlements?.features?.managed_agent_limit?.usage_period?.end; + const managedAgentFeatureEnabled = entitlements?.features?.managed_agent_limit?.enabled; return ( <> @@ -151,6 +158,17 @@ const LicensesSettingsPageView: FC = ({ }))} /> )} + + {licenses && licenses.length > 0 && managedAgentFeature && ( + + )} ); diff --git a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.stories.tsx b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.stories.tsx new file mode 100644 index 0000000000000..fbe9713d03e5d --- /dev/null +++ b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.stories.tsx @@ -0,0 +1,52 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { ManagedAgentsConsumption } from "./ManagedAgentsConsumption"; + +const meta: Meta = { + title: + "pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption", + component: ManagedAgentsConsumption, + args: { + usage: 50000, + included: 60000, + limit: 120000, + startDate: "February 27, 2025", + endDate: "February 27, 2026", + }, +}; + +export default meta; +type Story = StoryObj; + +export const Default: Story = {}; + +export const NearLimit: Story = { + args: { + usage: 115000, + included: 60000, + limit: 120000, + }, +}; + +export const OverIncluded: Story = { + args: { + usage: 80000, + included: 60000, + limit: 120000, + }, +}; + +export const LowUsage: Story = { + args: { + usage: 25000, + included: 60000, + limit: 120000, + }, +}; + +export const Disabled: Story = { + args: { + usage: NaN, + included: NaN, + limit: NaN, + }, +}; diff --git a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx new file mode 100644 index 0000000000000..ff76c029850df --- /dev/null +++ b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx @@ -0,0 +1,210 @@ +import { Button } from "components/Button/Button"; +import { + Collapsible, + CollapsibleContent, + CollapsibleTrigger, +} from "components/Collapsible/Collapsible"; +import { Link } from "components/Link/Link"; +import { Stack } from "components/Stack/Stack"; +import { ChevronRightIcon } from "lucide-react"; +import type { FC } from "react"; +import { Link as RouterLink } from "react-router-dom"; +import { docs } from "utils/docs"; +import MuiLink from "@mui/material/Link"; +import { type Interpolation, type Theme } from "@emotion/react"; +import dayjs from "dayjs"; + +interface ManagedAgentsConsumptionProps { + usage: number; + included: number; + limit: number; + startDate: string; + endDate: string; + enabled?: boolean; +} + +export const ManagedAgentsConsumption: FC = ({ + usage, + included, + limit, + startDate, + endDate, + enabled = true, +}) => { + // If feature is disabled, show disabled state + if (!enabled) { + return ( +
+ + + + Managed AI Agent Feature Disabled + + + The managed AI agent feature is not included in your current license. + Contact{" "} + sales to + upgrade your license and unlock this feature. + + + +
+ ); + } + + // Calculate percentages for the progress bar + const usagePercentage = Math.min((usage / limit) * 100, 100); + const includedPercentage = Math.min((included / limit) * 100, 100); + const remainingPercentage = Math.max(100 - includedPercentage, 0); + + return ( +
+
+ +
+

+ Managed agents consumption +

+ + + + +
+ + +

+ Managed agents are counted based on active agent connections during the billing period. + Each unique agent that connects to your deployment consumes one managed agent seat. +

+
    +
  • +
    + Current usage represents active managed agents during this period. +
  • +
  • +
    + Included allowance from your current license plan. +
  • +
  • +
    +
    +
    + Total limit including any additional purchased capacity. +
  • +
+
+ You might also check: +
    +
  • + + + Deployment overview + + +
  • +
  • + + More details on managed agents + +
  • +
+
+
+
+
+ +
+ {/* Date range */} +
+ {startDate ? dayjs(startDate).format("MMMM D, YYYY") : ""} + {endDate ? dayjs(endDate).format("MMMM D, YYYY") : ""} +
+ + {/* Progress bar container */} +
+ {/* Usage bar (green) */} +
+ + {/* Included allowance background (darker) */} +
+
+ + {/* Labels */} +
+
+ Usage: + {usage.toLocaleString()} +
+
+ Included: + {included.toLocaleString()} +
+
+ Limit: + {limit.toLocaleString()} +
+
+
+
+ ); +}; + +const styles = { + disabledTitle: { + fontSize: 16, + }, + + disabledRoot: (theme) => ({ + minHeight: 240, + display: "flex", + alignItems: "center", + justifyContent: "center", + borderRadius: 8, + border: `1px solid ${theme.palette.divider}`, + padding: 48, + }), + + disabledDescription: (theme) => ({ + color: theme.palette.text.secondary, + textAlign: "center", + maxWidth: 464, + marginTop: 8, + }), +} satisfies Record>; From 74ff0382cb5f9b8042d1772bab1313b8faf3193b Mon Sep 17 00:00:00 2001 From: Michael Suchacz <203725896+ibetitsmike@users.noreply.github.com> Date: Mon, 21 Jul 2025 12:28:42 +0000 Subject: [PATCH 02/12] layout adjustments for representing managed agents consumption --- .../ManagedAgentsConsumption.tsx | 47 +++++-------------- 1 file changed, 12 insertions(+), 35 deletions(-) diff --git a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx index ff76c029850df..0c1646c3ad81c 100644 --- a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx +++ b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx @@ -31,7 +31,7 @@ export const ManagedAgentsConsumption: FC = ({ endDate, enabled = true, }) => { - // If feature is disabled, show disabled state + if (!enabled) { return (
@@ -52,7 +52,6 @@ export const ManagedAgentsConsumption: FC = ({ ); } - // Calculate percentages for the progress bar const usagePercentage = Math.min((usage / limit) * 100, 100); const includedPercentage = Math.min((included / limit) * 100, 100); const remainingPercentage = Math.max(100 - includedPercentage, 0); @@ -88,8 +87,7 @@ export const ManagedAgentsConsumption: FC = ({ `} >

- Managed agents are counted based on active agent connections during the billing period. - Each unique agent that connects to your deployment consumes one managed agent seat. + Managed agents are counted based on the amount of started workspaces with an AI agent.

  • @@ -97,7 +95,7 @@ export const ManagedAgentsConsumption: FC = ({ className="rounded-[2px] bg-highlight-green size-3 inline-block" aria-label="Legend for current usage in the chart" /> - Current usage represents active managed agents during this period. + Amount of started workspaces with an AI agent.
  • = ({ >
    - Total limit including any additional purchased capacity. + Total limit after which the feature will be disabled.
-
- You might also check: -
    -
  • - - - Deployment overview - - -
  • -
  • - - More details on managed agents - -
  • -
-
- {/* Date range */}
{startDate ? dayjs(startDate).format("MMMM D, YYYY") : ""} {endDate ? dayjs(endDate).format("MMMM D, YYYY") : ""}
- {/* Progress bar container */}
- {/* Usage bar (green) */}
- {/* Included allowance background (darker) */}
= ({ />
- {/* Labels */} -
+
- Usage: + Actual: {usage.toLocaleString()}
-
+ +
Included: {included.toLocaleString()}
+
Limit: {limit.toLocaleString()} From 2e87ac282ececbf95d044d7bdded82f92d9d94a0 Mon Sep 17 00:00:00 2001 From: Michael Suchacz <203725896+ibetitsmike@users.noreply.github.com> Date: Mon, 21 Jul 2025 12:35:31 +0000 Subject: [PATCH 03/12] improve params to license settings page --- .../LicensesSettingsPage/LicensesSettingsPage.tsx | 2 +- .../LicensesSettingsPageView.tsx | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/LicensesSettingsPage.tsx b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/LicensesSettingsPage.tsx index 535a08b8228c9..2055067caed7a 100644 --- a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/LicensesSettingsPage.tsx +++ b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/LicensesSettingsPage.tsx @@ -85,7 +85,7 @@ const LicensesSettingsPage: FC = () => { isRemovingLicense={isRemovingLicense} removeLicense={(licenseId: number) => removeLicenseApi(licenseId)} activeUsers={userStatusCount?.active} - entitlements={entitlementsQuery.data} + managedAgentFeature={entitlementsQuery.data?.features.managed_agent_limit} refreshEntitlements={async () => { try { await refreshEntitlementsMutation.mutateAsync(); diff --git a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/LicensesSettingsPageView.tsx b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/LicensesSettingsPageView.tsx index 95655025f5a00..483fb92fc3143 100644 --- a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/LicensesSettingsPageView.tsx +++ b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/LicensesSettingsPageView.tsx @@ -4,7 +4,7 @@ import MuiLink from "@mui/material/Link"; import Skeleton from "@mui/material/Skeleton"; import Tooltip from "@mui/material/Tooltip"; import type { GetLicensesResponse } from "api/api"; -import type { Entitlements, UserStatusChangeCount } from "api/typesGenerated"; +import type { Entitlements, Feature, UserStatusChangeCount } from "api/typesGenerated"; import { Button } from "components/Button/Button"; import { SettingsHeader, @@ -33,7 +33,7 @@ type Props = { removeLicense: (licenseId: number) => void; refreshEntitlements: () => void; activeUsers: UserStatusChangeCount[] | undefined; - entitlements?: Entitlements; + managedAgentFeature?: Feature; }; const LicensesSettingsPageView: FC = ({ @@ -47,14 +47,13 @@ const LicensesSettingsPageView: FC = ({ removeLicense, refreshEntitlements, activeUsers, - entitlements, + managedAgentFeature, }) => { const theme = useTheme(); const { width, height } = useWindowSize(); - const managedAgentFeature = entitlements?.features?.managed_agent_limit; - const managedAgentLimitStarts = entitlements?.features?.managed_agent_limit?.usage_period?.start; - const managedAgentLimitExpires = entitlements?.features?.managed_agent_limit?.usage_period?.end; - const managedAgentFeatureEnabled = entitlements?.features?.managed_agent_limit?.enabled; + const managedAgentLimitStarts = managedAgentFeature?.usage_period?.start; + const managedAgentLimitExpires = managedAgentFeature?.usage_period?.end; + const managedAgentFeatureEnabled = managedAgentFeature?.enabled; return ( <> From bcb7faa8fb48a7b52e6f00d0e9a1a0befb1903c1 Mon Sep 17 00:00:00 2001 From: Michael Suchacz <203725896+ibetitsmike@users.noreply.github.com> Date: Mon, 21 Jul 2025 12:40:00 +0000 Subject: [PATCH 04/12] lint fixes --- site/package.json | 6 +- .../LicensesSettingsPage.tsx | 4 +- .../LicensesSettingsPageView.tsx | 2 +- .../ManagedAgentsConsumption.stories.tsx | 60 ++-- .../ManagedAgentsConsumption.tsx | 327 +++++++++--------- 5 files changed, 203 insertions(+), 196 deletions(-) diff --git a/site/package.json b/site/package.json index 8d688b45c928b..ca55bfde68cf9 100644 --- a/site/package.json +++ b/site/package.json @@ -191,7 +191,11 @@ "vite-plugin-checker": "0.9.3", "vite-plugin-turbosnap": "1.0.3" }, - "browserslist": ["chrome 110", "firefox 111", "safari 16.0"], + "browserslist": [ + "chrome 110", + "firefox 111", + "safari 16.0" + ], "resolutions": { "optionator": "0.9.3", "semver": "7.6.2" diff --git a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/LicensesSettingsPage.tsx b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/LicensesSettingsPage.tsx index 2055067caed7a..4cc6f52523edf 100644 --- a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/LicensesSettingsPage.tsx +++ b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/LicensesSettingsPage.tsx @@ -85,7 +85,9 @@ const LicensesSettingsPage: FC = () => { isRemovingLicense={isRemovingLicense} removeLicense={(licenseId: number) => removeLicenseApi(licenseId)} activeUsers={userStatusCount?.active} - managedAgentFeature={entitlementsQuery.data?.features.managed_agent_limit} + managedAgentFeature={ + entitlementsQuery.data?.features.managed_agent_limit + } refreshEntitlements={async () => { try { await refreshEntitlementsMutation.mutateAsync(); diff --git a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/LicensesSettingsPageView.tsx b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/LicensesSettingsPageView.tsx index 483fb92fc3143..2989a24397652 100644 --- a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/LicensesSettingsPageView.tsx +++ b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/LicensesSettingsPageView.tsx @@ -4,7 +4,7 @@ import MuiLink from "@mui/material/Link"; import Skeleton from "@mui/material/Skeleton"; import Tooltip from "@mui/material/Tooltip"; import type { GetLicensesResponse } from "api/api"; -import type { Entitlements, Feature, UserStatusChangeCount } from "api/typesGenerated"; +import type { Feature, UserStatusChangeCount } from "api/typesGenerated"; import { Button } from "components/Button/Button"; import { SettingsHeader, diff --git a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.stories.tsx b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.stories.tsx index fbe9713d03e5d..555e03a8e5b14 100644 --- a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.stories.tsx +++ b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.stories.tsx @@ -2,16 +2,16 @@ import type { Meta, StoryObj } from "@storybook/react"; import { ManagedAgentsConsumption } from "./ManagedAgentsConsumption"; const meta: Meta = { - title: - "pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption", - component: ManagedAgentsConsumption, - args: { - usage: 50000, - included: 60000, - limit: 120000, - startDate: "February 27, 2025", - endDate: "February 27, 2026", - }, + title: + "pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption", + component: ManagedAgentsConsumption, + args: { + usage: 50000, + included: 60000, + limit: 120000, + startDate: "February 27, 2025", + endDate: "February 27, 2026", + }, }; export default meta; @@ -20,33 +20,33 @@ type Story = StoryObj; export const Default: Story = {}; export const NearLimit: Story = { - args: { - usage: 115000, - included: 60000, - limit: 120000, - }, + args: { + usage: 115000, + included: 60000, + limit: 120000, + }, }; export const OverIncluded: Story = { - args: { - usage: 80000, - included: 60000, - limit: 120000, - }, + args: { + usage: 80000, + included: 60000, + limit: 120000, + }, }; export const LowUsage: Story = { - args: { - usage: 25000, - included: 60000, - limit: 120000, - }, + args: { + usage: 25000, + included: 60000, + limit: 120000, + }, }; export const Disabled: Story = { - args: { - usage: NaN, - included: NaN, - limit: NaN, - }, + args: { + usage: Number.NaN, + included: Number.NaN, + limit: Number.NaN, + }, }; diff --git a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx index 0c1646c3ad81c..de1346f9d6aab 100644 --- a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx +++ b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx @@ -1,187 +1,188 @@ +import type { Interpolation, Theme } from "@emotion/react"; +import MuiLink from "@mui/material/Link"; import { Button } from "components/Button/Button"; import { - Collapsible, - CollapsibleContent, - CollapsibleTrigger, + Collapsible, + CollapsibleContent, + CollapsibleTrigger, } from "components/Collapsible/Collapsible"; -import { Link } from "components/Link/Link"; import { Stack } from "components/Stack/Stack"; +import dayjs from "dayjs"; import { ChevronRightIcon } from "lucide-react"; import type { FC } from "react"; -import { Link as RouterLink } from "react-router-dom"; -import { docs } from "utils/docs"; -import MuiLink from "@mui/material/Link"; -import { type Interpolation, type Theme } from "@emotion/react"; -import dayjs from "dayjs"; interface ManagedAgentsConsumptionProps { - usage: number; - included: number; - limit: number; - startDate: string; - endDate: string; - enabled?: boolean; + usage: number; + included: number; + limit: number; + startDate: string; + endDate: string; + enabled?: boolean; } export const ManagedAgentsConsumption: FC = ({ - usage, - included, - limit, - startDate, - endDate, - enabled = true, + usage, + included, + limit, + startDate, + endDate, + enabled = true, }) => { - - if (!enabled) { - return ( -
- - - - Managed AI Agent Feature Disabled - - - The managed AI agent feature is not included in your current license. - Contact{" "} - sales to - upgrade your license and unlock this feature. - - - -
- ); - } - - const usagePercentage = Math.min((usage / limit) * 100, 100); - const includedPercentage = Math.min((included / limit) * 100, 100); - const remainingPercentage = Math.max(100 - includedPercentage, 0); - - return ( -
-
- -
-

- Managed agents consumption -

- - -
+ ); + } + + const usagePercentage = Math.min((usage / limit) * 100, 100); + const includedPercentage = Math.min((included / limit) * 100, 100); + const remainingPercentage = Math.max(100 - includedPercentage, 0); + + return ( +
+
+ +
+

+ Managed agents consumption +

+ + + - -
- - + + How we calculate managed agent consumption + + + + + -

- Managed agents are counted based on the amount of started workspaces with an AI agent. -

-
    -
  • -
    - Amount of started workspaces with an AI agent. -
  • -
  • -
    - Included allowance from your current license plan. -
  • -
  • -
    -
    -
    - Total limit after which the feature will be disabled. -
  • -
-
-
-
- -
-
- {startDate ? dayjs(startDate).format("MMMM D, YYYY") : ""} - {endDate ? dayjs(endDate).format("MMMM D, YYYY") : ""} -
- -
-
- -
-
- -
-
- Actual: - {usage.toLocaleString()} -
- -
- Included: - {included.toLocaleString()} -
- -
- Limit: - {limit.toLocaleString()} -
-
-
-
- ); + > +

+ Managed agents are counted based on the amount of started + workspaces with an AI agent. +

+
    +
  • +
    + Amount of started workspaces with an AI agent. +
  • +
  • +
    + Included allowance from your current license plan. +
  • +
  • +
    +
    +
    + Total limit after which the feature will be disabled. +
  • +
+ + +
+ +
+
+ + {startDate ? dayjs(startDate).format("MMMM D, YYYY") : ""} + + {endDate ? dayjs(endDate).format("MMMM D, YYYY") : ""} +
+ +
+
+ +
+
+ +
+
+ Actual: + {usage.toLocaleString()} +
+ +
+ Included: + {included.toLocaleString()} +
+ +
+ Limit: + {limit.toLocaleString()} +
+
+
+ + ); }; const styles = { - disabledTitle: { - fontSize: 16, - }, - - disabledRoot: (theme) => ({ - minHeight: 240, - display: "flex", - alignItems: "center", - justifyContent: "center", - borderRadius: 8, - border: `1px solid ${theme.palette.divider}`, - padding: 48, - }), - - disabledDescription: (theme) => ({ - color: theme.palette.text.secondary, - textAlign: "center", - maxWidth: 464, - marginTop: 8, - }), + disabledTitle: { + fontSize: 16, + }, + + disabledRoot: (theme) => ({ + minHeight: 240, + display: "flex", + alignItems: "center", + justifyContent: "center", + borderRadius: 8, + border: `1px solid ${theme.palette.divider}`, + padding: 48, + }), + + disabledDescription: (theme) => ({ + color: theme.palette.text.secondary, + textAlign: "center", + maxWidth: 464, + marginTop: 8, + }), } satisfies Record>; From 9d58c44c74da48e0068fd9a1ffeb3ccb478c67dc Mon Sep 17 00:00:00 2001 From: Michael Suchacz <203725896+ibetitsmike@users.noreply.github.com> Date: Tue, 22 Jul 2025 13:54:03 +0000 Subject: [PATCH 05/12] layout fixes on small screen and PR review --- .../ManagedAgentsConsumption.stories.tsx | 9 +++++ .../ManagedAgentsConsumption.tsx | 33 ++++++++++++++----- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.stories.tsx b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.stories.tsx index 555e03a8e5b14..2621bfc48a6b6 100644 --- a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.stories.tsx +++ b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.stories.tsx @@ -43,8 +43,17 @@ export const LowUsage: Story = { }, }; +export const IncludedAtLimit: Story = { + args: { + usage: 25000, + included: 30500, + limit: 30500, + }, +}; + export const Disabled: Story = { args: { + enabled: false, usage: Number.NaN, included: Number.NaN, limit: Number.NaN, diff --git a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx index de1346f9d6aab..e0bb6c5873b9a 100644 --- a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx +++ b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx @@ -34,11 +34,11 @@ export const ManagedAgentsConsumption: FC = ({ - Managed AI Agent Feature Disabled + Managed AI Agents Disabled - The managed AI agent feature is not included in your current - license. Contact{" "} + Managed AI agents are not included in your current license. + Contact{" "} sales to upgrade your license and unlock this feature. @@ -70,7 +70,7 @@ export const ManagedAgentsConsumption: FC = ({ `} > - How we calculate managed agent consumption + How we calculate managed agents consumption @@ -83,8 +83,8 @@ export const ManagedAgentsConsumption: FC = ({ `} >

- Managed agents are counted based on the amount of started - workspaces with an AI agent. + Managed agents are counted based on the amount of successfully + started workspaces with an AI agent.

  • @@ -108,7 +108,7 @@ export const ManagedAgentsConsumption: FC = ({ >
    - Total limit after which the feature will be disabled. + Total limit after which further AI workspace builds will be blocked.
@@ -138,7 +138,7 @@ export const ManagedAgentsConsumption: FC = ({ />
-
+
Actual: {usage.toLocaleString()} @@ -159,6 +159,23 @@ export const ManagedAgentsConsumption: FC = ({ {limit.toLocaleString()}
+ +
+
+
+ Actual: + {usage.toLocaleString()} +
+
+ Included: + {included.toLocaleString()} +
+
+ Limit: + {limit.toLocaleString()} +
+
+
); From 721561b2d506493c43cb812996b6a23445d90a06 Mon Sep 17 00:00:00 2001 From: Michael Suchacz <203725896+ibetitsmike@users.noreply.github.com> Date: Mon, 28 Jul 2025 10:10:33 +0000 Subject: [PATCH 06/12] - changed ManagedAgentsConsumption component to only have a managedAgentFeature param - added managedAgentFeature validation and stories for various failed states --- .../LicensesSettingsPageView.tsx | 14 +- .../ManagedAgentsConsumption.stories.tsx | 177 +++++++++++++++--- .../ManagedAgentsConsumption.tsx | 76 ++++++-- 3 files changed, 221 insertions(+), 46 deletions(-) diff --git a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/LicensesSettingsPageView.tsx b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/LicensesSettingsPageView.tsx index 2989a24397652..c631ed178b9a3 100644 --- a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/LicensesSettingsPageView.tsx +++ b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/LicensesSettingsPageView.tsx @@ -51,9 +51,6 @@ const LicensesSettingsPageView: FC = ({ }) => { const theme = useTheme(); const { width, height } = useWindowSize(); - const managedAgentLimitStarts = managedAgentFeature?.usage_period?.start; - const managedAgentLimitExpires = managedAgentFeature?.usage_period?.end; - const managedAgentFeatureEnabled = managedAgentFeature?.enabled; return ( <> @@ -158,15 +155,8 @@ const LicensesSettingsPageView: FC = ({ /> )} - {licenses && licenses.length > 0 && managedAgentFeature && ( - + {licenses && licenses.length > 0 && ( + )}
diff --git a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.stories.tsx b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.stories.tsx index 2621bfc48a6b6..8b526914edd50 100644 --- a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.stories.tsx +++ b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.stories.tsx @@ -6,11 +6,18 @@ const meta: Meta = { "pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption", component: ManagedAgentsConsumption, args: { - usage: 50000, - included: 60000, - limit: 120000, - startDate: "February 27, 2025", - endDate: "February 27, 2026", + managedAgentFeature: { + enabled: true, + actual: 50000, + soft_limit: 60000, + limit: 120000, + usage_period: { + start: "February 27, 2025", + end: "February 27, 2026", + issued_at: "February 27, 2025", + }, + entitlement: "entitled", + }, }, }; @@ -21,41 +28,169 @@ export const Default: Story = {}; export const NearLimit: Story = { args: { - usage: 115000, - included: 60000, - limit: 120000, + managedAgentFeature: { + enabled: true, + actual: 115000, + soft_limit: 60000, + limit: 120000, + usage_period: { + start: "February 27, 2025", + end: "February 27, 2026", + issued_at: "February 27, 2025", + }, + entitlement: "entitled", + }, }, }; export const OverIncluded: Story = { args: { - usage: 80000, - included: 60000, - limit: 120000, + managedAgentFeature: { + enabled: true, + actual: 80000, + soft_limit: 60000, + limit: 120000, + usage_period: { + start: "February 27, 2025", + end: "February 27, 2026", + issued_at: "February 27, 2025", + }, + entitlement: "entitled", + }, }, }; export const LowUsage: Story = { args: { - usage: 25000, - included: 60000, - limit: 120000, + managedAgentFeature: { + enabled: true, + actual: 25000, + soft_limit: 60000, + limit: 120000, + usage_period: { + start: "February 27, 2025", + end: "February 27, 2026", + issued_at: "February 27, 2025", + }, + entitlement: "entitled", + }, }, }; export const IncludedAtLimit: Story = { args: { - usage: 25000, - included: 30500, - limit: 30500, + managedAgentFeature: { + enabled: true, + actual: 25000, + soft_limit: 30500, + limit: 30500, + usage_period: { + start: "February 27, 2025", + end: "February 27, 2026", + issued_at: "February 27, 2025", + }, + entitlement: "entitled", + }, }, }; export const Disabled: Story = { args: { - enabled: false, - usage: Number.NaN, - included: Number.NaN, - limit: Number.NaN, + managedAgentFeature: { + enabled: false, + actual: undefined, + soft_limit: undefined, + limit: undefined, + usage_period: undefined, + entitlement: "not_entitled", + }, + }, +}; + +export const NoFeature: Story = { + args: { + managedAgentFeature: undefined, + }, +}; + +// Error States for Validation +export const ErrorMissingData: Story = { + args: { + managedAgentFeature: { + enabled: true, + actual: undefined, + soft_limit: undefined, + limit: undefined, + usage_period: undefined, + entitlement: "entitled", + }, + }, +}; + +export const ErrorNegativeValues: Story = { + args: { + managedAgentFeature: { + enabled: true, + actual: -100, + soft_limit: 60000, + limit: 120000, + usage_period: { + start: "February 27, 2025", + end: "February 27, 2026", + issued_at: "February 27, 2025", + }, + entitlement: "entitled", + }, + }, +}; + +export const ErrorSoftLimitExceedsLimit: Story = { + args: { + managedAgentFeature: { + enabled: true, + actual: 50000, + soft_limit: 150000, + limit: 120000, + usage_period: { + start: "February 27, 2025", + end: "February 27, 2026", + issued_at: "February 27, 2025", + }, + entitlement: "entitled", + }, + }, +}; + +export const ErrorInvalidDates: Story = { + args: { + managedAgentFeature: { + enabled: true, + actual: 50000, + soft_limit: 60000, + limit: 120000, + usage_period: { + start: "invalid-date", + end: "February 27, 2026", + issued_at: "February 27, 2025", + }, + entitlement: "entitled", + }, + }, +}; + +export const ErrorEndBeforeStart: Story = { + args: { + managedAgentFeature: { + enabled: true, + actual: 50000, + soft_limit: 60000, + limit: 120000, + usage_period: { + start: "February 27, 2026", + end: "February 27, 2025", + issued_at: "February 27, 2025", + }, + entitlement: "entitled", + }, }, }; diff --git a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx index e0bb6c5873b9a..033d4827c0565 100644 --- a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx +++ b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx @@ -1,5 +1,7 @@ import type { Interpolation, Theme } from "@emotion/react"; import MuiLink from "@mui/material/Link"; +import type { Feature } from "api/typesGenerated"; +import { ErrorAlert } from "components/Alert/ErrorAlert"; import { Button } from "components/Button/Button"; import { Collapsible, @@ -12,23 +14,65 @@ import { ChevronRightIcon } from "lucide-react"; import type { FC } from "react"; interface ManagedAgentsConsumptionProps { - usage: number; - included: number; - limit: number; - startDate: string; - endDate: string; - enabled?: boolean; + managedAgentFeature?: Feature; } +const validateFeature = (feature?: Feature): string | null => { + if (!feature) { + return null; // No feature is valid (will show disabled state) + } + + // If enabled, we need valid numeric data + if (feature.enabled) { + if ( + feature.actual === undefined || + feature.soft_limit === undefined || + feature.limit === undefined + ) { + return "Managed agent feature is enabled but missing required usage data (actual, soft_limit, or limit)."; + } + + if ( + feature.actual < 0 || + feature.soft_limit < 0 || + feature.limit < 0 + ) { + return "Managed agent feature contains invalid negative values for usage metrics."; + } + + if (feature.soft_limit > feature.limit) { + return "Managed agent feature has invalid configuration: soft limit exceeds total limit."; + } + + // Validate usage period if present + if (feature.usage_period) { + const start = dayjs(feature.usage_period.start); + const end = dayjs(feature.usage_period.end); + + if (!start.isValid() || !end.isValid()) { + return "Managed agent feature has invalid usage period dates."; + } + + if (end.isBefore(start)) { + return "Managed agent feature has invalid usage period: end date is before start date."; + } + } + } + + return null; // Valid +}; + export const ManagedAgentsConsumption: FC = ({ - usage, - included, - limit, - startDate, - endDate, - enabled = true, + managedAgentFeature, }) => { - if (!enabled) { + // Validate the feature data + const validationError = validateFeature(managedAgentFeature); + if (validationError) { + return ; + } + + // If no feature is provided or it's disabled, show disabled state + if (!managedAgentFeature?.enabled) { return (
@@ -48,6 +92,12 @@ export const ManagedAgentsConsumption: FC = ({ ); } + const usage = managedAgentFeature.actual || 0; + const included = managedAgentFeature.soft_limit || 0; + const limit = managedAgentFeature.limit || 0; + const startDate = managedAgentFeature.usage_period?.start || ""; + const endDate = managedAgentFeature.usage_period?.end || ""; + const usagePercentage = Math.min((usage / limit) * 100, 100); const includedPercentage = Math.min((included / limit) * 100, 100); const remainingPercentage = Math.max(100 - includedPercentage, 0); From 873a1a33f0cc50a8dcba6fcee20d8af517c1c856 Mon Sep 17 00:00:00 2001 From: Michael Suchacz <203725896+ibetitsmike@users.noreply.github.com> Date: Mon, 28 Jul 2025 10:41:49 +0000 Subject: [PATCH 07/12] removed Emotion styles and added different colouring based on the usage percentage --- .../ManagedAgentsConsumption.stories.tsx | 65 ++++++++++++++++++- .../ManagedAgentsConsumption.tsx | 48 ++++++-------- 2 files changed, 81 insertions(+), 32 deletions(-) diff --git a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.stories.tsx b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.stories.tsx index 8b526914edd50..8b5839d66ea7a 100644 --- a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.stories.tsx +++ b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.stories.tsx @@ -24,13 +24,70 @@ const meta: Meta = { export default meta; type Story = StoryObj; -export const Default: Story = {}; +export const Default: Story = { + name: "Normal Usage (42% of limit)", +}; + +export const Warning: Story = { + name: "Warning (80-99% of limit)", + args: { + managedAgentFeature: { + enabled: true, + actual: 96000, // 80% of limit - should show orange + soft_limit: 60000, + limit: 120000, + usage_period: { + start: "February 27, 2025", + end: "February 27, 2026", + issued_at: "February 27, 2025", + }, + entitlement: "entitled", + }, + }, +}; export const NearLimit: Story = { + name: "Near Limit (95% of limit)", + args: { + managedAgentFeature: { + enabled: true, + actual: 114000, // 95% of limit - should show orange + soft_limit: 60000, + limit: 120000, + usage_period: { + start: "February 27, 2025", + end: "February 27, 2026", + issued_at: "February 27, 2025", + }, + entitlement: "entitled", + }, + }, +}; + +export const AtLimit: Story = { + name: "At Limit (100% of limit)", + args: { + managedAgentFeature: { + enabled: true, + actual: 120000, // 100% of limit - should show red + soft_limit: 60000, + limit: 120000, + usage_period: { + start: "February 27, 2025", + end: "February 27, 2026", + issued_at: "February 27, 2025", + }, + entitlement: "entitled", + }, + }, +}; + +export const OverLimit: Story = { + name: "Over Limit (120% of limit)", args: { managedAgentFeature: { enabled: true, - actual: 115000, + actual: 144000, // 120% of limit - should show red soft_limit: 60000, limit: 120000, usage_period: { @@ -44,10 +101,11 @@ export const NearLimit: Story = { }; export const OverIncluded: Story = { + name: "Over Included (67% of limit)", args: { managedAgentFeature: { enabled: true, - actual: 80000, + actual: 80000, // Over included but under 80% of total limit - should still be green soft_limit: 60000, limit: 120000, usage_period: { @@ -61,6 +119,7 @@ export const OverIncluded: Story = { }; export const LowUsage: Story = { + name: "Low Usage (21% of limit)", args: { managedAgentFeature: { enabled: true, diff --git a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx index 033d4827c0565..5e9032e8ca80f 100644 --- a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx +++ b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx @@ -1,4 +1,3 @@ -import type { Interpolation, Theme } from "@emotion/react"; import MuiLink from "@mui/material/Link"; import type { Feature } from "api/typesGenerated"; import { ErrorAlert } from "components/Alert/ErrorAlert"; @@ -74,13 +73,13 @@ export const ManagedAgentsConsumption: FC = ({ // If no feature is provided or it's disabled, show disabled state if (!managedAgentFeature?.enabled) { return ( -
+
- + Managed AI Agents Disabled - + Managed AI agents are not included in your current license. Contact{" "} sales to upgrade @@ -102,6 +101,20 @@ export const ManagedAgentsConsumption: FC = ({ const includedPercentage = Math.min((included / limit) * 100, 100); const remainingPercentage = Math.max(100 - includedPercentage, 0); + // Determine usage bar color based on percentage + const getUsageColor = () => { + const actualUsagePercent = (usage / limit) * 100; + if (actualUsagePercent >= 100) { + return "bg-highlight-red"; // Critical: at or over limit + } + if (actualUsagePercent >= 80) { + return "bg-surface-orange"; // Warning: approaching limit + } + return "bg-highlight-green"; // Normal: safe usage + }; + + const usageBarColor = getUsageColor(); + return (
@@ -139,7 +152,7 @@ export const ManagedAgentsConsumption: FC = ({
  • Amount of started workspaces with an AI agent. @@ -175,7 +188,7 @@ export const ManagedAgentsConsumption: FC = ({
    @@ -230,26 +243,3 @@ export const ManagedAgentsConsumption: FC = ({
); }; - -const styles = { - disabledTitle: { - fontSize: 16, - }, - - disabledRoot: (theme) => ({ - minHeight: 240, - display: "flex", - alignItems: "center", - justifyContent: "center", - borderRadius: 8, - border: `1px solid ${theme.palette.divider}`, - padding: 48, - }), - - disabledDescription: (theme) => ({ - color: theme.palette.text.secondary, - textAlign: "center", - maxWidth: 464, - marginTop: 8, - }), -} satisfies Record>; From c893257ed8faada08b1db1500485820d6df1d6ab Mon Sep 17 00:00:00 2001 From: Michael Suchacz <203725896+ibetitsmike@users.noreply.github.com> Date: Mon, 28 Jul 2025 10:42:54 +0000 Subject: [PATCH 08/12] fmt fixes --- site/package.json | 6 +----- .../ManagedAgentsConsumption.tsx | 18 ++++++------------ 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/site/package.json b/site/package.json index ca55bfde68cf9..8d688b45c928b 100644 --- a/site/package.json +++ b/site/package.json @@ -191,11 +191,7 @@ "vite-plugin-checker": "0.9.3", "vite-plugin-turbosnap": "1.0.3" }, - "browserslist": [ - "chrome 110", - "firefox 111", - "safari 16.0" - ], + "browserslist": ["chrome 110", "firefox 111", "safari 16.0"], "resolutions": { "optionator": "0.9.3", "semver": "7.6.2" diff --git a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx index 5e9032e8ca80f..8150adaf5c2f8 100644 --- a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx +++ b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx @@ -31,11 +31,7 @@ const validateFeature = (feature?: Feature): string | null => { return "Managed agent feature is enabled but missing required usage data (actual, soft_limit, or limit)."; } - if ( - feature.actual < 0 || - feature.soft_limit < 0 || - feature.limit < 0 - ) { + if (feature.actual < 0 || feature.soft_limit < 0 || feature.limit < 0) { return "Managed agent feature contains invalid negative values for usage metrics."; } @@ -76,14 +72,11 @@ export const ManagedAgentsConsumption: FC = ({
- - Managed AI Agents Disabled - + Managed AI Agents Disabled Managed AI agents are not included in your current license. - Contact{" "} - sales to upgrade - your license and unlock this feature. + Contact sales to + upgrade your license and unlock this feature. @@ -171,7 +164,8 @@ export const ManagedAgentsConsumption: FC = ({ >
- Total limit after which further AI workspace builds will be blocked. + Total limit after which further AI workspace builds will be + blocked. From ba22be6486282b57eeb72e9b8fea5aeec977e4c5 Mon Sep 17 00:00:00 2001 From: Michael Suchacz <203725896+ibetitsmike@users.noreply.github.com> Date: Mon, 28 Jul 2025 11:41:15 +0000 Subject: [PATCH 09/12] reverted the orange/red based on usage --- .../ManagedAgentsConsumption.stories.tsx | 65 +------------------ .../ManagedAgentsConsumption.tsx | 18 +---- 2 files changed, 5 insertions(+), 78 deletions(-) diff --git a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.stories.tsx b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.stories.tsx index 8b5839d66ea7a..8b526914edd50 100644 --- a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.stories.tsx +++ b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.stories.tsx @@ -24,70 +24,13 @@ const meta: Meta = { export default meta; type Story = StoryObj; -export const Default: Story = { - name: "Normal Usage (42% of limit)", -}; - -export const Warning: Story = { - name: "Warning (80-99% of limit)", - args: { - managedAgentFeature: { - enabled: true, - actual: 96000, // 80% of limit - should show orange - soft_limit: 60000, - limit: 120000, - usage_period: { - start: "February 27, 2025", - end: "February 27, 2026", - issued_at: "February 27, 2025", - }, - entitlement: "entitled", - }, - }, -}; +export const Default: Story = {}; export const NearLimit: Story = { - name: "Near Limit (95% of limit)", - args: { - managedAgentFeature: { - enabled: true, - actual: 114000, // 95% of limit - should show orange - soft_limit: 60000, - limit: 120000, - usage_period: { - start: "February 27, 2025", - end: "February 27, 2026", - issued_at: "February 27, 2025", - }, - entitlement: "entitled", - }, - }, -}; - -export const AtLimit: Story = { - name: "At Limit (100% of limit)", - args: { - managedAgentFeature: { - enabled: true, - actual: 120000, // 100% of limit - should show red - soft_limit: 60000, - limit: 120000, - usage_period: { - start: "February 27, 2025", - end: "February 27, 2026", - issued_at: "February 27, 2025", - }, - entitlement: "entitled", - }, - }, -}; - -export const OverLimit: Story = { - name: "Over Limit (120% of limit)", args: { managedAgentFeature: { enabled: true, - actual: 144000, // 120% of limit - should show red + actual: 115000, soft_limit: 60000, limit: 120000, usage_period: { @@ -101,11 +44,10 @@ export const OverLimit: Story = { }; export const OverIncluded: Story = { - name: "Over Included (67% of limit)", args: { managedAgentFeature: { enabled: true, - actual: 80000, // Over included but under 80% of total limit - should still be green + actual: 80000, soft_limit: 60000, limit: 120000, usage_period: { @@ -119,7 +61,6 @@ export const OverIncluded: Story = { }; export const LowUsage: Story = { - name: "Low Usage (21% of limit)", args: { managedAgentFeature: { enabled: true, diff --git a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx index 8150adaf5c2f8..c2f948f8dee75 100644 --- a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx +++ b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx @@ -94,20 +94,6 @@ export const ManagedAgentsConsumption: FC = ({ const includedPercentage = Math.min((included / limit) * 100, 100); const remainingPercentage = Math.max(100 - includedPercentage, 0); - // Determine usage bar color based on percentage - const getUsageColor = () => { - const actualUsagePercent = (usage / limit) * 100; - if (actualUsagePercent >= 100) { - return "bg-highlight-red"; // Critical: at or over limit - } - if (actualUsagePercent >= 80) { - return "bg-surface-orange"; // Warning: approaching limit - } - return "bg-highlight-green"; // Normal: safe usage - }; - - const usageBarColor = getUsageColor(); - return (
@@ -145,7 +131,7 @@ export const ManagedAgentsConsumption: FC = ({
  • Amount of started workspaces with an AI agent. @@ -182,7 +168,7 @@ export const ManagedAgentsConsumption: FC = ({
    From f33f393e3196fa097eb54784001962c77fd19d5b Mon Sep 17 00:00:00 2001 From: Michael Suchacz <203725896+ibetitsmike@users.noreply.github.com> Date: Mon, 28 Jul 2025 12:16:40 +0000 Subject: [PATCH 10/12] reworded docs --- .../ManagedAgentsConsumption.tsx | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx index c2f948f8dee75..24e6684ece19c 100644 --- a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx +++ b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx @@ -9,8 +9,9 @@ import { } from "components/Collapsible/Collapsible"; import { Stack } from "components/Stack/Stack"; import dayjs from "dayjs"; -import { ChevronRightIcon } from "lucide-react"; +import { ChevronRightIcon, Link } from "lucide-react"; import type { FC } from "react"; +import { docs } from "utils/docs"; interface ManagedAgentsConsumptionProps { managedAgentFeature?: Feature; @@ -100,7 +101,7 @@ export const ManagedAgentsConsumption: FC = ({

    - Managed agents consumption + Managed AI Agents Usage

    @@ -112,7 +113,7 @@ export const ManagedAgentsConsumption: FC = ({ `} > - How we calculate managed agents consumption + Learn more
    @@ -125,8 +126,13 @@ export const ManagedAgentsConsumption: FC = ({ `} >

    - Managed agents are counted based on the amount of successfully - started workspaces with an AI agent. + + Coder Tasks + {" "} and upcoming managed AI features are included in Coder Premium + licenses during beta. Usage limits and pricing subject to change.

    • From d65392b1850062ae40ef81f986df4edad7cc7692 Mon Sep 17 00:00:00 2001 From: Michael Suchacz <203725896+ibetitsmike@users.noreply.github.com> Date: Mon, 28 Jul 2025 16:32:43 +0000 Subject: [PATCH 11/12] fmt lint --- .../ManagedAgentsConsumption.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx index 24e6684ece19c..033af8cf93fc5 100644 --- a/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx +++ b/site/src/pages/DeploymentSettingsPage/LicensesSettingsPage/ManagedAgentsConsumption.tsx @@ -9,7 +9,7 @@ import { } from "components/Collapsible/Collapsible"; import { Stack } from "components/Stack/Stack"; import dayjs from "dayjs"; -import { ChevronRightIcon, Link } from "lucide-react"; +import { ChevronRightIcon } from "lucide-react"; import type { FC } from "react"; import { docs } from "utils/docs"; @@ -100,9 +100,7 @@ export const ManagedAgentsConsumption: FC = ({
      -

      - Managed AI Agents Usage -

      +

      Managed AI Agents Usage

      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/18934.patch

      Alternative Proxies:

      Alternative Proxy

      pFad Proxy

      pFad v3 Proxy

      pFad v4 Proxy