Skip to content
Draft
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
29 changes: 28 additions & 1 deletion .github/workflows/runner-tool-versions.yml
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ jobs:
echo "uv=$(parse UV_VERSION)" >> "$GITHUB_OUTPUT"
echo "pre_commit=$(parse PRE_COMMIT_VERSION)" >> "$GITHUB_OUTPUT"
echo "gemini_cli=$(parse GEMINI_CLI_VERSION)" >> "$GITHUB_OUTPUT"
# Cursor CLI: ARG is documentation-only (installer fetches latest).
# Parsed here for visibility in the PR summary table.
echo "cursor_cli=$(parse CURSOR_CLI_VERSION)" >> "$GITHUB_OUTPUT"

# ── Fetch latest upstream versions ────────────────────────────────

Expand Down Expand Up @@ -102,6 +105,11 @@ jobs:
"https://registry.npmjs.org/@google/gemini-cli/latest" \
'.version' &
pids+=($!); names+=("gemini-cli")
# Cursor CLI: no package registry — pass through the current pinned value.
# The installer (cursor.com/install) fetches "latest" automatically; automated
# version bumps are not yet possible. Update CURSOR_CLI_VERSION manually once
# Cursor publishes versioned binary releases.
echo "cursor_cli=${{ steps.current.outputs.cursor_cli }}" >> "$GITHUB_OUTPUT"

failed=false
for i in "${!pids[@]}"; do
Expand Down Expand Up @@ -129,6 +137,8 @@ jobs:
LAT_PC: ${{ steps.latest.outputs.pre_commit }}
CUR_GEM: ${{ steps.current.outputs.gemini_cli }}
LAT_GEM: ${{ steps.latest.outputs.gemini_cli }}
CUR_CURSOR: ${{ steps.current.outputs.cursor_cli }}
LAT_CURSOR: ${{ steps.latest.outputs.cursor_cli }}
run: |
needs_update=false
updates=""
Expand Down Expand Up @@ -162,6 +172,10 @@ jobs:
check_tool uv "$CUR_UV" "$LAT_UV"
check_tool pc "$CUR_PC" "$LAT_PC"
check_tool gem "$CUR_GEM" "$LAT_GEM"
# Cursor CLI: latest always equals current (pass-through) — check_tool
# will always emit cursor=false. Included for future use when Cursor
# publishes a queryable version registry.
check_tool cursor "$CUR_CURSOR" "$LAT_CURSOR"

echo "any=$needs_update" >> "$GITHUB_OUTPUT"
echo "updates=$updates" >> "$GITHUB_OUTPUT"
Expand All @@ -184,12 +198,15 @@ jobs:
LAT_PC: ${{ steps.latest.outputs.pre_commit }}
CUR_GEM: ${{ steps.current.outputs.gemini_cli }}
LAT_GEM: ${{ steps.latest.outputs.gemini_cli }}
CUR_CURSOR: ${{ steps.current.outputs.cursor_cli }}
LAT_CURSOR: ${{ steps.latest.outputs.cursor_cli }}
UPD_BASE: ${{ steps.diff.outputs.base }}
UPD_GH: ${{ steps.diff.outputs.gh }}
UPD_GLAB: ${{ steps.diff.outputs.glab }}
UPD_UV: ${{ steps.diff.outputs.uv }}
UPD_PC: ${{ steps.diff.outputs.pc }}
UPD_GEM: ${{ steps.diff.outputs.gem }}
UPD_CURSOR: ${{ steps.diff.outputs.cursor }}
run: |
# Build sed expressions for all components that need updating
SED_ARGS=()
Expand All @@ -199,12 +216,17 @@ jobs:
[ "$UPD_UV" = "true" ] && SED_ARGS+=(-e "s/ARG UV_VERSION=${CUR_UV}/ARG UV_VERSION=${LAT_UV}/")
[ "$UPD_PC" = "true" ] && SED_ARGS+=(-e "s/ARG PRE_COMMIT_VERSION=${CUR_PC}/ARG PRE_COMMIT_VERSION=${LAT_PC}/")
[ "$UPD_GEM" = "true" ] && SED_ARGS+=(-e "s/ARG GEMINI_CLI_VERSION=${CUR_GEM}/ARG GEMINI_CLI_VERSION=${LAT_GEM}/")
# Cursor CLI: UPD_CURSOR will always be false (pass-through); included for
# future use when Cursor publishes a queryable release registry.
[ "$UPD_CURSOR" = "true" ] && SED_ARGS+=(-e "s/ARG CURSOR_CLI_VERSION=${CUR_CURSOR}/ARG CURSOR_CLI_VERSION=${LAT_CURSOR}/")

