Skip to content

Commit 62a0a9c

Browse files
committed
feat: add support for agentapi
1 parent ee1bd53 commit 62a0a9c

File tree

4 files changed

+191
-51
lines changed

4 files changed

+191
-51
lines changed

registry/coder-labs/modules/cursor-cli/main.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ describe("cursor-cli", async () => {
9999
const mcpContent = await execContainer(id, [
100100
"bash",
101101
"-c",
102-
`cat '/home/coder/.cursor/mcp.json'`,
102+
`cat '/home/coder/project/.cursor/mcp.json'`,
103103
]);
104104
expect(mcpContent.exitCode).toBe(0);
105105
expect(mcpContent.stdout).toContain("mcpServers");

registry/coder-labs/modules/cursor-cli/main.tf

Lines changed: 80 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,24 @@ variable "cursor_cli_version" {
5353
default = "latest"
5454
}
5555

56+
variable "enable_agentapi" {
57+
type = bool
58+
description = "Whether to enable the AgentAPI for Cursor CLI."
59+
default = false
60+
}
61+
62+
variable "install_agentapi" {
63+
type = bool
64+
description = "Whether to install AgentAPI."
65+
default = true
66+
}
67+
68+
variable "agentapi_version" {
69+
type = string
70+
description = "The version of AgentAPI to install."
71+
default = "v0.4.0"
72+
}
73+
5674
# Running mode is non-interactive by design for automation.
5775

5876

@@ -132,6 +150,7 @@ resource "coder_script" "cursor_cli" {
132150
agent_id = var.agent_id
133151
display_name = "Cursor CLI"
134152
icon = var.icon
153+
count = var.enable_agentapi ? 0 : 1
135154
script = <<-EOT
136155
#!/bin/bash
137156
set -o errexit
@@ -151,10 +170,10 @@ resource "coder_script" "cursor_cli" {
151170
fi
152171
ARG_INSTALL='${var.install_cursor_cli}' \
153172
ARG_VERSION='${var.cursor_cli_version}' \
154-
WORKSPACE_MCP_JSON='${var.mcp_json != null ? base64encode(replace(var.mcp_json, "'", "'\\''")) : ""}' \
155-
WORKSPACE_RULES_JSON='${var.rules_files != null ? base64encode(jsonencode(var.rules_files)) : ""}' \
156-
MODULE_DIR_NAME='${local.module_dir_name}' \
157-
FOLDER='${var.folder}' \
173+
ARG_WORKSPACE_MCP_JSON='${var.mcp_json != null ? base64encode(replace(var.mcp_json, "'", "'\\''")) : ""}' \
174+
ARG_WORKSPACE_RULES_JSON='${var.rules_files != null ? base64encode(jsonencode(var.rules_files)) : ""}' \
175+
ARG_MODULE_DIR_NAME='${local.module_dir_name}' \
176+
ARG_FOLDER='${var.folder}' \
158177
/tmp/install.sh | tee "$HOME/${local.module_dir_name}/install.log"
159178
160179
# Run optional post-install script
@@ -167,11 +186,11 @@ resource "coder_script" "cursor_cli" {
167186
168187
echo -n '${base64encode(local.start_script)}' | base64 -d > /tmp/start.sh
169188
chmod +x /tmp/start.sh
170-
FORCE='${var.force}' \
171-
MODEL='${var.model}' \
172-
AI_PROMPT='${var.ai_prompt}' \
173-
MODULE_DIR_NAME='${local.module_dir_name}' \
174-
FOLDER='${var.folder}' \
189+
ARG_FORCE='${var.force}' \
190+
ARG_MODEL='${var.model}' \
191+
ARG_AI_PROMPT='${base64encode(var.ai_prompt)}' \
192+
ARG_MODULE_DIR_NAME='${local.module_dir_name}' \
193+
ARG_FOLDER='${var.folder}' \
175194
/tmp/start.sh | tee "$HOME/${local.module_dir_name}/start.log"
176195
EOT
177196
run_on_start = true
@@ -181,6 +200,7 @@ resource "coder_app" "cursor_cli" {
181200
agent_id = var.agent_id
182201
slug = local.app_slug
183202
display_name = "Cursor CLI"
203+
count = var.enable_agentapi ? 0 : 1
184204
icon = var.icon
185205
order = var.order
186206
group = var.group
@@ -197,7 +217,55 @@ resource "coder_app" "cursor_cli" {
197217
EOT
198218
}
199219

200-
output "app_id" {
201-
description = "The ID of the Cursor CLI app."
202-
value = coder_app.cursor_cli.id
220+
module "agentapi" {
221+
source = "registry.coder.com/coder/agentapi/coder"
222+
version = "1.0.0"
223+
count = var.enable_agentapi ? 1 : 0
224+
225+
agent_id = var.agent_id
226+
web_app_slug = "${local.app_slug}-agentapi"
227+
web_app_order = var.order
228+
web_app_group = var.group
229+
web_app_icon = var.icon
230+
web_app_display_name = "Cursor CLI"
231+
cli_app_slug = local.app_slug
232+
cli_app_display_name = "Cursor CLI"
233+
module_dir_name = local.module_dir_name
234+
install_agentapi = var.install_agentapi
235+
agentapi_version = var.agentapi_version
236+
pre_install_script = var.pre_install_script
237+
post_install_script = var.post_install_script
238+
start_script = <<-EOT
239+
#!/bin/bash
240+
set -o errexit
241+
set -o pipefail
242+
243+
echo -n '${base64encode(local.start_script)}' | base64 -d > /tmp/start.sh
244+
chmod +x /tmp/start.sh
245+
ARG_FORCE='${var.force}' \
246+
ARG_MODEL='${var.model}' \
247+
ARG_AI_PROMPT='${base64encode(var.ai_prompt)}' \
248+
ARG_MODULE_DIR_NAME='${local.module_dir_name}' \
249+
ARG_FOLDER='${var.folder}' \
250+
ARG_AGENTAPI_MODE='${var.enable_agentapi}' \
251+
/tmp/start.sh
252+
EOT
253+
254+
install_script = <<-EOT
255+
#!/bin/bash
256+
set -o errexit
257+
set -o pipefail
258+
259+
echo -n '${base64encode(local.install_script)}' | base64 -d > /tmp/install.sh
260+
chmod +x /tmp/install.sh
261+
ARG_INSTALL='${var.install_cursor_cli}' \
262+
ARG_VERSION='${var.cursor_cli_version}' \
263+
ARG_WORKSPACE_MCP_JSON='${var.mcp_json != null ? base64encode(replace(var.mcp_json, "'", "'\\''")) : ""}' \
264+
ARG_WORKSPACE_RULES_JSON='${var.rules_files != null ? base64encode(jsonencode(var.rules_files)) : ""}' \
265+
ARG_MODULE_DIR_NAME='${local.module_dir_name}' \
266+
ARG_FOLDER='${var.folder}' \
267+
ARG_AGENTAPI_MODE='${var.enable_agentapi}' \
268+
ARG_CODER_MCP_APP_STATUS_SLUG='${local.app_slug}-agentapi' \
269+
/tmp/install.sh
270+
EOT
203271
}

registry/coder-labs/modules/cursor-cli/scripts/install.sh

Lines changed: 64 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,31 +10,36 @@ command_exists() {
1010
# Inputs
1111
ARG_INSTALL=${ARG_INSTALL:-true}
1212
ARG_VERSION=${ARG_VERSION:-latest}
13-
MODULE_DIR_NAME=${MODULE_DIR_NAME:-.cursor-cli-module}
14-
FOLDER=${FOLDER:-$HOME}
13+
ARG_MODULE_DIR_NAME=${ARG_MODULE_DIR_NAME:-.cursor-cli-module}
14+
ARG_FOLDER=${ARG_FOLDER:-$HOME}
15+
ARG_AGENTAPI_MODE=${ARG_AGENTAPI_MODE:-false}
16+
ARG_CODER_MCP_APP_STATUS_SLUG=${ARG_CODER_MCP_APP_STATUS_SLUG:-}
1517

16-
mkdir -p "$HOME/$MODULE_DIR_NAME"
18+
mkdir -p "$HOME/$ARG_MODULE_DIR_NAME"
1719

18-
WORKSPACE_MCP_JSON=$(echo -n "$WORKSPACE_MCP_JSON" | base64 -d)
19-
WORKSPACE_RULES_JSON=$(echo -n "$WORKSPACE_RULES_JSON" | base64 -d)
20+
ARG_WORKSPACE_MCP_JSON=$(echo -n "$ARG_WORKSPACE_MCP_JSON" | base64 -d)
21+
ARG_WORKSPACE_RULES_JSON=$(echo -n "$ARG_WORKSPACE_RULES_JSON" | base64 -d)
2022

2123
{
2224
echo "--------------------------------"
2325
echo "install: $ARG_INSTALL"
2426
echo "version: $ARG_VERSION"
25-
echo "folder: $FOLDER"
27+
echo "folder: $ARG_FOLDER"
28+
echo "agentapi_mode: $ARG_AGENTAPI_MODE"
29+
echo "coder_mcp_app_status_slug: $ARG_CODER_MCP_APP_STATUS_SLUG"
30+
echo "module_dir_name: $ARG_MODULE_DIR_NAME"
2631
echo "--------------------------------"
27-
} | tee -a "$HOME/$MODULE_DIR_NAME/install.log"
32+
} | tee -a "$HOME/$ARG_MODULE_DIR_NAME/install.log"
2833

2934
# Install Cursor via official installer if requested
3035
if [ "$ARG_INSTALL" = "true" ]; then
31-
echo "Installing Cursor via official installer..." | tee -a "$HOME/$MODULE_DIR_NAME/install.log"
36+
echo "Installing Cursor via official installer..." | tee -a "$HOME/$ARG_MODULE_DIR_NAME/install.log"
3237
set +e
33-
curl https://cursor.com/install -fsS | bash 2>&1 | tee -a "$HOME/$MODULE_DIR_NAME/install.log"
38+
curl https://cursor.com/install -fsS | bash 2>&1 | tee -a "$HOME/$ARG_MODULE_DIR_NAME/install.log"
3439
CURL_EXIT=${PIPESTATUS[0]}
3540
set -e
3641
if [ $CURL_EXIT -ne 0 ]; then
37-
echo "Cursor installer failed with exit code $CURL_EXIT" | tee -a "$HOME/$MODULE_DIR_NAME/install.log"
42+
echo "Cursor installer failed with exit code $CURL_EXIT" | tee -a "$HOME/$ARG_MODULE_DIR_NAME/install.log"
3843
fi
3944

4045
# Ensure binaries are discoverable; create stable symlink to cursor-agent
@@ -53,7 +58,7 @@ if [ "$ARG_INSTALL" = "true" ]; then
5358
if [ -n "$FOUND_BIN" ]; then
5459
ln -sf "$FOUND_BIN" "$HOME/.local/bin/cursor-agent"
5560
fi
56-
echo "Installed cursor-agent at: $(command -v cursor-agent || true) (resolved: $FOUND_BIN)" | tee -a "$HOME/$MODULE_DIR_NAME/install.log"
61+
echo "Installed cursor-agent at: $(command -v cursor-agent || true) (resolved: $FOUND_BIN)" | tee -a "$HOME/$ARG_MODULE_DIR_NAME/install.log"
5762
fi
5863

5964
# Ensure status slug env is exported for downstream processes
@@ -62,25 +67,65 @@ if [ -n "${STATUS_SLUG:-}" ]; then
6267
export CODER_MCP_APP_STATUS_SLUG="$STATUS_SLUG"
6368
fi
6469

65-
# Write MCP config to user's home if provided (~/.cursor/mcp.json)
66-
if [ -n "$WORKSPACE_MCP_JSON" ]; then
67-
TARGET_DIR="$HOME/.cursor"
70+
# Write MCP config to user's home if provided (ARG_FOLDER/.cursor/mcp.json)
71+
if [ -n "$ARG_WORKSPACE_MCP_JSON" ] || [ "$ARG_AGENTAPI_MODE" = "true" ]; then
72+
TARGET_DIR="$ARG_FOLDER/.cursor"
6873
TARGET_FILE="$TARGET_DIR/mcp.json"
6974
mkdir -p "$TARGET_DIR"
70-
echo "$WORKSPACE_MCP_JSON" > "$TARGET_FILE"
71-
echo "Wrote workspace MCP to $TARGET_FILE" | tee -a "$HOME/$MODULE_DIR_NAME/install.log"
75+
76+
77+
if [ "$ARG_AGENTAPI_MODE" = "true" ]; then
78+
79+
CURSOR_MCP_HACK_SCRIPT=$(cat <<EOF
80+
#!/usr/bin/env bash
81+
set -e
82+
83+
# --- Set environment variables ---
84+
export CODER_MCP_APP_STATUS_SLUG="${ARG_CODER_MCP_APP_STATUS_SLUG}"
85+
export CODER_MCP_AI_AGENTAPI_URL="http://localhost:3284"
86+
export CODER_AGENT_URL="${CODER_AGENT_URL}"
87+
export CODER_AGENT_TOKEN="${CODER_AGENT_TOKEN}"
88+
89+
# --- Launch the MCP server ---
90+
exec coder exp mcp server
91+
EOF
92+
)
93+
echo "$CURSOR_MCP_HACK_SCRIPT" > "/tmp/mcp-hack.sh"
94+
chmod +x /tmp/mcp-hack.sh
95+
96+
CODER_MCP=$(cat <<EOF
97+
{
98+
"coder": {
99+
"args": [],
100+
"command": "/tmp/mcp-hack.sh",
101+
"description": "Report ALL tasks and statuses (in progress, done, failed) you are working on.",
102+
"name": "Coder",
103+
"timeout": 3000,
104+
"type": "stdio",
105+
"trust": true
106+
}
107+
}
108+
EOF
109+
)
110+
111+
echo "${ARG_WORKSPACE_MCP_JSON:-{}}" | jq --argjson base "$CODER_MCP" \
112+
'.mcpServers = ((.mcpServers // {}) + $base)' > "$TARGET_FILE"
113+
else
114+
echo "${ARG_WORKSPACE_MCP_JSON}" > "$TARGET_FILE"
115+
fi
116+
echo "Wrote workspace MCP to $TARGET_FILE" | tee -a "$HOME/$ARG_MODULE_DIR_NAME/install.log"
72117
fi
73118

74119
# Write rules files to user's home (~/.cursor/rules)
75-
if [ -n "$WORKSPACE_RULES_JSON" ]; then
120+
if [ -n "$ARG_WORKSPACE_RULES_JSON" ]; then
76121
RULES_DIR="$HOME/.cursor/rules"
77122
mkdir -p "$RULES_DIR"
78-
echo "$WORKSPACE_RULES_JSON" | jq -r 'to_entries[] | @base64' | while read -r entry; do
123+
echo "$ARG_WORKSPACE_RULES_JSON" | jq -r 'to_entries[] | @base64' | while read -r entry; do
79124
_jq() { echo "${entry}" | base64 -d | jq -r ${1}; }
80125
NAME=$(_jq '.key')
81126
CONTENT=$(_jq '.value')
82127
echo "$CONTENT" > "$RULES_DIR/$NAME"
83-
echo "Wrote rule: $RULES_DIR/$NAME" | tee -a "$HOME/$MODULE_DIR_NAME/install.log"
128+
echo "Wrote rule: $RULES_DIR/$NAME" | tee -a "$HOME/$ARG_MODULE_DIR_NAME/install.log"
84129
done
85130
fi
86131

registry/coder-labs/modules/cursor-cli/scripts/start.sh

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,31 @@ command_exists() {
77
command -v "$1" >/dev/null 2>&1
88
}
99

10-
AI_PROMPT=${AI_PROMPT:-}
11-
FORCE=${FORCE:-false}
12-
MODEL=${MODEL:-}
13-
OUTPUT_FORMAT=${OUTPUT_FORMAT:-json}
14-
MODULE_DIR_NAME=${MODULE_DIR_NAME:-.cursor-cli-module}
15-
FOLDER=${FOLDER:-$HOME}
10+
ARG_AI_PROMPT=$(echo -n "${ARG_AI_PROMPT:-}" | base64 -d)
11+
ARG_FORCE=${ARG_FORCE:-false}
12+
ARG_MODEL=${ARG_MODEL:-}
13+
ARG_OUTPUT_FORMAT=${ARG_OUTPUT_FORMAT:-json}
14+
ARG_MODULE_DIR_NAME=${ARG_MODULE_DIR_NAME:-.cursor-cli-module}
15+
ARG_FOLDER=${ARG_FOLDER:-$HOME}
16+
ARG_AGENTAPI_MODE=${ARG_AGENTAPI_MODE:-false}
1617

17-
mkdir -p "$HOME/$MODULE_DIR_NAME"
18+
{
19+
echo "--------------------------------"
20+
echo "install: $ARG_INSTALL"
21+
echo "version: $ARG_VERSION"
22+
echo "folder: $FOLDER"
23+
echo "ai_prompt: $ARG_AI_PROMPT"
24+
echo "force: $ARG_FORCE"
25+
echo "model: $ARG_MODEL"
26+
echo "output_format: $ARG_OUTPUT_FORMAT"
27+
echo "module_dir_name: $ARG_MODULE_DIR_NAME"
28+
echo "folder: $ARG_FOLDER"
29+
echo "agentapi_mode: $ARG_AGENTAPI_MODE"
30+
echo "--------------------------------"
31+
} | tee -a "$HOME/$MODULE_DIR_NAME/start.log"
32+
33+
34+
mkdir -p "$HOME/$ARG_MODULE_DIR_NAME"
1835

1936

2037
# Find cursor agent cli
@@ -23,32 +40,42 @@ if command_exists cursor-agent; then
2340
elif [ -x "$HOME/.local/bin/cursor-agent" ]; then
2441
CURSOR_CMD="$HOME/.local/bin/cursor-agent"
2542
else
26-
echo "Error: cursor-agent not found. Install it or set install_cursor_cli=true." | tee -a "$HOME/$MODULE_DIR_NAME/start.log"
43+
echo "Error: cursor-agent not found. Install it or set install_cursor_cli=true." | tee -a "$HOME/$ARG_MODULE_DIR_NAME/start.log"
2744
exit 1
2845
fi
2946

3047
# Ensure working directory exists
31-
if [ -d "$FOLDER" ]; then
32-
cd "$FOLDER"
48+
if [ -d "$ARG_FOLDER" ]; then
49+
cd "$ARG_FOLDER"
3350
else
34-
mkdir -p "$FOLDER"
35-
cd "$FOLDER"
51+
mkdir -p "$ARG_FOLDER"
52+
cd "$ARG_FOLDER"
3653
fi
3754

3855
ARGS=()
3956

4057
# global flags
41-
if [ -n "$MODEL" ]; then
42-
ARGS+=("-m" "$MODEL")
58+
if [ -n "$ARG_MODEL" ]; then
59+
ARGS+=("-m" "$ARG_MODEL")
4360
fi
44-
if [ "$FORCE" = "true" ]; then
61+
if [ "$ARG_FORCE" = "true" ]; then
4562
ARGS+=("-f")
4663
fi
4764

48-
if [ -n "$AI_PROMPT" ]; then
49-
ARGS+=("$AI_PROMPT")
65+
if [ -n "$ARG_AI_PROMPT" ]; then
66+
printf "AI prompt provided\n"
67+
if [ "$ARG_AGENTAPI_MODE" = "true" ]; then
68+
ARGS+=("Complete the task at hand and at every step of the way, report tasks to Coder with proper summary and statuses. Your task at hand: $ARG_AI_PROMPT")
69+
elif [ "$ARG_AI_PROMPT" ]; then
70+
ARGS+=("$ARG_AI_PROMPT")
71+
fi
5072
fi
5173

5274
# Log and run in background, redirecting all output to the log file
53-
printf "Running: %q %s\n" "$CURSOR_CMD" "$(printf '%q ' "${ARGS[@]}")" | tee -a "$HOME/$MODULE_DIR_NAME/start.log"
54-
("$CURSOR_CMD" "${ARGS[@]}" >> "$HOME/$MODULE_DIR_NAME/start.log" 2>&1) &
75+
printf "Running: %q %s\n" "$CURSOR_CMD" "$(printf '%q ' "${ARGS[@]}")" | tee -a "$HOME/$ARG_MODULE_DIR_NAME/start.log"
76+
77+
if [ "$ARG_AGENTAPI_MODE" = "true" ]; then
78+
agentapi server --term-width 67 --term-height 1190 -- "$CURSOR_CMD" "${ARGS[@]}"
79+
else
80+
("$CURSOR_CMD" "${ARGS[@]}" >> "$HOME/$ARG_MODULE_DIR_NAME/start.log" 2>&1) &
81+
fi

0 commit comments

Comments
 (0)