MCPcopy Index your code
hub / github.com/coder/coder / StopWorkspace

Function StopWorkspace

coderd/x/chatd/chattool/stopworkspace.go:40–181  ·  view source on GitHub ↗

StopWorkspace returns a tool that stops the workspace associated with the current chat. The tool is idempotent when the workspace is already stopped. db must not be nil and chatID must not be uuid.Nil.

(db database.Store, chatID uuid.UUID, options StopWorkspaceOptions)

Source from the content-addressed store, hash-verified

38// with the current chat. The tool is idempotent when the workspace is
39// already stopped. db must not be nil and chatID must not be uuid.Nil.
40func StopWorkspace(db database.Store, chatID uuid.UUID, options StopWorkspaceOptions) fantasy.AgentTool {
41 return fantasy.NewAgentTool(
42 "stop_workspace",
43 "Stop the chat's workspace and wait for the stop build to complete. "+
44 "If another workspace build is already in progress, this waits "+
45 "for that build first, then stops the workspace if needed. "+
46 "After waiting, this tool is idempotent if the workspace is "+
47 "already stopped or the in-progress build stopped it. Use "+
48 "this when the "+
49 "user explicitly asks to stop the workspace, or when a "+
50 "workspace-agent error tells you to stop and then start the "+
51 "workspace. Stopping a workspace terminates running processes "+
52 "and may discard unsaved in-memory state. This tool does not "+
53 "delete the workspace.",
54 func(ctx context.Context, _ stopWorkspaceArgs, _ fantasy.ToolCall) (fantasy.ToolResponse, error) {
55 if options.StopFn == nil {
56 return fantasy.NewTextErrorResponse("workspace stopper is not configured"), nil
57 }
58
59 // Serialize with create_workspace and start_workspace to
60 // prevent lifecycle races.
61 if options.WorkspaceMu != nil {
62 options.WorkspaceMu.Lock()
63 defer options.WorkspaceMu.Unlock()
64 }
65
66 chat, err := db.GetChatByID(ctx, chatID)
67 if err != nil {
68 return fantasy.NewTextErrorResponse(
69 xerrors.Errorf("load chat: %w", err).Error(),
70 ), nil
71 }
72 if !chat.WorkspaceID.Valid {
73 return fantasy.NewTextErrorResponse(
74 "chat has no workspace; use create_workspace first",
75 ), nil
76 }
77
78 ws, err := db.GetWorkspaceByID(ctx, chat.WorkspaceID.UUID)
79 if err != nil {
80 return fantasy.NewTextErrorResponse(
81 xerrors.Errorf("load workspace: %w", err).Error(),
82 ), nil
83 }
84 if ws.Deleted {
85 return fantasy.NewTextErrorResponse(
86 "workspace was deleted; use create_workspace to make a new one",
87 ), nil
88 }
89
90 build, job, err := latestWorkspaceBuildAndJob(ctx, db, ws.ID)
91 if err != nil {
92 return fantasy.NewTextErrorResponse(err.Error()), nil
93 }
94
95 // If a build is already in progress, wait for it before
96 // deciding whether a stop build is still needed.
97 switch job.JobStatus {

Callers 2

appendRootChatToolsMethod · 0.92
TestStopWorkspaceFunction · 0.92

Calls 15

IsResponderFunction · 0.92
publishBuildBindingFunction · 0.85
provisionerJobTerminalFunction · 0.85
buildToolResponseFunction · 0.85
newBuildErrorFunction · 0.85
setNoBuildFunction · 0.85
toolResponseFunction · 0.85
asOwnerFunction · 0.85
responseErrorResultFunction · 0.85
setBuildIDFunction · 0.85
waitForBuildFunction · 0.70

Tested by 1

TestStopWorkspaceFunction · 0.74