Skip to content

Commit 9629145

Browse files
committed
feat: workspace bash background parameter
1 parent 00dd127 commit 9629145

File tree

2 files changed

+58
-5
lines changed

2 files changed

+58
-5
lines changed

codersdk/toolsdk/bash.go

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package toolsdk
33
import (
44
"bytes"
55
"context"
6+
_ "embed"
7+
"encoding/base64"
68
"errors"
79
"fmt"
810
"io"
@@ -18,19 +20,24 @@ import (
1820
"github.com/coder/coder/v2/cli/cliui"
1921
"github.com/coder/coder/v2/codersdk"
2022
"github.com/coder/coder/v2/codersdk/workspacesdk"
23+
"github.com/coder/coder/v2/cryptorand"
2124
)
2225

2326
type WorkspaceBashArgs struct {
24-
Workspace string `json:"workspace"`
25-
Command string `json:"command"`
26-
TimeoutMs int `json:"timeout_ms,omitempty"`
27+
Workspace string `json:"workspace"`
28+
Command string `json:"command"`
29+
TimeoutMs int `json:"timeout_ms,omitempty"`
30+
Background bool `json:"background,omitempty"`
2731
}
2832

2933
type WorkspaceBashResult struct {
3034
Output string `json:"output"`
3135
ExitCode int `json:"exit_code"`
3236
}
3337

38+
//go:embed resources/background.sh
39+
var backgroundScript string
40+
3441
var WorkspaceBash = Tool[WorkspaceBashArgs, WorkspaceBashResult]{
3542
Tool: aisdk.Tool{
3643
Name: ToolNameWorkspaceBash,
@@ -53,6 +60,7 @@ If the command times out, all output captured up to that point is returned with
5360
Examples:
5461
- workspace: "my-workspace", command: "ls -la"
5562
- workspace: "john/dev-env", command: "git status", timeout_ms: 30000
63+
- workspace: "my-workspace", command: "npm run dev", background: true
5664
- workspace: "my-workspace.main", command: "docker ps"`,
5765
Schema: aisdk.Schema{
5866
Properties: map[string]any{
@@ -70,6 +78,10 @@ Examples:
7078
"default": 60000,
7179
"minimum": 1,
7280
},
81+
"background": map[string]any{
82+
"type": "boolean",
83+
"description": "Whether to run the command in the background. The command will not be affected by the timeout.",
84+
},
7385
},
7486
Required: []string{"workspace", "command"},
7587
},
@@ -137,16 +149,34 @@ Examples:
137149

138150
// Set default timeout if not specified (60 seconds)
139151
timeoutMs := args.TimeoutMs
152+
defaultTimeoutMs := 60000
140153
if timeoutMs <= 0 {
141-
timeoutMs = 60000
154+
timeoutMs = defaultTimeoutMs
155+
}
156+
command := args.Command
157+
if args.Background {
158+
// Background commands are not affected by the timeout
159+
timeoutMs = defaultTimeoutMs
160+
encodedCommand := base64.StdEncoding.EncodeToString([]byte(args.Command))
161+
encodedScript := base64.StdEncoding.EncodeToString([]byte(backgroundScript))
162+
commandID, err := cryptorand.StringCharset(cryptorand.Human, 8)
163+
if err != nil {
164+
return WorkspaceBashResult{}, xerrors.Errorf("failed to generate command ID: %w", err)
165+
}
166+
command = fmt.Sprintf(
167+
"ARG_COMMAND=\"$(echo -n %s | base64 -d)\" ARG_COMMAND_ID=%s bash -c \"$(echo -n %s | base64 -d)\"",
168+
encodedCommand,
169+
commandID,
170+
encodedScript,
171+
)
142172
}
143173

144174
// Create context with timeout
145175
ctx, cancel = context.WithTimeout(ctx, time.Duration(timeoutMs)*time.Millisecond)
146176
defer cancel()
147177

148178
// Execute command with timeout handling
149-
output, err := executeCommandWithTimeout(ctx, session, args.Command)
179+
output, err := executeCommandWithTimeout(ctx, session, command)
150180
outputStr := strings.TrimSpace(string(output))
151181

152182
// Handle command execution results
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/bin/bash
2+
3+
# This script is used to run a command in the background.
4+
5+
set -o errexit
6+
set -o pipefail
7+
8+
set -o nounset
9+
10+
COMMAND="$ARG_COMMAND"
11+
COMMAND_ID="$ARG_COMMAND_ID"
12+
13+
set +o nounset
14+
15+
LOG_DIR="/tmp/mcp-bg"
16+
LOG_PATH="$LOG_DIR/$COMMAND_ID.log"
17+
mkdir -p "$LOG_DIR"
18+
19+
nohup bash -c "$COMMAND" >"$LOG_PATH" 2>&1 &
20+
COMMAND_PID="$!"
21+
22+
echo "Command started with PID: $COMMAND_PID"
23+
echo "Log path: $LOG_PATH"

0 commit comments

Comments
 (0)