if [ ${#SED_ARGS[@]} -gt 0 ]; then
sed -i "${SED_ARGS[@]}" "$DOCKERFILE"
fi

# Sanity check: all ARGs still present and non-empty
# Sanity check: all version-controlled ARGs still present and non-empty.
# CURSOR_CLI_VERSION is intentionally excluded — it is a documentation-only
# placeholder and does not control what the installer fetches.
for arg in GH_VERSION GLAB_VERSION UV_VERSION PRE_COMMIT_VERSION GEMINI_CLI_VERSION; do
if ! grep -qP "ARG ${arg}=\S+" "$DOCKERFILE"; then
echo "ERROR: ${arg} missing or empty after update"
Expand Down Expand Up @@ -247,6 +269,7 @@ jobs:
LAT_PC: ${{ steps.latest.outputs.pre_commit }}
CUR_GEM: ${{ steps.current.outputs.gemini_cli }}
LAT_GEM: ${{ steps.latest.outputs.gemini_cli }}
CUR_CURSOR: ${{ steps.current.outputs.cursor_cli }}
UPD_BASE: ${{ steps.diff.outputs.base }}
UPD_GH: ${{ steps.diff.outputs.gh }}
UPD_GLAB: ${{ steps.diff.outputs.glab }}
Expand All @@ -270,6 +293,7 @@ jobs:
[ "$UPD_UV" = "true" ] && CHANGED="${CHANGED}uv "
[ "$UPD_PC" = "true" ] && CHANGED="${CHANGED}pre-commit "
[ "$UPD_GEM" = "true" ] && CHANGED="${CHANGED}gemini-cli "
# cursor-cli is never updated automatically (pass-through); omit from title
CHANGED=$(echo "$CHANGED" | xargs | tr ' ' ', ')

git commit -m "chore(runner): update ${CHANGED}
Expand All @@ -293,6 +317,7 @@ jobs:
| uv | $(status "$UPD_UV" "$CUR_UV" "$LAT_UV") |
| pre-commit | $(status "$UPD_PC" "$CUR_PC" "$LAT_PC") |
| gemini-cli | $(status "$UPD_GEM" "$CUR_GEM" "$LAT_GEM") |
| cursor-cli | \`${CUR_CURSOR}\` (installer fetches latest — no auto-bump) |

### Components not version-pinned (updated with base image)

Expand Down Expand Up @@ -333,6 +358,7 @@ jobs:
LAT_PC: ${{ steps.latest.outputs.pre_commit }}
CUR_GEM: ${{ steps.current.outputs.gemini_cli }}
LAT_GEM: ${{ steps.latest.outputs.gemini_cli }}
CUR_CURSOR: ${{ steps.current.outputs.cursor_cli }}
ANY_UPDATE: ${{ steps.diff.outputs.any }}
PR_EXISTS: ${{ steps.existing_pr.outputs.pr_exists || 'false' }}
run: |
Expand All @@ -349,6 +375,7 @@ jobs:
echo "| uv | \`${CUR_UV}\` | \`${LAT_UV}\` | $(icon "$CUR_UV" "$LAT_UV") |"
echo "| pre-commit | \`${CUR_PC}\` | \`${LAT_PC}\` | $(icon "$CUR_PC" "$LAT_PC") |"
echo "| gemini-cli | \`${CUR_GEM}\` | \`${LAT_GEM}\` | $(icon "$CUR_GEM" "$LAT_GEM") |"
echo "| cursor-cli | \`${CUR_CURSOR}\` | (installer fetches latest) | ℹ️ |"
echo ""
if [ "$ANY_UPDATE" = "true" ]; then
if [ "$PR_EXISTS" = "true" ]; then
Expand Down
29 changes: 29 additions & 0 deletions components/manifests/base/core/agent-registry-configmap.yaml
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,34 @@ data:
"vertexSupported": true
},
"featureGate": "runner.gemini-cli.enabled"
},
{
"id": "cursor-cli",
"displayName": "Cursor CLI",
"description": "Cursor coding agent with multi-model support and built-in file, bash, and search tools",
"framework": "cursor-cli",
"provider": "cursor",
"container": {
"image": "quay.io/ambient_code/vteam_claude_runner:latest",
"port": 8001,
"env": {
"RUNNER_TYPE": "cursor-cli",
"RUNNER_STATE_DIR": ".cursor"
}
},
"sandbox": {
"stateDir": ".cursor",
"stateSyncImage": "quay.io/ambient_code/vteam_state_sync:latest",
"persistence": "s3",
"workspaceSize": "10Gi",
"terminationGracePeriod": 60,
"seed": {"cloneRepos": true, "hydrateState": true}
},
"auth": {
"requiredSecretKeys": ["CURSOR_API_KEY"],
"secretKeyLogic": "any",
"vertexSupported": false
},
"featureGate": "runner.cursor-cli.enabled"
}
]
10 changes: 10 additions & 0 deletions components/manifests/base/core/flags.json
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
{
"flags": [
{
"name": "runner.cursor-cli.enabled",
"description": "Enable Cursor CLI runner type for session creation",
"tags": [
{
"type": "scope",
"value": "workspace"
}
]
},
{
"name": "runner.gemini-cli.enabled",
"description": "Enable Gemini CLI runner type for session creation",
Expand Down
35 changes: 34 additions & 1 deletion components/manifests/base/core/models.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"defaultModel": "claude-sonnet-4-6",
"providerDefaults": {
"anthropic": "claude-sonnet-4-6",
"google": "gemini-2.5-flash"
"google": "gemini-2.5-flash",
"cursor": "claude-sonnet-4-6"
},
"models": [
{
Expand Down Expand Up @@ -141,6 +142,38 @@
"provider": "google",
"available": true,
"featureGated": true
},
{
"id": "cursor:claude-sonnet-4-6",
"label": "Claude Sonnet 4.6 (via Cursor)",
"vertexId": "",
"provider": "cursor",
"available": true,
"featureGated": false
},
{
"id": "cursor:claude-opus-4-6",
"label": "Claude Opus 4.6 (via Cursor)",
"vertexId": "",
"provider": "cursor",
"available": true,
"featureGated": true
},
{
"id": "cursor:gpt-5",
"label": "GPT-5 (via Cursor)",
"vertexId": "",
"provider": "cursor",
"available": false,
"featureGated": true
},
{
"id": "cursor:composer",
"label": "Composer 1 (Cursor)",
"vertexId": "",
"provider": "cursor",
"available": true,
"featureGated": false
}
]
}
13 changes: 13 additions & 0 deletions components/runners/ambient-runner/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ ARG GLAB_VERSION=1.52.0
ARG UV_VERSION=0.7.8
ARG PRE_COMMIT_VERSION=4.2.0
ARG GEMINI_CLI_VERSION=0.1.17
# NOTE: CURSOR_CLI_VERSION is a documentation-only placeholder. The official
# installer (cursor.com/install) fetches "latest" automatically and does not
# accept a version argument. Switch to a pinned binary URL once Cursor
# publishes versioned releases. Not included in runner-tool-versions sanity check.
ARG CURSOR_CLI_VERSION=1.0.0

# Install system packages: Python 3.12, git, jq, Node.js, Go
RUN dnf install -y python3 python3-pip python3-devel \
Expand Down Expand Up @@ -43,6 +48,14 @@ RUN pip3 install --break-system-packages --no-cache-dir '/app/ambient-runner[all
RUN npm install -g @google/gemini-cli@${GEMINI_CLI_VERSION} && \
npm cache clean --force

# Install Cursor Agent CLI via official installer.
# The installer places the binary at $HOME/.local/bin/cursor-agent.
# We run as root during build, then symlink to /usr/local/bin/ so it's
# in PATH for the runtime user (UID 1001).
RUN curl -fsSL "https://cursor.com/install" | bash && \
ln -sf /root/.local/bin/cursor-agent /usr/local/bin/cursor-agent && \
chmod +x /usr/local/bin/cursor-agent

# Set environment variables
ENV PYTHONUNBUFFERED=1
ENV PYTHONDONTWRITEBYTECODE=1
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# components/runners/ambient-runner/ag_ui_cursor_cli/__init__.py
"""AG-UI adapter for Cursor CLI stream-json output."""

from ag_ui_cursor_cli.adapter import CursorCLIAdapter

__all__ = ["CursorCLIAdapter"]
Loading
Loading