Skill: CNB 连接

元信息

  • 名称: cnb-connect
  • 描述: 连接 CNB 云端工作空间,在云端默认终端执行,保存终端配置并获取 SSH 连接信息
  • 关键词: cnb, 云端工作空间, cloud native

执行环境

  • 终端: CNB 云端默认终端(/bin/sh
  • 依赖: curl, sed, grep, awk, tr(云端默认安装)

脚本

#!/bin/bash

# CNB 连接脚本(逐步执行版)
# 依赖: curl, sed, grep, awk, tr(云端默认工具)

# JSON 字段提取函数(云端兼容版)
getJsonStr() {
    local json="$1"
    local key="$2"
    echo "$json" | sed 's/"/ /g' | tr ',' '\n' | grep " $key " | sed 's/.*'$key' //' | awk '{print $1}'
}

# ========== 步骤 1: 获取 CNB Token ==========
echo ""
echo "=== 步骤 1/7: 获取 CNB Token ==="
PREF_RESULT=$(curl -s "https://www.skillup.host/api/lae/api/office/doc/preference" \
  -H "Authorization: Bearer {{AUTH}}")

CNB_TOKEN=$(getJsonStr "$PREF_RESULT" "cnb_token")

if [ -z "$CNB_TOKEN" ] || [ "$CNB_TOKEN" = "null" ] || [ "$CNB_TOKEN" = "" ]; then
  echo "❌ 获取 CNB Token 失败,请确认已在个人偏好中绑定 CNB 账号"
  exit 1
fi
echo "✓ CNB Token 获取成功"

# ========== 步骤 2: 获取工作空间列表 ==========
echo ""
echo "=== 步骤 2/7: 获取工作空间列表 ==="
WORKSPACES=$(curl -s "https://cnb.cool/workspace/list?slug=&branch=&page=1&page_size=20&status=" \
  -H "Accept: application/vnd.cnb.web+json" \
  -H "Cookie: $CNB_TOKEN")

echo "$WORKSPACES"
echo "(显示工作空间列表,如需停止请按 Ctrl+C)"

# ========== 步骤 3: 选择并启动工作空间 ==========
echo ""
echo "=== 步骤 3/7: 选择工作空间 ==="
RUNNING_SLUG=$(echo "$WORKSPACES" | grep -E '"status":"running"' -A2 | grep '"slug"' | head -1 | sed 's/.*"slug":"//;s/".*//')

if [ -n "$RUNNING_SLUG" ] && [ "$RUNNING_SLUG" != "null" ]; then
  SLUG="$RUNNING_SLUG"
  echo "✓ 选择运行中的工作空间: $SLUG"
else
  SLUG=$(echo "$WORKSPACES" | grep '"slug"' | head -1 | sed 's/.*"slug":"//;s/".*//')
  BRANCH=$(echo "$WORKSPACES" | grep '"branch"' | head -1 | sed 's/.*"branch":"//;s/".*//')
  if [ -z "$SLUG" ] || [ "$SLUG" = "null" ]; then
    echo "❌ 没有找到可用的工作空间"
    exit 1
  fi
  echo "✓ 选择工作空间: $SLUG(状态: 未运行)"

  echo ""
  echo "=== 步骤 4/7: 启动工作空间 ==="
  echo "正在启动..."
  START_RESULT=$(curl -s -X POST "https://cnb.cool/$SLUG/-/workspace/start" \
    -H "Accept: application/vnd.cnb.web+json" \
    -H "Content-Type: application/json" \
    -H "Cookie: $CNB_TOKEN" \
    -d "{\"branch\":\"$BRANCH\"}")

  echo "$START_RESULT"

  echo ""
  echo "=== 步骤 5/7: 等待工作空间就绪 ==="
  echo "等待工作空间启动(最多等待 120 秒)..."
  PIPELINE_ID=""
  for i in $(seq 1 120); do
    sleep 1
    STATUS_RESULT=$(curl -s "https://cnb.cool/$SLUG/-/workspace/status?sn=$SLUG" \
      -H "Accept: application/vnd.cnb.web+json" \
      -H "Cookie: $CNB_TOKEN")

    PIPELINE_ID=$(echo "$STATUS_RESULT" | grep -o '"pipelineId":"[^"]*"' | sed 's/"pipelineId":"//;s/"//')
    if [ -n "$PIPELINE_ID" ] && [ "$PIPELINE_ID" != "null" ] && [ "$PIPELINE_ID" != "" ]; then
      echo "✓ 工作空间已就绪,Pipeline ID: $PIPELINE_ID"
      break
    fi
    if [ $((i % 10)) -eq 0 ]; then
      echo "  等待中... ($i 秒)"
    fi
  done

  if [ -z "$PIPELINE_ID" ] || [ "$PIPELINE_ID" = "null" ] || [ "$PIPELINE_ID" = "" ]; then
    echo "⚠ 等待超时,尝试继续获取连接信息..."
  fi
fi

# ========== 步骤 6: 获取连接信息 ==========
echo ""
echo "=== 步骤 6/7: 获取连接信息 ==="
if [ -z "$PIPELINE_ID" ]; then
  PIPELINE_ID=$(echo "$WORKSPACES" | grep -E '"status":"running"' -A5 | grep '"pipeline_id"' | sed 's/.*"pipeline_id":"//;s/".*//')
fi
echo "Pipeline ID: $PIPELINE_ID"

SCHEMA=$(curl -s "https://cnb.cool/$SLUG/-/workspace/all-schema?pipelineId=$PIPELINE_ID" \
  -H "Accept: application/vnd.cnb.web+json" \
  -H "Cookie: $CNB_TOKEN")

echo "$SCHEMA"

REMOTE_SSH=$(echo "$SCHEMA" | grep -o '"remoteSsh":"[^"]*"' | sed 's/"remoteSsh":"//;s/"//')
CURSOR=$(echo "$SCHEMA" | grep -o '"cursor":"[^"]*"' | sed 's/"cursor":"//;s/"//')
VSCODE=$(echo "$SCHEMA" | grep -o '"vscode":"[^"]*"' | sed 's/"vscode":"//;s/"//')

if [ -z "$REMOTE_SSH" ] || [ "$REMOTE_SSH" = "null" ]; then
  echo "❌ 获取连接信息失败"
  echo "$SCHEMA" | grep -o '"message":"[^"]*"' | head -1 | sed 's/"message":"//;s/"//' 2>/dev/null || echo "未知错误"
  exit 1
fi

echo ""
echo "=== CNB 工作空间连接信息 ==="
echo "SSH: $REMOTE_SSH"
echo "Cursor: $CURSOR"
echo "VSCode: $VSCODE"
echo "✓ 连接信息获取成功"

# ========== 步骤 7: 保存终端配置 ==========
echo ""
echo "=== 步骤 7/7: 保存终端配置 ==="
USERNAME=$(echo "$REMOTE_SSH" | cut -d'@' -f1)
echo "用户名: $USERNAME"

EXISTING=$(curl -s "https://www.skillup.host/api/lae/api/office/doc/terminal?range=name:cnb" \
  -H "Authorization: Bearer {{AUTH}}")

EXISTING_ID=$(echo "$EXISTING" | grep -o '"_id":"[^"]*"' | head -1 | sed 's/"_id":"//;s/"//')

if [ -n "$EXISTING_ID" ] && [ "$EXISTING_ID" != "null" ]; then
  echo "更新现有 CNB 终端 (ID: $EXISTING_ID)..."
  SAVE_RESULT=$(curl -s -X POST "https://www.skillup.host/api/lae/api/office/doc/terminal" \
    -H "Authorization: Bearer {{AUTH}}" \
    -H "Content-Type: application/json" \
    -d "{\"_id\":\"$EXISTING_ID\",\"name\":\"cnb\",\"type\":2,\"host\":\"cnb.space\",\"port\":22,\"username\":\"$USERNAME\",\"auth_method\":2,\"visible_to_ai\":1}")
else
  echo "创建新的 CNB 终端..."
  SAVE_RESULT=$(curl -s -X POST "https://www.skillup.host/api/lae/api/office/doc/terminal" \
    -H "Authorization: Bearer {{AUTH}}" \
    -H "Content-Type: application/json" \
    -d "{\"name\":\"cnb\",\"agent_id\":1234567890,\"type\":2,\"host\":\"cnb.space\",\"port\":22,\"username\":\"$USERNAME\",\"auth_method\":2,\"visible_to_ai\":1}")
fi

echo "$SAVE_RESULT"

if echo "$SAVE_RESULT" | grep -q '"code":0\|"success":true'; then
  echo "✓ 终端配置保存成功"
else
  echo "⚠ 终端配置保存完成(请检查结果)"
fi

echo ""
echo "=== 完成 ==="
echo "您可以在终端列表中选择 'cnb' 进行连接"
echo ""
echo "可用连接命令: ssh $REMOTE_SSH"

参数

参数 说明
{{AUTH}} 系统自动注入,无需手动填写。AI 禁止擅自替换此占位符!

⚠️ AI 执行警告

  • {{AUTH}} 是系统占位符,禁止 AI 擅自替换
  • 执行时系统会自动注入正确的 JWT Token
  • AI 只能原样保留此占位符,不能用其他 token 值替换
  • 禁止擅自修改脚本内容,包括:
    • 禁止修改终端名称(如 name:cnb 改为其他名称)
    • 禁止修改 API 地址、参数等
    • 必须完全按照脚本原内容执行
  • 禁止跳过脚本步骤,包括:
    • 禁止跳过条件判断(如 if/else)
    • 禁止跳过循环等待(如轮询检查 status)
    • 必须严格按照脚本顺序执行每一步
    • 示例:保存终端前必须先查询是否存在,存在则更新,不存在则创建

执行结果

  • 成功: 保存终端配置并输出 SSH 连接信息
  • 失败: 输出错误原因

前置条件

  • 用户已在个人偏好中绑定 CNB 账号