mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: add app status tracking to the backend (#17163)
This does ~95% of the backend work required to integrate the AI work. Most left to integrate from the tasks branch is just frontend, which will be a lot smaller I believe. The real difference between this branch and that one is the abstraction -- this now attaches statuses to apps, and returns the latest status reported as part of a workspace. This change enables us to have a similar UX to in the tasks branch, but for agents other than Claude Code as well. Any app can report status now.
This commit is contained in:
@@ -581,6 +581,28 @@ func (c *Client) PatchLogs(ctx context.Context, req PatchLogs) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// PatchAppStatus updates the status of a workspace app.
|
||||
type PatchAppStatus struct {
|
||||
AppSlug string `json:"app_slug"`
|
||||
NeedsUserAttention bool `json:"needs_user_attention"`
|
||||
State codersdk.WorkspaceAppStatusState `json:"state"`
|
||||
Message string `json:"message"`
|
||||
URI string `json:"uri"`
|
||||
Icon string `json:"icon"`
|
||||
}
|
||||
|
||||
func (c *Client) PatchAppStatus(ctx context.Context, req PatchAppStatus) error {
|
||||
res, err := c.SDK.Request(ctx, http.MethodPatch, "/api/v2/workspaceagents/me/app-status", req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return codersdk.ReadBodyAsError(res)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type PostLogSourceRequest struct {
|
||||
// ID is a unique identifier for the log source.
|
||||
// It is scoped to a workspace agent, and can be statically
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package codersdk
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
@@ -13,6 +15,14 @@ const (
|
||||
WorkspaceAppHealthUnhealthy WorkspaceAppHealth = "unhealthy"
|
||||
)
|
||||
|
||||
type WorkspaceAppStatusState string
|
||||
|
||||
const (
|
||||
WorkspaceAppStatusStateWorking WorkspaceAppStatusState = "working"
|
||||
WorkspaceAppStatusStateComplete WorkspaceAppStatusState = "complete"
|
||||
WorkspaceAppStatusStateFailure WorkspaceAppStatusState = "failure"
|
||||
)
|
||||
|
||||
var MapWorkspaceAppHealths = map[WorkspaceAppHealth]struct{}{
|
||||
WorkspaceAppHealthDisabled: {},
|
||||
WorkspaceAppHealthInitializing: {},
|
||||
@@ -75,6 +85,9 @@ type WorkspaceApp struct {
|
||||
Health WorkspaceAppHealth `json:"health"`
|
||||
Hidden bool `json:"hidden"`
|
||||
OpenIn WorkspaceAppOpenIn `json:"open_in"`
|
||||
|
||||
// Statuses is a list of statuses for the app.
|
||||
Statuses []WorkspaceAppStatus `json:"statuses"`
|
||||
}
|
||||
|
||||
type Healthcheck struct {
|
||||
@@ -85,3 +98,20 @@ type Healthcheck struct {
|
||||
// Threshold specifies the number of consecutive failed health checks before returning "unhealthy".
|
||||
Threshold int32 `json:"threshold"`
|
||||
}
|
||||
|
||||
type WorkspaceAppStatus struct {
|
||||
ID uuid.UUID `json:"id" format:"uuid"`
|
||||
CreatedAt time.Time `json:"created_at" format:"date-time"`
|
||||
WorkspaceID uuid.UUID `json:"workspace_id" format:"uuid"`
|
||||
AgentID uuid.UUID `json:"agent_id" format:"uuid"`
|
||||
AppID uuid.UUID `json:"app_id" format:"uuid"`
|
||||
State WorkspaceAppStatusState `json:"state"`
|
||||
NeedsUserAttention bool `json:"needs_user_attention"`
|
||||
Message string `json:"message"`
|
||||
// URI is the URI of the resource that the status is for.
|
||||
// e.g. https://github.com/org/repo/pull/123
|
||||
// e.g. file:///path/to/file
|
||||
URI string `json:"uri"`
|
||||
// Icon is an external URL to an icon that will be rendered in the UI.
|
||||
Icon string `json:"icon"`
|
||||
}
|
||||
|
||||
+22
-21
@@ -26,27 +26,28 @@ const (
|
||||
// Workspace is a deployment of a template. It references a specific
|
||||
// version and can be updated.
|
||||
type Workspace struct {
|
||||
ID uuid.UUID `json:"id" format:"uuid"`
|
||||
CreatedAt time.Time `json:"created_at" format:"date-time"`
|
||||
UpdatedAt time.Time `json:"updated_at" format:"date-time"`
|
||||
OwnerID uuid.UUID `json:"owner_id" format:"uuid"`
|
||||
OwnerName string `json:"owner_name"`
|
||||
OwnerAvatarURL string `json:"owner_avatar_url"`
|
||||
OrganizationID uuid.UUID `json:"organization_id" format:"uuid"`
|
||||
OrganizationName string `json:"organization_name"`
|
||||
TemplateID uuid.UUID `json:"template_id" format:"uuid"`
|
||||
TemplateName string `json:"template_name"`
|
||||
TemplateDisplayName string `json:"template_display_name"`
|
||||
TemplateIcon string `json:"template_icon"`
|
||||
TemplateAllowUserCancelWorkspaceJobs bool `json:"template_allow_user_cancel_workspace_jobs"`
|
||||
TemplateActiveVersionID uuid.UUID `json:"template_active_version_id" format:"uuid"`
|
||||
TemplateRequireActiveVersion bool `json:"template_require_active_version"`
|
||||
LatestBuild WorkspaceBuild `json:"latest_build"`
|
||||
Outdated bool `json:"outdated"`
|
||||
Name string `json:"name"`
|
||||
AutostartSchedule *string `json:"autostart_schedule,omitempty"`
|
||||
TTLMillis *int64 `json:"ttl_ms,omitempty"`
|
||||
LastUsedAt time.Time `json:"last_used_at" format:"date-time"`
|
||||
ID uuid.UUID `json:"id" format:"uuid"`
|
||||
CreatedAt time.Time `json:"created_at" format:"date-time"`
|
||||
UpdatedAt time.Time `json:"updated_at" format:"date-time"`
|
||||
OwnerID uuid.UUID `json:"owner_id" format:"uuid"`
|
||||
OwnerName string `json:"owner_name"`
|
||||
OwnerAvatarURL string `json:"owner_avatar_url"`
|
||||
OrganizationID uuid.UUID `json:"organization_id" format:"uuid"`
|
||||
OrganizationName string `json:"organization_name"`
|
||||
TemplateID uuid.UUID `json:"template_id" format:"uuid"`
|
||||
TemplateName string `json:"template_name"`
|
||||
TemplateDisplayName string `json:"template_display_name"`
|
||||
TemplateIcon string `json:"template_icon"`
|
||||
TemplateAllowUserCancelWorkspaceJobs bool `json:"template_allow_user_cancel_workspace_jobs"`
|
||||
TemplateActiveVersionID uuid.UUID `json:"template_active_version_id" format:"uuid"`
|
||||
TemplateRequireActiveVersion bool `json:"template_require_active_version"`
|
||||
LatestBuild WorkspaceBuild `json:"latest_build"`
|
||||
LatestAppStatus *WorkspaceAppStatus `json:"latest_app_status"`
|
||||
Outdated bool `json:"outdated"`
|
||||
Name string `json:"name"`
|
||||
AutostartSchedule *string `json:"autostart_schedule,omitempty"`
|
||||
TTLMillis *int64 `json:"ttl_ms,omitempty"`
|
||||
LastUsedAt time.Time `json:"last_used_at" format:"date-time"`
|
||||
|
||||
// DeletingAt indicates the time at which the workspace will be permanently deleted.
|
||||
// A workspace is eligible for deletion if it is dormant (a non-nil dormant_at value)
|
||||
|
||||
Reference in New Issue
Block a user