Skip to content

feat: add idle app status #18415

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cli/exp_mcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -585,10 +585,10 @@ func (s *mcpServer) startWatcher(ctx context.Context, inv *serpent.Invocation) {
case event := <-eventsCh:
switch ev := event.(type) {
case agentapi.EventStatusChange:
// If the screen is stable, assume complete.
// If the screen is stable, report idle.
state := codersdk.WorkspaceAppStatusStateWorking
if ev.Status == agentapi.StatusStable {
state = codersdk.WorkspaceAppStatusStateComplete
state = codersdk.WorkspaceAppStatusStateIdle
}
err := s.queue.Push(taskReport{
state: state,
Expand Down
4 changes: 2 additions & 2 deletions cli/exp_mcp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -900,7 +900,7 @@ func TestExpMcpReporter(t *testing.T) {
{
event: makeStatusEvent(agentapi.StatusStable),
expected: &codersdk.WorkspaceAppStatus{
State: codersdk.WorkspaceAppStatusStateComplete,
State: codersdk.WorkspaceAppStatusStateIdle,
Message: "doing work",
URI: "https://dev.coder.com",
},
Expand Down Expand Up @@ -948,7 +948,7 @@ func TestExpMcpReporter(t *testing.T) {
{
event: makeStatusEvent(agentapi.StatusStable),
expected: &codersdk.WorkspaceAppStatus{
State: codersdk.WorkspaceAppStatusStateComplete,
State: codersdk.WorkspaceAppStatusStateIdle,
Message: "oops",
URI: "",
},
Expand Down
2 changes: 2 additions & 0 deletions coderd/apidoc/docs.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion coderd/apidoc/swagger.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion coderd/database/dump.sql

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-- It is not possible to delete enum values.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that's true. These steps should revert the enum to its original set of values:

  1. Replace any occurences of new enum values with different values
  2. Rename the enum to something else
  3. Re-create the original enum
  4. Update columns to use the new enum
  5. Drop the renamed enum

Here are the SQL statements you'd use: https://blink.so/chat/Revert-Enum-Value-in-Postgres-5vVDbfY5A7ZOLPxyuqVgsG

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TYPE workspace_app_status_state ADD VALUE IF NOT EXISTS 'idle';
5 changes: 4 additions & 1 deletion coderd/database/models.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion coderd/workspaceagents.go
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,10 @@ func (api *API) patchWorkspaceAgentAppStatus(rw http.ResponseWriter, r *http.Req
}

switch req.State {
case codersdk.WorkspaceAppStatusStateComplete, codersdk.WorkspaceAppStatusStateFailure, codersdk.WorkspaceAppStatusStateWorking: // valid states
case codersdk.WorkspaceAppStatusStateComplete,
codersdk.WorkspaceAppStatusStateFailure,
codersdk.WorkspaceAppStatusStateWorking,
codersdk.WorkspaceAppStatusStateIdle: // valid states
default:
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
Message: "Invalid state provided.",
Expand Down
6 changes: 3 additions & 3 deletions codersdk/toolsdk/toolsdk.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ Bad Tasks
Use the "state" field to indicate your progress. Periodically report
progress with state "working" to keep the user updated. It is not possible to send too many updates!

ONLY report a "complete" or "failure" state if you have FULLY completed the task.
ONLY report an "idle" or "failure" state if you have FULLY completed the task.
`,
Schema: aisdk.Schema{
Properties: map[string]any{
Expand All @@ -205,10 +205,10 @@ ONLY report a "complete" or "failure" state if you have FULLY completed the task
},
"state": map[string]any{
"type": "string",
"description": "The state of your task. This can be one of the following: working, complete, or failure. Select the state that best represents your current progress.",
"description": "The state of your task. This can be one of the following: working, idle, or failure. Select the state that best represents your current progress.",
"enum": []string{
string(codersdk.WorkspaceAppStatusStateWorking),
string(codersdk.WorkspaceAppStatusStateComplete),
string(codersdk.WorkspaceAppStatusStateIdle),
string(codersdk.WorkspaceAppStatusStateFailure),
},
},
Expand Down
1 change: 1 addition & 0 deletions codersdk/workspaceapps.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type WorkspaceAppStatusState string

const (
WorkspaceAppStatusStateWorking WorkspaceAppStatusState = "working"
WorkspaceAppStatusStateIdle WorkspaceAppStatusState = "idle"
WorkspaceAppStatusStateComplete WorkspaceAppStatusState = "complete"
WorkspaceAppStatusStateFailure WorkspaceAppStatusState = "failure"
)
Expand Down
2 changes: 2 additions & 0 deletions docs/reference/api/builds.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions docs/reference/api/schemas.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions docs/reference/api/templates.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion site/src/api/typesGenerated.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions site/src/modules/apps/AppStatusStateIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
CircleAlertIcon,
CircleCheckIcon,
HourglassIcon,
SquareIcon,
TriangleAlertIcon,
} from "lucide-react";
import type { FC } from "react";
Expand All @@ -26,6 +27,10 @@ export const AppStatusStateIcon: FC<AppStatusStateIconProps> = ({
const className = cn(["size-4 shrink-0", customClassName]);

switch (state) {
case "idle":
return (
<SquareIcon className={cn(["text-content-secondary", className])} />
);
case "complete":
return (
<CircleCheckIcon className={cn(["text-content-success", className])} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,26 @@ export const Working: Story = {
},
};

export const Idle: Story = {
args: {
status: {
...MockWorkspaceAppStatus,
state: "idle",
message: "Done for now",
},
},
};

export const NoMessage: Story = {
args: {
status: {
...MockWorkspaceAppStatus,
state: "idle",
message: "",
},
},
};

export const LongMessage: Story = {
args: {
status: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
TooltipProvider,
TooltipTrigger,
} from "components/Tooltip/Tooltip";
import capitalize from "lodash/capitalize";
import { AppStatusStateIcon } from "modules/apps/AppStatusStateIcon";
import { cn } from "utils/cn";

Expand All @@ -25,6 +26,7 @@ export const WorkspaceAppStatus = ({
);
}

const message = status.message || capitalize(status.state);
return (
<div className="flex flex-col text-content-secondary">
<TooltipProvider>
Expand All @@ -40,11 +42,11 @@ export const WorkspaceAppStatus = ({
})}
/>
<span className="whitespace-nowrap max-w-72 overflow-hidden text-ellipsis text-sm text-content-primary font-medium">
{status.message}
{message}
</span>
</div>
</TooltipTrigger>
<TooltipContent>{status.message}</TooltipContent>
<TooltipContent>{message}</TooltipContent>
</Tooltip>
</TooltipProvider>
<span className="text-xs first-letter:uppercase block pl-6">
Expand Down
34 changes: 34 additions & 0 deletions site/src/pages/WorkspacePage/AppStatuses.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,40 @@ export const WorkingState: Story = {
},
};

export const IdleState: Story = {
args: {
agent: mockAgent([
{
...MockWorkspaceAppStatus,
id: "status-8",
icon: "",
message: "Done for now",
created_at: createTimestamp(5, 20),
uri: "",
state: "idle" as const,
},
...MockWorkspaceAppStatuses,
]),
},
};

export const NoMessage: Story = {
args: {
agent: mockAgent([
{
...MockWorkspaceAppStatus,
id: "status-8",
icon: "",
message: "",
created_at: createTimestamp(5, 20),
uri: "",
state: "idle" as const,
},
...MockWorkspaceAppStatuses,
]),
},
};

export const LongStatusText: Story = {
args: {
agent: mockAgent([
Expand Down
5 changes: 3 additions & 2 deletions site/src/pages/WorkspacePage/AppStatuses.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
TooltipProvider,
TooltipTrigger,
} from "components/Tooltip/Tooltip";
import capitalize from "lodash/capitalize";
import { timeFrom } from "utils/time";

import {
Expand Down Expand Up @@ -77,7 +78,7 @@ export const AppStatuses: FC<AppStatusesProps> = ({
<div className="text-sm font-medium text-content-primary flex items-center gap-2 ">
<AppStatusStateIcon state={latestStatus.state} latest />
<span className="block flex-1 whitespace-nowrap overflow-hidden text-ellipsis">
{latestStatus.message}
{latestStatus.message || capitalize(latestStatus.state)}
</span>
</div>
<span className="text-xs text-content-secondary first-letter:uppercase block pl-[26px]">
Expand Down Expand Up @@ -160,7 +161,7 @@ export const AppStatuses: FC<AppStatusesProps> = ({
latest={false}
className="size-icon-xs w-[18px]"
/>
{status.message}
{status.message || capitalize(status.state)}
</span>
<span className="text-2xs text-content-secondary first-letter:uppercase block pl-[26px]">
{formattedTimestamp}
Expand Down
Loading