@cloudbase/cloudbase-mcp 2.21.0 → 2.21.1-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,12 @@
1
- export const __webpack_id__ = 341;
2
- export const __webpack_ids__ = [341];
3
- export const __webpack_modules__ = {
1
+ import * as __WEBPACK_EXTERNAL_MODULE_express__ from "express";
2
+ import * as __WEBPACK_EXTERNAL_MODULE_open__ from "open";
3
+ import * as __WEBPACK_EXTERNAL_MODULE_ws__ from "ws";
4
+ export const __webpack_esm_id__ = 267;
5
+ export const __webpack_esm_ids__ = [267];
6
+ export const __webpack_esm_modules__ = {
4
7
 
5
- /***/ 2341:
6
- /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
8
+ /***/ 6267
9
+ (__unused_webpack_module, exports, __webpack_require__) {
7
10
 
8
11
 
9
12
  var __importDefault = (this && this.__importDefault) || function (mod) {
@@ -19,8 +22,8 @@ const http_1 = __importDefault(__webpack_require__(3782));
19
22
  const child_process_1 = __webpack_require__(5814);
20
23
  const open_1 = __importDefault(__webpack_require__(1622));
21
24
  const ws_1 = __webpack_require__(6220);
22
- const index_js_1 = __webpack_require__(9529);
23
- const logger_js_1 = __webpack_require__(3039);
25
+ const index_js_1 = __webpack_require__(9903);
26
+ const logger_js_1 = __webpack_require__(781);
24
27
  function isVSCodeEnvironment() {
25
28
  return Boolean(process.env.VSCODE_IPC_HOOK_CLI ||
26
29
  process.env.VSCODE_PID ||
@@ -2976,1388 +2979,1418 @@ async function getInteractiveServerSafe(mcpServer) {
2976
2979
  }
2977
2980
 
2978
2981
 
2979
- /***/ }),
2982
+ /***/ },
2980
2983
 
2981
- /***/ 4112:
2982
- /***/ ((__unused_webpack_module, exports) => {
2984
+ /***/ 4415
2985
+ (__unused_webpack_module, exports) {
2983
2986
 
2987
+ var __webpack_unused_export__;
2984
2988
 
2985
2989
  /**
2986
- * HTML template structure
2990
+ * Reusable UI components for env setup page
2987
2991
  */
2988
- Object.defineProperty(exports, "__esModule", ({ value: true }));
2989
- exports.buildHTMLPage = buildHTMLPage;
2990
- function buildHTMLPage(css, body, scripts) {
2992
+ __webpack_unused_export__ = ({ value: true });
2993
+ exports.renderHeader = renderHeader;
2994
+ exports.renderSearchBox = renderSearchBox;
2995
+ exports.renderEnvItem = renderEnvItem;
2996
+ exports.renderEmptyState = renderEmptyState;
2997
+ exports.renderNoResultsState = renderNoResultsState;
2998
+ exports.renderHelpLinks = renderHelpLinks;
2999
+ exports.renderActionButtons = renderActionButtons;
3000
+ exports.renderLoadingState = renderLoadingState;
3001
+ exports.renderSuccessState = renderSuccessState;
3002
+ exports.renderErrorBanner = renderErrorBanner;
3003
+ function renderHeader(accountInfo, ide) {
3004
+ const hasAccount = !!accountInfo?.uin;
3005
+ const isCodeBuddy = ide === "CodeBuddy";
2991
3006
  return `
2992
- <!DOCTYPE html>
2993
- <html lang="zh-CN">
2994
- <head>
2995
- <meta charset="UTF-8">
2996
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
2997
- <title>CloudBase MCP - 环境配置</title>
2998
- ${css}
2999
- </head>
3000
- <body>
3001
- ${body}
3002
- ${scripts}
3003
- </body>
3004
- </html>
3007
+ <div class="header">
3008
+ <div class="header-left">
3009
+ <img class="logo" src="https://7463-tcb-advanced-a656fc-1257967285.tcb.qcloud.la/mcp/cloudbase-logo.svg" alt="CloudBase Logo" />
3010
+ <span class="title">CloudBase</span>
3011
+ </div>
3012
+ ${(hasAccount && accountInfo.region !== 'ap-singapore') ? /** 国际站不支持切 */ `
3013
+ <div class="header-right">
3014
+ <div class="account-section">
3015
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
3016
+ <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/>
3017
+ <circle cx="12" cy="7" r="4"/>
3018
+ </svg>
3019
+ <span class="account-uin">${accountInfo.uin}</span>
3020
+ ${accountInfo.region ? `<span class="account-region">${accountInfo.region}</span>` : ''}
3021
+ ${!isCodeBuddy ? `
3022
+ <button class="btn-switch" onclick="switchAccount()" title="切换账号">
3023
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
3024
+ <path d="M17 2l4 4-4 4M7 22l-4-4 4-4M21 6H10M3 18h11"/>
3025
+ </svg>
3026
+ </button>
3027
+ ` : ''}
3028
+ </div>
3029
+ </div>
3030
+ ` : ''}
3031
+ </div>
3005
3032
  `.trim();
3006
3033
  }
3034
+ function renderSearchBox() {
3035
+ return `
3036
+ <div class="search-section">
3037
+ <div class="search-box">
3038
+ <svg class="search-icon" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
3039
+ <circle cx="11" cy="11" r="8"/>
3040
+ <path d="m21 21-4.35-4.35"/>
3041
+ </svg>
3042
+ <input
3043
+ type="text"
3044
+ id="searchInput"
3045
+ class="search-input"
3046
+ placeholder="搜索环境名称或 ID..."
3047
+ oninput="filterEnvs(this.value)"
3048
+ />
3049
+ <button class="search-clear" onclick="clearSearch()" id="searchClear" style="display: none;">
3050
+ <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
3051
+ <path d="M18 6L6 18M6 6l12 12"/>
3052
+ </svg>
3053
+ </button>
3054
+ </div>
3055
+ <div class="search-actions">
3056
+ <button class="btn-action" onclick="createNewEnv()" title="新建环境">
3057
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
3058
+ <path d="M12 5v14M5 12h14"/>
3059
+ </svg>
3060
+ <span class="btn-text">新建环境</span>
3061
+ </button>
3062
+ <button class="btn-action" onclick="refreshEnvList()" title="刷新环境列表">
3063
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
3064
+ <path d="M21.5 2v6h-6M2.5 22v-6h6M2 11.5a10 10 0 0 1 18.8-4.3M22 12.5a10 10 0 0 1-18.8 4.2"/>
3065
+ </svg>
3066
+ </button>
3067
+ </div>
3068
+ </div>
3069
+ `.trim();
3070
+ }
3071
+ function renderEnvItem(env, index) {
3072
+ const alias = env.Alias || '(未命名)';
3073
+ const envId = env.EnvId;
3074
+ const hasAlias = !!env.Alias;
3075
+ return `
3076
+ <div class="env-item" onclick="selectEnv('${envId}', this)">
3077
+ <div class="env-info">
3078
+ <div class="env-name ${!hasAlias ? 'unnamed' : ''}">${alias}</div>
3079
+ <div class="env-id">${envId}</div>
3080
+ </div>
3081
+ </div>
3082
+ `.trim();
3083
+ }
3084
+ function renderEmptyState(hasInitError) {
3085
+ return `
3086
+ <div class="empty-state">
3087
+ <p class="empty-message">
3088
+ 暂无环境,请先<a href="https://buy.cloud.tencent.com/lowcode?buyType=tcb&channel=mcp" onclick="openUrl(event, 'https://buy.cloud.tencent.com/lowcode?buyType=tcb&channel=mcp'); return false;" class="create-env-link">创建环境</a>,然后点击刷新按钮重试
3089
+ </p>
3090
+ </div>
3091
+ `.trim();
3092
+ }
3093
+ function renderNoResultsState() {
3094
+ return `
3095
+ <div class="empty-state" id="noResults" style="display: none;">
3096
+ <svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="opacity: 0.3;">
3097
+ <circle cx="11" cy="11" r="8"/>
3098
+ <path d="m21 21-4.35-4.35"/>
3099
+ </svg>
3100
+ <p class="empty-message">未找到匹配的环境</p>
3101
+ </div>
3102
+ `.trim();
3103
+ }
3104
+ function renderHelpLinks() {
3105
+ return `
3106
+ <div class="help-links">
3107
+ <a href="https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/" onclick="openUrl(event, 'https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/'); return false;" class="help-link">
3108
+ <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
3109
+ <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
3110
+ <polyline points="14 2 14 8 20 8"/>
3111
+ <line x1="16" y1="13" x2="8" y2="13"/>
3112
+ <line x1="16" y1="17" x2="8" y2="17"/>
3113
+ </svg>
3114
+ 帮助文档
3115
+ </a>
3116
+ <a href="https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/tutorials" onclick="openUrl(event, 'https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/tutorials'); return false;" class="help-link">
3117
+ <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
3118
+ <polygon points="23 7 16 12 23 17 23 7"/>
3119
+ <rect x="1" y="5" width="15" height="14" rx="2" ry="2"/>
3120
+ </svg>
3121
+ 视频教程
3122
+ </a>
3123
+ <a href="https://github.com/TencentCloudBase/CloudBase-AI-ToolKit" onclick="openUrl(event, 'https://github.com/TencentCloudBase/CloudBase-AI-ToolKit'); return false;" class="help-link">
3124
+ <svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor">
3125
+ <path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
3126
+ </svg>
3127
+ GitHub
3128
+ </a>
3129
+ </div>
3130
+ `.trim();
3131
+ }
3132
+ function renderActionButtons(hasEnvs, hasInitError) {
3133
+ return `
3134
+ <div class="actions">
3135
+ <button class="btn btn-secondary" onclick="cancel()">
3136
+ <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
3137
+ <path d="M18 6L6 18M6 6l12 12"/>
3138
+ </svg>
3139
+ 取消
3140
+ </button>
3141
+ <button class="btn btn-primary" id="confirmBtn" onclick="confirm()" disabled>
3142
+ <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
3143
+ <path d="M20 6L9 17l-5-5"/>
3144
+ </svg>
3145
+ 确认选择
3146
+ </button>
3147
+ </div>
3148
+ `.trim();
3149
+ }
3150
+ function renderLoadingState() {
3151
+ return `
3152
+ <div class="loading" id="loading" style="display: none;">
3153
+ <div class="spinner"></div>
3154
+ <span>正在配置环境...</span>
3155
+ </div>
3156
+ `.trim();
3157
+ }
3158
+ function renderSuccessState() {
3159
+ return `
3160
+ <div class="success-state" id="successState" style="display: none;">
3161
+ <div class="success-icon">
3162
+ <svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
3163
+ <path d="M20 6L9 17l-5-5"/>
3164
+ </svg>
3165
+ </div>
3166
+ <h2 class="success-title">环境配置成功!</h2>
3167
+ <p class="success-message">已成功选择 CloudBase 环境</p>
3168
+ <div class="selected-env-info">
3169
+ <span class="env-label">环境 ID:</span>
3170
+ <span class="env-value" id="selectedEnvDisplay"></span>
3171
+ </div>
3172
+ </div>
3173
+ `.trim();
3174
+ }
3175
+ function renderErrorBanner(errorContext, sessionId) {
3176
+ const initTcbError = errorContext?.initTcbError;
3177
+ const createEnvError = errorContext?.createEnvError;
3178
+ // Only show initTcbError, hide createEnvError
3179
+ if (!initTcbError) {
3180
+ return '';
3181
+ }
3182
+ return `
3183
+ <div class="info-banner" id="errorBanner">
3184
+ ${initTcbError ? `
3185
+ <div class="info-item">
3186
+ <div class="info-header">
3187
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
3188
+ <circle cx="12" cy="12" r="10"/>
3189
+ <line x1="12" y1="8" x2="12" y2="12"/>
3190
+ <line x1="12" y1="16" x2="12.01" y2="16"/>
3191
+ </svg>
3192
+ <span class="info-title">${escapeHtml(initTcbError.message)}</span>
3193
+ </div>
3194
+ <div class="info-message">${escapeHtml(initTcbError.actionText || '')}</div>
3195
+ ${initTcbError.requestId ? `
3196
+ <div class="info-details">
3197
+ <span class="detail-label">错误码:</span> <span class="detail-value">${escapeHtml(initTcbError.code)}</span>
3198
+ <span class="detail-label">请求 ID:</span> <span class="detail-value">${escapeHtml(initTcbError.requestId)}</span>
3199
+ </div>
3200
+ ` : ''}
3201
+ ${initTcbError.needRealNameAuth ? `
3202
+ <div class="error-action">
3203
+ <a href="${initTcbError.helpUrl || 'https://buy.cloud.tencent.com/lowcode?buyType=tcb&channel=mcp'}" onclick="openUrl(event, '${initTcbError.helpUrl || 'https://buy.cloud.tencent.com/lowcode?buyType=tcb&channel=mcp'}'); return false;" class="error-link">
3204
+ 前往实名认证
3205
+ </a>
3206
+ </div>
3207
+ ` : ''}
3208
+ ${initTcbError.needCamAuth ? `
3209
+ <div class="error-action">
3210
+ <a href="${initTcbError.helpUrl || 'https://buy.cloud.tencent.com/lowcode?buyType=tcb&channel=mcp'}" onclick="openUrl(event, '${initTcbError.helpUrl || 'https://buy.cloud.tencent.com/lowcode?buyType=tcb&channel=mcp'}'); return false;" class="error-link">
3211
+ 前往开通 CloudBase 服务
3212
+ </a>
3213
+ ${sessionId ? `
3214
+ <button class="error-link error-retry-btn" onclick="retryInitTcb('${sessionId}')">
3215
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
3216
+ <path d="M23 4v6h-6M1 20v-6h6M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/>
3217
+ </svg>
3218
+ 重试
3219
+ </button>
3220
+ ` : ''}
3221
+ </div>
3222
+ ` : ''}
3223
+ ${!initTcbError.needRealNameAuth && !initTcbError.needCamAuth && initTcbError.helpUrl ? `
3224
+ <div class="error-action">
3225
+ <a href="${initTcbError.helpUrl}" onclick="openUrl(event, '${initTcbError.helpUrl}'); return false;" class="error-link">
3226
+ 前往开通 CloudBase 服务
3227
+ </a>
3228
+ ${sessionId ? `
3229
+ <button class="error-link error-retry-btn" onclick="retryInitTcb('${sessionId}')">
3230
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
3231
+ <path d="M23 4v6h-6M1 20v-6h6M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/>
3232
+ </svg>
3233
+ 重试
3234
+ </button>
3235
+ ` : ''}
3236
+ </div>
3237
+ ` : ''}
3238
+ </div>
3239
+ ` : ''}
3240
+ </div>
3241
+ `.trim();
3242
+ }
3243
+ // Helper function to escape HTML
3244
+ function escapeHtml(text) {
3245
+ const map = {
3246
+ '&': '&amp;',
3247
+ '<': '&lt;',
3248
+ '>': '&gt;',
3249
+ '"': '&quot;',
3250
+ "'": '&#039;'
3251
+ };
3252
+ return text.replace(/[&<>"']/g, (m) => map[m]);
3253
+ }
3007
3254
 
3008
3255
 
3009
- /***/ }),
3010
-
3011
- /***/ 6975:
3012
- /***/ ((__unused_webpack_module, exports) => {
3013
-
3014
-
3015
- /**
3016
- * CSS styles for env setup page
3017
- */
3018
- Object.defineProperty(exports, "__esModule", ({ value: true }));
3019
- exports.CSS_STYLES = void 0;
3020
- exports.CSS_STYLES = `
3021
- <style>
3022
- @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&display=swap');
3023
-
3024
- * { margin: 0; padding: 0; box-sizing: border-box; }
3025
-
3026
- :root {
3027
- --primary-color: #1a1a1a;
3028
- --primary-hover: #000000;
3029
- --accent-color: #67E9E9;
3030
- --accent-hover: #2BCCCC;
3031
- --text-primary: #ffffff;
3032
- --text-secondary: #a0a0a0;
3033
- --border-color: rgba(255, 255, 255, 0.15);
3034
- --bg-secondary: rgba(255, 255, 255, 0.08);
3035
- --bg-glass: rgba(26, 26, 26, 0.95);
3036
- --shadow: 0 25px 50px rgba(0, 0, 0, 0.3), 0 10px 20px rgba(0, 0, 0, 0.2);
3037
- --font-mono: 'JetBrains Mono', 'SF Mono', 'Monaco', monospace;
3038
- --header-bg: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 50%, #0d1117 100%);
3039
- }
3040
-
3041
- body {
3042
- font-family: var(--font-mono);
3043
- background: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 100%);
3044
- min-height: 100vh;
3045
- display: flex;
3046
- align-items: center;
3047
- justify-content: center;
3048
- padding: 20px;
3049
- position: relative;
3050
- overflow-x: hidden;
3051
- overflow-y: auto;
3052
- }
3053
-
3054
- /* Custom scrollbar styles */
3055
- ::-webkit-scrollbar {
3056
- width: 8px;
3057
- }
3058
-
3059
- ::-webkit-scrollbar-track {
3060
- background: rgba(255, 255, 255, 0.05);
3061
- border-radius: 4px;
3062
- }
3063
-
3064
- ::-webkit-scrollbar-thumb {
3065
- background: var(--accent-color);
3066
- border-radius: 4px;
3067
- }
3068
-
3069
- ::-webkit-scrollbar-thumb:hover {
3070
- background: var(--accent-hover);
3071
- }
3072
-
3073
- body::before {
3074
- content: '';
3075
- position: fixed;
3076
- top: 0; left: 0; right: 0; bottom: 0;
3077
- background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grid" width="20" height="20" patternUnits="userSpaceOnUse"><path d="M 20 0 L 0 0 0 20" fill="none" stroke="rgba(255,255,255,0.02)" stroke-width="1"/></pattern></defs><rect width="100" height="100" fill="url(%23grid)"/></svg>') repeat;
3078
- pointer-events: none;
3079
- z-index: -1;
3080
- }
3081
-
3082
- body::after {
3083
- content: '';
3084
- position: fixed;
3085
- top: 50%; left: 50%;
3086
- width: 500px; height: 500px;
3087
- background: radial-gradient(circle, rgba(103, 233, 233, 0.05) 0%, transparent 70%);
3088
- transform: translate(-50%, -50%);
3089
- pointer-events: none;
3090
- z-index: -1;
3091
- animation: pulse 8s ease-in-out infinite;
3092
- }
3093
-
3094
- @keyframes pulse {
3095
- 0%, 100% { opacity: 0.3; transform: translate(-50%, -50%) scale(1); }
3096
- 50% { opacity: 0.6; transform: translate(-50%, -50%) scale(1.1); }
3097
- }
3098
-
3099
- .modal {
3100
- background: var(--bg-glass);
3101
- backdrop-filter: blur(20px);
3102
- border-radius: 20px;
3103
- box-shadow: var(--shadow);
3104
- border: 1px solid var(--border-color);
3105
- width: 100%;
3106
- max-width: 640px;
3107
- overflow: hidden;
3108
- animation: modalIn 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275);
3109
- position: relative;
3110
- }
3111
-
3112
- .modal::before {
3113
- content: '';
3114
- position: absolute;
3115
- top: 0; left: 0; right: 0; bottom: 0;
3116
- background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.02) 50%, transparent 70%);
3117
- animation: shimmer 3s infinite;
3118
- pointer-events: none;
3119
- }
3120
-
3121
- @keyframes shimmer {
3122
- 0% { transform: translateX(-100%); }
3123
- 100% { transform: translateX(100%); }
3124
- }
3125
-
3126
- @keyframes modalIn {
3127
- from {
3128
- opacity: 0;
3129
- transform: scale(0.9) translateY(-20px);
3130
- }
3131
- to {
3132
- opacity: 1;
3133
- transform: scale(1) translateY(0);
3134
- }
3135
- }
3136
-
3137
- .header {
3138
- background: var(--header-bg);
3139
- color: var(--text-primary);
3140
- padding: 20px 32px;
3141
- display: flex;
3142
- align-items: center;
3143
- justify-content: space-between;
3144
- position: relative;
3145
- overflow: hidden;
3146
- }
3147
-
3148
- .header::before {
3149
- content: '';
3150
- position: absolute;
3151
- top: 0; left: 0; right: 0; bottom: 0;
3152
- background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.03) 50%, transparent 70%);
3153
- animation: headerShimmer 4s infinite;
3154
- pointer-events: none;
3155
- }
3156
-
3157
- @keyframes headerShimmer {
3158
- 0% { transform: translateX(-100%); }
3159
- 100% { transform: translateX(100%); }
3160
- }
3161
-
3162
- .header-left {
3163
- display: flex;
3164
- align-items: center;
3165
- gap: 16px;
3166
- z-index: 1;
3167
- }
3168
-
3169
- .logo {
3170
- width: 32px;
3171
- height: 32px;
3172
- filter: drop-shadow(0 4px 8px rgba(0,0,0,0.2));
3173
- animation: logoFloat 3s ease-in-out infinite;
3174
- }
3175
-
3176
- @keyframes logoFloat {
3177
- 0%, 100% { transform: translateY(0px); }
3178
- 50% { transform: translateY(-3px); }
3179
- }
3180
-
3181
- .title {
3182
- font-size: 18px;
3183
- font-weight: 600;
3184
- text-shadow: 0 2px 4px rgba(0,0,0,0.1);
3185
- }
3186
-
3187
- .header-right {
3188
- display: flex;
3189
- align-items: center;
3190
- gap: 16px;
3191
- z-index: 1;
3192
- }
3193
-
3194
- .account-section {
3195
- display: flex;
3196
- align-items: center;
3197
- gap: 8px;
3198
- padding: 6px 12px;
3199
- background: rgba(255, 255, 255, 0.04);
3200
- border: 1px solid var(--border-color);
3201
- border-radius: 8px;
3202
- }
3203
-
3204
- .account-uin {
3205
- font-size: 12px;
3206
- color: var(--text-secondary);
3207
- font-family: var(--font-mono);
3208
- }
3209
-
3210
- .btn-switch {
3211
- display: flex;
3212
- align-items: center;
3213
- justify-content: center;
3214
- padding: 4px;
3215
- background: transparent;
3216
- border: none;
3217
- color: var(--text-secondary);
3218
- cursor: pointer;
3219
- transition: all 0.3s ease;
3220
- border-radius: 4px;
3221
- }
3222
-
3223
- .btn-switch:hover {
3224
- background: rgba(255, 255, 255, 0.1);
3225
- color: var(--accent-color);
3226
- }
3227
-
3228
- .btn-icon-link {
3229
- display: flex;
3230
- align-items: center;
3231
- justify-content: center;
3232
- padding: 7px;
3233
- background: transparent;
3234
- border: 1px solid var(--border-color);
3235
- border-radius: 8px;
3236
- color: var(--text-primary);
3237
- cursor: pointer;
3238
- transition: all 0.3s ease;
3239
- text-decoration: none;
3240
- }
3256
+ /***/ },
3241
3257
 
3242
- .btn-icon-link:hover {
3243
- background: rgba(255, 255, 255, 0.08);
3244
- border-color: var(--accent-color);
3245
- }
3258
+ /***/ 4182
3259
+ (__unused_webpack_module, exports) {
3246
3260
 
3247
- .content {
3248
- padding: 32px 32px 28px;
3249
- }
3261
+ var __webpack_unused_export__;
3250
3262
 
3251
- .content-title {
3252
- font-size: 20px;
3253
- font-weight: 600;
3254
- color: var(--text-primary);
3255
- margin-bottom: 28px;
3256
- text-align: center;
3257
- letter-spacing: -0.01em;
3258
- }
3259
-
3260
- /* Search section styles */
3261
- .search-section {
3262
- display: flex;
3263
- gap: 10px;
3264
- margin-bottom: 24px;
3265
- }
3266
-
3267
- .search-box {
3268
- position: relative;
3269
- flex: 1;
3270
- }
3271
-
3272
- .search-icon {
3273
- position: absolute;
3274
- left: 14px;
3275
- top: 50%;
3276
- transform: translateY(-50%);
3277
- color: var(--text-secondary);
3278
- pointer-events: none;
3279
- z-index: 1;
3280
- }
3281
-
3282
- .search-input {
3283
- width: 100%;
3284
- padding: 11px 38px 11px 38px;
3285
- background: var(--bg-secondary);
3286
- border: 1px solid var(--border-color);
3287
- border-radius: 10px;
3288
- color: var(--text-primary);
3289
- font-size: 13px;
3290
- font-family: var(--font-mono);
3291
- transition: all 0.3s ease;
3292
- }
3263
+ /**
3264
+ * HTML template structure
3265
+ */
3266
+ __webpack_unused_export__ = ({ value: true });
3267
+ exports.buildHTMLPage = buildHTMLPage;
3268
+ function buildHTMLPage(css, body, scripts) {
3269
+ return `
3270
+ <!DOCTYPE html>
3271
+ <html lang="zh-CN">
3272
+ <head>
3273
+ <meta charset="UTF-8">
3274
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
3275
+ <title>CloudBase MCP - 环境配置</title>
3276
+ ${css}
3277
+ </head>
3278
+ <body>
3279
+ ${body}
3280
+ ${scripts}
3281
+ </body>
3282
+ </html>
3283
+ `.trim();
3284
+ }
3293
3285
 
3294
- .search-input:focus {
3295
- outline: none;
3296
- border-color: var(--accent-color);
3297
- background: rgba(255, 255, 255, 0.1);
3298
- box-shadow: 0 0 0 3px rgba(103, 233, 233, 0.08);
3299
- }
3300
3286
 
3301
- .search-input::placeholder {
3302
- color: var(--text-secondary);
3303
- opacity: 0.6;
3304
- }
3287
+ /***/ },
3305
3288
 
3306
- .search-clear {
3307
- position: absolute;
3308
- right: 12px;
3309
- top: 50%;
3310
- transform: translateY(-50%);
3311
- background: transparent;
3312
- border: none;
3313
- color: var(--text-secondary);
3314
- cursor: pointer;
3315
- padding: 4px;
3316
- display: flex;
3317
- align-items: center;
3318
- justify-content: center;
3319
- border-radius: 4px;
3320
- transition: all 0.3s ease;
3321
- z-index: 1;
3322
- }
3289
+ /***/ 9903
3290
+ (__unused_webpack_module, exports, __webpack_require__) {
3323
3291
 
3324
- .search-clear:hover {
3325
- color: var(--text-primary);
3326
- background: rgba(255, 255, 255, 0.1);
3327
- }
3292
+ var __webpack_unused_export__;
3328
3293
 
3329
- .search-actions {
3330
- display: flex;
3331
- gap: 8px;
3332
- }
3294
+ /**
3295
+ * Main renderer for env setup page
3296
+ */
3297
+ __webpack_unused_export__ = ({ value: true });
3298
+ exports.renderEnvSetupPage = renderEnvSetupPage;
3299
+ const components_js_1 = __webpack_require__(4415);
3300
+ const html_js_1 = __webpack_require__(4182);
3301
+ const scripts_js_1 = __webpack_require__(7335);
3302
+ const styles_js_1 = __webpack_require__(7373);
3303
+ /**
3304
+ * Render the complete env setup page
3305
+ */
3306
+ function renderEnvSetupPage(options) {
3307
+ const { envs = [], accountInfo, errorContext, sessionId, wsPort, ide } = options;
3308
+ const hasEnvs = envs.length > 0;
3309
+ const hasInitError = !!errorContext?.initTcbError;
3310
+ const hasErrors = !!(errorContext?.initTcbError || errorContext?.createEnvError);
3311
+ // Build env list HTML
3312
+ let envListHTML = '';
3313
+ if (hasEnvs) {
3314
+ envListHTML = `
3315
+ ${(0, components_js_1.renderSearchBox)()}
3316
+ <div class="env-list" id="envList">
3317
+ ${envs.map((env, index) => (0, components_js_1.renderEnvItem)(env, index)).join('\n')}
3318
+ </div>
3319
+ ${(0, components_js_1.renderNoResultsState)()}
3320
+ `;
3321
+ }
3322
+ else {
3323
+ // 暂无环境时也显示搜索框、新建和刷新按钮
3324
+ envListHTML = `
3325
+ ${(0, components_js_1.renderSearchBox)()}
3326
+ <div class="env-list" id="envList">
3327
+ ${(0, components_js_1.renderEmptyState)(hasInitError)}
3328
+ </div>
3329
+ ${(0, components_js_1.renderNoResultsState)()}
3330
+ `;
3331
+ }
3332
+ // Build body HTML
3333
+ const bodyHTML = `
3334
+ <div class="modal">
3335
+ ${(0, components_js_1.renderHeader)(accountInfo, ide)}
3336
+ <div class="content">
3337
+ <h1 class="content-title">选择环境</h1>
3338
+
3339
+ ${hasErrors ? (0, components_js_1.renderErrorBanner)(errorContext, sessionId) : ''}
3340
+
3341
+ ${envListHTML}
3342
+
3343
+ ${(0, components_js_1.renderActionButtons)(hasEnvs, hasInitError)}
3344
+
3345
+ ${(0, components_js_1.renderHelpLinks)()}
3346
+
3347
+ ${(0, components_js_1.renderLoadingState)()}
3348
+
3349
+ ${(0, components_js_1.renderSuccessState)()}
3350
+ </div>
3351
+ </div>
3352
+ `;
3353
+ // Get JavaScript with WebSocket port
3354
+ const scripts = (0, scripts_js_1.getJavaScripts)(wsPort);
3355
+ // Assemble final HTML
3356
+ return (0, html_js_1.buildHTMLPage)(styles_js_1.CSS_STYLES, bodyHTML, scripts);
3357
+ }
3333
3358
 
3334
- .btn-action {
3335
- display: flex;
3336
- align-items: center;
3337
- justify-content: center;
3338
- gap: 6px;
3339
- padding: 11px 14px;
3340
- background: var(--bg-secondary);
3341
- border: 1px solid var(--border-color);
3342
- border-radius: 10px;
3343
- color: var(--text-secondary);
3344
- cursor: pointer;
3345
- transition: all 0.3s ease;
3346
- }
3347
3359
 
3348
- .btn-action:hover {
3349
- background: rgba(255, 255, 255, 0.1);
3350
- border-color: rgba(103, 233, 233, 0.5);
3351
- color: var(--accent-color);
3352
- }
3360
+ /***/ },
3353
3361
 
3354
- .btn-action:active {
3355
- transform: scale(0.95);
3356
- }
3362
+ /***/ 7335
3363
+ (__unused_webpack_module, exports) {
3357
3364
 
3358
- .btn-text {
3359
- font-size: 13px;
3360
- font-weight: 500;
3361
- }
3365
+ var __webpack_unused_export__;
3362
3366
 
3363
- .env-list {
3364
- max-height: 340px;
3365
- overflow-y: auto;
3366
- padding-right: 6px;
3367
- margin-bottom: 24px;
3368
- }
3367
+ /**
3368
+ * JavaScript logic for env setup page
3369
+ */
3370
+ __webpack_unused_export__ = ({ value: true });
3371
+ exports.getJavaScripts = getJavaScripts;
3372
+ function getJavaScripts(wsPort) {
3373
+ return `
3374
+ <script>
3375
+ let selectedEnvId = null;
3369
3376
 
3370
- .env-list::-webkit-scrollbar {
3371
- width: 5px;
3377
+ // Select environment
3378
+ function selectEnv(envId, element) {
3379
+ console.log('[env-setup] Selecting environment:', envId);
3380
+ selectedEnvId = envId;
3381
+
3382
+ // Remove selected class from all items
3383
+ document.querySelectorAll('.env-item').forEach(item => {
3384
+ item.classList.remove('selected');
3385
+ });
3386
+
3387
+ // Add selected class to current item
3388
+ element.classList.add('selected');
3389
+
3390
+ // Enable confirm button
3391
+ document.getElementById('confirmBtn').disabled = false;
3372
3392
  }
3373
3393
 
3374
- .env-list::-webkit-scrollbar-track {
3375
- background: transparent;
3394
+ // Filter environments
3395
+ function filterEnvs(searchTerm) {
3396
+ const items = document.querySelectorAll('.env-item');
3397
+ const searchClear = document.getElementById('searchClear');
3398
+ let visibleCount = 0;
3399
+
3400
+ items.forEach(item => {
3401
+ const name = item.querySelector('.env-name').textContent.toLowerCase();
3402
+ const id = item.querySelector('.env-id').textContent.toLowerCase();
3403
+ const match = name.includes(searchTerm.toLowerCase()) ||
3404
+ id.includes(searchTerm.toLowerCase());
3405
+
3406
+ item.style.display = match ? 'flex' : 'none';
3407
+ if (match) visibleCount++;
3408
+ });
3409
+
3410
+ // Show/hide clear button
3411
+ if (searchClear) {
3412
+ searchClear.style.display = searchTerm ? 'flex' : 'none';
3413
+ }
3414
+
3415
+ // Show/hide no results message
3416
+ const noResults = document.getElementById('noResults');
3417
+ if (noResults) {
3418
+ const hasItems = items.length > 0;
3419
+ noResults.style.display = visibleCount === 0 && hasItems ? 'block' : 'none';
3420
+ }
3376
3421
  }
3377
3422
 
3378
- .env-list::-webkit-scrollbar-thumb {
3379
- background: var(--accent-color);
3380
- border-radius: 3px;
3423
+ // Clear search
3424
+ function clearSearch() {
3425
+ const searchInput = document.getElementById('searchInput');
3426
+ if (searchInput) {
3427
+ searchInput.value = '';
3428
+ filterEnvs('');
3429
+ searchInput.focus();
3430
+ }
3381
3431
  }
3382
3432
 
3383
- /* Env item styles */
3384
- .env-item {
3385
- display: flex;
3386
- align-items: center;
3387
- gap: 14px;
3388
- padding: 14px 16px;
3389
- background: var(--bg-secondary);
3390
- border: 1px solid var(--border-color);
3391
- border-radius: 10px;
3392
- margin-bottom: 10px;
3393
- cursor: pointer;
3394
- transition: all 0.3s ease;
3395
- position: relative;
3396
- }
3433
+ // WebSocket: same host as page so it works in remote VS Code / Cloud IDE (no localhost)
3434
+ const wsScheme = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
3435
+ const wsUrl = wsScheme + '//' + window.location.host;
3436
+ const ws = new WebSocket(wsUrl);
3437
+
3438
+ ws.onopen = () => {
3439
+ console.log('[env-setup] WebSocket connected');
3440
+ // Send session ID to server to associate this WebSocket with the session
3441
+ const sessionId = window.location.pathname.split('/').pop();
3442
+ ws.send(JSON.stringify({
3443
+ type: 'registerSession',
3444
+ sessionId: sessionId
3445
+ }));
3446
+ };
3447
+
3448
+ ws.onmessage = (event) => {
3449
+ const data = JSON.parse(event.data);
3450
+ console.log('[env-setup] Received message:', data);
3451
+
3452
+ if (data.type === 'success' && data.envId) {
3453
+ showSuccess(data.envId);
3454
+ } else if (data.type === 'envListRefreshed') {
3455
+ if (data.success) {
3456
+ console.log('[env-setup] Environment list refreshed, reloading page');
3457
+ // Reload the page to show updated environment list
3458
+ window.location.reload();
3459
+ } else {
3460
+ console.error('[env-setup] Failed to refresh environment list:', data.error);
3461
+ alert('刷新环境列表失败: ' + (data.error || '未知错误'));
3462
+ }
3463
+ }
3464
+ };
3397
3465
 
3398
- .env-item:hover {
3399
- background: rgba(255, 255, 255, 0.1);
3400
- border-color: rgba(103, 233, 233, 0.5);
3401
- transform: translateX(2px);
3402
- }
3466
+ ws.onerror = (error) => {
3467
+ console.error('[env-setup] WebSocket error:', error);
3468
+ };
3403
3469
 
3404
- .env-item.selected {
3405
- background: rgba(103, 233, 233, 0.12);
3406
- border-color: var(--accent-color);
3407
- box-shadow: 0 0 0 1px rgba(103, 233, 233, 0.2);
3408
- }
3470
+ ws.onclose = () => {
3471
+ console.log('[env-setup] WebSocket closed');
3472
+ };
3409
3473
 
3410
- .env-item.selected::after {
3411
- content: '';
3412
- position: absolute;
3413
- right: 16px;
3414
- top: 50%;
3415
- transform: translateY(-50%);
3416
- width: 6px;
3417
- height: 6px;
3418
- background: var(--accent-color);
3419
- border-radius: 50%;
3420
- box-shadow: 0 0 8px var(--accent-color);
3474
+ // Show success state
3475
+ function showSuccess(envId) {
3476
+ document.querySelector('.content').style.display = 'none';
3477
+ const successState = document.getElementById('successState');
3478
+ const selectedEnvDisplay = document.getElementById('selectedEnvDisplay');
3479
+
3480
+ if (successState && selectedEnvDisplay) {
3481
+ selectedEnvDisplay.textContent = envId;
3482
+ successState.style.display = 'block';
3483
+ }
3421
3484
  }
3422
3485
 
3423
- .env-info {
3424
- flex: 1;
3425
- min-width: 0;
3486
+ // Confirm selection
3487
+ function confirm() {
3488
+ if (!selectedEnvId) {
3489
+ console.warn('[env-setup] No environment selected');
3490
+ return;
3491
+ }
3492
+
3493
+ console.log('[env-setup] Confirming selection:', selectedEnvId);
3494
+
3495
+ if (ws.readyState === WebSocket.OPEN) {
3496
+ ws.send(JSON.stringify({
3497
+ type: 'envId',
3498
+ data: selectedEnvId,
3499
+ cancelled: false
3500
+ }));
3501
+
3502
+ // Close window immediately after sending confirmation
3503
+ setTimeout(() => {
3504
+ window.close();
3505
+ }, 100);
3506
+ } else {
3507
+ console.error('[env-setup] WebSocket not connected');
3508
+ alert('连接已断开,请刷新页面重试');
3509
+ }
3426
3510
  }
3427
3511
 
3428
- .env-name {
3429
- font-size: 15px;
3430
- font-weight: 500;
3431
- color: var(--text-primary);
3432
- margin-bottom: 5px;
3433
- overflow: hidden;
3434
- text-overflow: ellipsis;
3435
- white-space: nowrap;
3436
- letter-spacing: -0.01em;
3512
+ // Cancel
3513
+ function cancel() {
3514
+ console.log('[env-setup] Cancelling');
3515
+ if (ws.readyState === WebSocket.OPEN) {
3516
+ ws.send(JSON.stringify({
3517
+ type: 'envId',
3518
+ data: null,
3519
+ cancelled: true
3520
+ }));
3521
+
3522
+ // Close window immediately after sending cancellation
3523
+ setTimeout(() => {
3524
+ window.close();
3525
+ }, 100);
3526
+ }
3437
3527
  }
3438
3528
 
3439
- .env-name.unnamed {
3440
- opacity: 0.5;
3529
+ // Switch account
3530
+ function switchAccount() {
3531
+ console.log('[env-setup] Switching account');
3532
+ if (ws.readyState === WebSocket.OPEN) {
3533
+ ws.send(JSON.stringify({
3534
+ type: 'envId',
3535
+ data: null,
3536
+ switch: true
3537
+ }));
3538
+
3539
+ // Close window immediately after sending switch request
3540
+ setTimeout(() => {
3541
+ window.close();
3542
+ }, 100);
3543
+ }
3441
3544
  }
3442
3545
 
3443
- .env-id {
3444
- font-size: 11px;
3445
- color: var(--text-secondary);
3446
- font-family: var(--font-mono);
3447
- word-break: break-all;
3448
- opacity: 0.8;
3546
+ // Universal URL opener - works with all IDEs including CodeBuddy
3547
+ async function openUrl(event, url) {
3548
+ if (event) {
3549
+ event.preventDefault();
3550
+ }
3551
+
3552
+ console.log('[env-setup] Opening URL:', url);
3553
+
3554
+ try {
3555
+ const response = await fetch('/api/open-url', {
3556
+ method: 'POST',
3557
+ headers: {
3558
+ 'Content-Type': 'application/json',
3559
+ },
3560
+ body: JSON.stringify({ url }),
3561
+ });
3562
+
3563
+ const result = await response.json();
3564
+
3565
+ if (!result.success) {
3566
+ console.error('[env-setup] Failed to open URL:', result.error);
3567
+ // Fallback to direct open if API fails
3568
+ window.open(url, '_blank');
3569
+ }
3570
+ } catch (error) {
3571
+ console.error('[env-setup] Error opening URL:', error);
3572
+ // Fallback to direct open if API fails
3573
+ window.open(url, '_blank');
3574
+ }
3449
3575
  }
3450
3576
 
3451
- /* Empty state */
3452
- .empty-state {
3453
- padding: 60px 20px;
3454
- text-align: center;
3577
+ // Create new environment
3578
+ function createNewEnv() {
3579
+ console.log('[env-setup] Creating new environment');
3580
+ openUrl(null, 'https://buy.cloud.tencent.com/lowcode?buyType=tcb&channel=mcp');
3455
3581
  }
3456
3582
 
3457
- .empty-message {
3458
- font-size: 14px;
3459
- color: var(--text-secondary);
3460
- opacity: 0.7;
3461
- line-height: 1.6;
3583
+ // Refresh environment list
3584
+ function refreshEnvList() {
3585
+ console.log('[env-setup] Refreshing environment list');
3586
+ if (ws.readyState === WebSocket.OPEN) {
3587
+ ws.send(JSON.stringify({
3588
+ type: 'refreshEnvList'
3589
+ }));
3590
+
3591
+ // Add rotation animation
3592
+ const btn = event.target.closest('.btn-refresh');
3593
+ if (btn) {
3594
+ btn.style.transform = 'rotate(360deg)';
3595
+ setTimeout(() => {
3596
+ btn.style.transform = 'rotate(0deg)';
3597
+ }, 600);
3598
+ }
3599
+ }
3462
3600
  }
3463
3601
 
3464
- .create-env-link {
3465
- color: var(--accent-color);
3466
- text-decoration: none;
3467
- border-bottom: 1px solid transparent;
3468
- transition: all 0.3s ease;
3602
+ // Retry init TCB
3603
+ function retryInitTcb(sessionId) {
3604
+ console.log('[env-setup] Retrying TCB initialization:', sessionId);
3605
+ if (ws.readyState === WebSocket.OPEN) {
3606
+ ws.send(JSON.stringify({
3607
+ type: 'retryInitTcb',
3608
+ sessionId: sessionId
3609
+ }));
3610
+ }
3469
3611
  }
3470
3612
 
3471
- .create-env-link:hover {
3472
- border-bottom-color: var(--accent-color);
3473
- opacity: 0.8;
3474
- }
3613
+ // Initialize on page load
3614
+ window.addEventListener('load', () => {
3615
+ // Auto-select first environment if exists
3616
+ const firstEnvItem = document.querySelector('.env-item');
3617
+ if (firstEnvItem && !selectedEnvId) {
3618
+ const envId = firstEnvItem.getAttribute('onclick')?.match(/selectEnv\\('([^']+)'/)?.[1];
3619
+ if (envId) {
3620
+ selectEnv(envId, firstEnvItem);
3621
+ console.log('[env-setup] Auto-selected first environment:', envId);
3622
+ }
3623
+ }
3624
+ });
3625
+ </script>
3626
+ `.trim();
3627
+ }
3475
3628
 
3476
- /* Action buttons */
3477
- .actions {
3478
- display: flex;
3479
- gap: 10px;
3480
- margin-top: 28px;
3481
- }
3482
3629
 
3483
- .btn {
3484
- flex: 1;
3485
- padding: 12px 20px;
3486
- border: none;
3487
- border-radius: 10px;
3488
- font-size: 13px;
3489
- font-weight: 500;
3490
- cursor: pointer;
3491
- transition: all 0.3s ease;
3630
+ /***/ },
3631
+
3632
+ /***/ 7373
3633
+ (__unused_webpack_module, exports) {
3634
+
3635
+ var __webpack_unused_export__;
3636
+
3637
+ /**
3638
+ * CSS styles for env setup page
3639
+ */
3640
+ __webpack_unused_export__ = ({ value: true });
3641
+ exports.CSS_STYLES = void 0;
3642
+ exports.CSS_STYLES = `
3643
+ <style>
3644
+ @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&display=swap');
3645
+
3646
+ * { margin: 0; padding: 0; box-sizing: border-box; }
3647
+
3648
+ :root {
3649
+ --primary-color: #1a1a1a;
3650
+ --primary-hover: #000000;
3651
+ --accent-color: #67E9E9;
3652
+ --accent-hover: #2BCCCC;
3653
+ --text-primary: #ffffff;
3654
+ --text-secondary: #a0a0a0;
3655
+ --border-color: rgba(255, 255, 255, 0.15);
3656
+ --bg-secondary: rgba(255, 255, 255, 0.08);
3657
+ --bg-glass: rgba(26, 26, 26, 0.95);
3658
+ --shadow: 0 25px 50px rgba(0, 0, 0, 0.3), 0 10px 20px rgba(0, 0, 0, 0.2);
3659
+ --font-mono: 'JetBrains Mono', 'SF Mono', 'Monaco', monospace;
3660
+ --header-bg: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 50%, #0d1117 100%);
3661
+ }
3662
+
3663
+ body {
3664
+ font-family: var(--font-mono);
3665
+ background: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 100%);
3666
+ min-height: 100vh;
3492
3667
  display: flex;
3493
3668
  align-items: center;
3494
3669
  justify-content: center;
3495
- gap: 6px;
3496
- font-family: var(--font-mono);
3497
- letter-spacing: -0.01em;
3670
+ padding: 20px;
3671
+ position: relative;
3672
+ overflow-x: hidden;
3673
+ overflow-y: auto;
3498
3674
  }
3499
3675
 
3500
- .btn-primary {
3676
+ /* Custom scrollbar styles */
3677
+ ::-webkit-scrollbar {
3678
+ width: 8px;
3679
+ }
3680
+
3681
+ ::-webkit-scrollbar-track {
3682
+ background: rgba(255, 255, 255, 0.05);
3683
+ border-radius: 4px;
3684
+ }
3685
+
3686
+ ::-webkit-scrollbar-thumb {
3501
3687
  background: var(--accent-color);
3502
- color: var(--primary-color);
3503
- border: 1px solid var(--accent-color);
3688
+ border-radius: 4px;
3504
3689
  }
3505
3690
 
3506
- .btn-primary:hover:not(:disabled) {
3691
+ ::-webkit-scrollbar-thumb:hover {
3507
3692
  background: var(--accent-hover);
3508
- box-shadow: 0 4px 12px rgba(103, 233, 233, 0.3);
3509
3693
  }
3510
3694
 
3511
- .btn-primary:disabled {
3512
- background: var(--bg-secondary);
3513
- color: var(--text-secondary);
3514
- cursor: not-allowed;
3515
- opacity: 0.5;
3516
- border-color: var(--border-color);
3695
+ body::before {
3696
+ content: '';
3697
+ position: fixed;
3698
+ top: 0; left: 0; right: 0; bottom: 0;
3699
+ background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grid" width="20" height="20" patternUnits="userSpaceOnUse"><path d="M 20 0 L 0 0 0 20" fill="none" stroke="rgba(255,255,255,0.02)" stroke-width="1"/></pattern></defs><rect width="100" height="100" fill="url(%23grid)"/></svg>') repeat;
3700
+ pointer-events: none;
3701
+ z-index: -1;
3517
3702
  }
3518
3703
 
3519
- .btn-secondary {
3520
- background: transparent;
3521
- color: var(--text-primary);
3522
- border: 1px solid var(--border-color);
3704
+ body::after {
3705
+ content: '';
3706
+ position: fixed;
3707
+ top: 50%; left: 50%;
3708
+ width: 500px; height: 500px;
3709
+ background: radial-gradient(circle, rgba(103, 233, 233, 0.05) 0%, transparent 70%);
3710
+ transform: translate(-50%, -50%);
3711
+ pointer-events: none;
3712
+ z-index: -1;
3713
+ animation: pulse 8s ease-in-out infinite;
3523
3714
  }
3524
3715
 
3525
- .btn-secondary:hover {
3526
- background: var(--bg-secondary);
3527
- border-color: rgba(255, 255, 255, 0.3);
3716
+ @keyframes pulse {
3717
+ 0%, 100% { opacity: 0.3; transform: translate(-50%, -50%) scale(1); }
3718
+ 50% { opacity: 0.6; transform: translate(-50%, -50%) scale(1.1); }
3528
3719
  }
3529
3720
 
3530
- /* Help links */
3531
- .help-links {
3532
- display: flex;
3533
- gap: 20px;
3534
- justify-content: center;
3535
- margin-top: 24px;
3536
- padding-top: 24px;
3537
- border-top: 1px solid rgba(255, 255, 255, 0.06);
3721
+ .modal {
3722
+ background: var(--bg-glass);
3723
+ backdrop-filter: blur(20px);
3724
+ border-radius: 20px;
3725
+ box-shadow: var(--shadow);
3726
+ border: 1px solid var(--border-color);
3727
+ width: 100%;
3728
+ max-width: 640px;
3729
+ overflow: hidden;
3730
+ animation: modalIn 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275);
3731
+ position: relative;
3538
3732
  }
3539
3733
 
3540
- .help-link {
3541
- display: flex;
3542
- align-items: center;
3543
- gap: 6px;
3544
- color: var(--text-secondary);
3545
- text-decoration: none;
3546
- font-size: 12px;
3547
- padding: 6px 10px;
3548
- border-radius: 6px;
3549
- transition: all 0.3s ease;
3550
- opacity: 0.8;
3734
+ .modal::before {
3735
+ content: '';
3736
+ position: absolute;
3737
+ top: 0; left: 0; right: 0; bottom: 0;
3738
+ background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.02) 50%, transparent 70%);
3739
+ animation: shimmer 3s infinite;
3740
+ pointer-events: none;
3551
3741
  }
3552
3742
 
3553
- .help-link:hover {
3554
- background: rgba(103, 233, 233, 0.08);
3555
- color: var(--accent-color);
3556
- opacity: 1;
3743
+ @keyframes shimmer {
3744
+ 0% { transform: translateX(-100%); }
3745
+ 100% { transform: translateX(100%); }
3557
3746
  }
3558
3747
 
3559
- /* Loading state */
3560
- .loading {
3561
- display: none;
3562
- flex-direction: column;
3563
- align-items: center;
3564
- justify-content: center;
3565
- padding: 40px;
3566
- gap: 20px;
3748
+ @keyframes modalIn {
3749
+ from {
3750
+ opacity: 0;
3751
+ transform: scale(0.9) translateY(-20px);
3752
+ }
3753
+ to {
3754
+ opacity: 1;
3755
+ transform: scale(1) translateY(0);
3756
+ }
3567
3757
  }
3568
3758
 
3569
- .spinner {
3570
- width: 40px;
3571
- height: 40px;
3572
- border: 3px solid var(--border-color);
3573
- border-top-color: var(--accent-color);
3574
- border-radius: 50%;
3575
- animation: spin 0.8s linear infinite;
3759
+ .header {
3760
+ background: var(--header-bg);
3761
+ color: var(--text-primary);
3762
+ padding: 20px 32px;
3763
+ display: flex;
3764
+ align-items: center;
3765
+ justify-content: space-between;
3766
+ position: relative;
3767
+ overflow: hidden;
3576
3768
  }
3577
3769
 
3578
- @keyframes spin {
3579
- to { transform: rotate(360deg); }
3770
+ .header::before {
3771
+ content: '';
3772
+ position: absolute;
3773
+ top: 0; left: 0; right: 0; bottom: 0;
3774
+ background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.03) 50%, transparent 70%);
3775
+ animation: headerShimmer 4s infinite;
3776
+ pointer-events: none;
3580
3777
  }
3581
3778
 
3582
- .loading span {
3583
- color: var(--text-secondary);
3584
- font-size: 14px;
3779
+ @keyframes headerShimmer {
3780
+ 0% { transform: translateX(-100%); }
3781
+ 100% { transform: translateX(100%); }
3585
3782
  }
3586
3783
 
3587
- /* Success state */
3588
- .success-state {
3589
- text-align: center;
3590
- padding: 40px 20px;
3591
- animation: fadeInUp 0.8s ease-out both;
3784
+ .header-left {
3785
+ display: flex;
3786
+ align-items: center;
3787
+ gap: 16px;
3788
+ z-index: 1;
3592
3789
  }
3593
3790
 
3594
- .success-icon {
3595
- margin-bottom: 20px;
3596
- color: var(--accent-color);
3597
- animation: successPulse 2s ease-in-out infinite;
3791
+ .logo {
3792
+ width: 32px;
3793
+ height: 32px;
3794
+ filter: drop-shadow(0 4px 8px rgba(0,0,0,0.2));
3795
+ animation: logoFloat 3s ease-in-out infinite;
3598
3796
  }
3599
3797
 
3600
- @keyframes successPulse {
3601
- 0%, 100% {
3602
- transform: scale(1);
3603
- filter: drop-shadow(0 0 8px rgba(103, 233, 233, 0.3));
3604
- }
3605
- 50% {
3606
- transform: scale(1.1);
3607
- filter: drop-shadow(0 0 16px rgba(103, 233, 233, 0.6));
3608
- }
3798
+ @keyframes logoFloat {
3799
+ 0%, 100% { transform: translateY(0px); }
3800
+ 50% { transform: translateY(-3px); }
3609
3801
  }
3610
3802
 
3611
- .success-title {
3612
- font-size: 24px;
3613
- font-weight: 700;
3614
- color: var(--text-primary);
3615
- margin-bottom: 12px;
3803
+ .title {
3804
+ font-size: 18px;
3805
+ font-weight: 600;
3806
+ text-shadow: 0 2px 4px rgba(0,0,0,0.1);
3616
3807
  }
3617
3808
 
3618
- .success-message {
3619
- color: var(--text-secondary);
3620
- font-size: 16px;
3621
- line-height: 1.5;
3809
+ .header-right {
3810
+ display: flex;
3811
+ align-items: center;
3812
+ gap: 16px;
3813
+ z-index: 1;
3622
3814
  }
3623
3815
 
3624
- .selected-env-info {
3625
- margin-top: 20px;
3626
- padding: 16px;
3627
- background: rgba(103, 233, 233, 0.1);
3628
- border: 1px solid var(--accent-color);
3629
- border-radius: 12px;
3816
+ .account-section {
3630
3817
  display: flex;
3631
3818
  align-items: center;
3632
- gap: 12px;
3819
+ gap: 8px;
3820
+ padding: 6px 12px;
3821
+ background: rgba(255, 255, 255, 0.04);
3822
+ border: 1px solid var(--border-color);
3823
+ border-radius: 8px;
3633
3824
  }
3634
3825
 
3635
- .env-label {
3826
+ .account-uin {
3827
+ font-size: 12px;
3636
3828
  color: var(--text-secondary);
3637
- font-size: 14px;
3638
- font-weight: 500;
3829
+ font-family: var(--font-mono);
3639
3830
  }
3640
3831
 
3641
- .env-value {
3832
+ .btn-switch {
3833
+ display: flex;
3834
+ align-items: center;
3835
+ justify-content: center;
3836
+ padding: 4px;
3837
+ background: transparent;
3838
+ border: none;
3839
+ color: var(--text-secondary);
3840
+ cursor: pointer;
3841
+ transition: all 0.3s ease;
3842
+ border-radius: 4px;
3843
+ }
3844
+
3845
+ .btn-switch:hover {
3846
+ background: rgba(255, 255, 255, 0.1);
3642
3847
  color: var(--accent-color);
3643
- font-size: 16px;
3644
- font-weight: 600;
3645
- font-family: var(--font-mono);
3646
3848
  }
3647
3849
 
3648
- /* Info banner (for non-critical notifications) */
3649
- .info-banner {
3650
- margin-bottom: 20px;
3651
- padding: 16px;
3652
- background: rgba(103, 233, 233, 0.08);
3653
- border: 1px solid rgba(103, 233, 233, 0.2);
3654
- border-radius: 12px;
3850
+ .btn-icon-link {
3851
+ display: flex;
3852
+ align-items: center;
3853
+ justify-content: center;
3854
+ padding: 7px;
3855
+ background: transparent;
3856
+ border: 1px solid var(--border-color);
3857
+ border-radius: 8px;
3858
+ color: var(--text-primary);
3859
+ cursor: pointer;
3860
+ transition: all 0.3s ease;
3861
+ text-decoration: none;
3655
3862
  }
3656
3863
 
3657
- .info-item {
3658
- margin-bottom: 16px;
3864
+ .btn-icon-link:hover {
3865
+ background: rgba(255, 255, 255, 0.08);
3866
+ border-color: var(--accent-color);
3659
3867
  }
3660
3868
 
3661
- .info-item:last-child {
3662
- margin-bottom: 0;
3869
+ .content {
3870
+ padding: 32px 32px 28px;
3663
3871
  }
3664
3872
 
3665
- .info-header {
3666
- display: flex;
3667
- align-items: center;
3668
- gap: 8px;
3669
- margin-bottom: 8px;
3873
+ .content-title {
3874
+ font-size: 20px;
3875
+ font-weight: 600;
3876
+ color: var(--text-primary);
3877
+ margin-bottom: 28px;
3878
+ text-align: center;
3879
+ letter-spacing: -0.01em;
3670
3880
  }
3671
3881
 
3672
- .info-header svg {
3673
- color: var(--accent-color);
3882
+ /* Search section styles */
3883
+ .search-section {
3884
+ display: flex;
3885
+ gap: 10px;
3886
+ margin-bottom: 24px;
3674
3887
  }
3675
3888
 
3676
- .info-title {
3677
- color: var(--text-primary);
3678
- font-weight: 600;
3679
- font-size: 14px;
3889
+ .search-box {
3890
+ position: relative;
3891
+ flex: 1;
3680
3892
  }
3681
3893
 
3682
- .info-message {
3894
+ .search-icon {
3895
+ position: absolute;
3896
+ left: 14px;
3897
+ top: 50%;
3898
+ transform: translateY(-50%);
3683
3899
  color: var(--text-secondary);
3900
+ pointer-events: none;
3901
+ z-index: 1;
3902
+ }
3903
+
3904
+ .search-input {
3905
+ width: 100%;
3906
+ padding: 11px 38px 11px 38px;
3907
+ background: var(--bg-secondary);
3908
+ border: 1px solid var(--border-color);
3909
+ border-radius: 10px;
3910
+ color: var(--text-primary);
3684
3911
  font-size: 13px;
3685
- line-height: 1.5;
3686
- margin-bottom: 12px;
3912
+ font-family: var(--font-mono);
3913
+ transition: all 0.3s ease;
3687
3914
  }
3688
3915
 
3689
- .info-details {
3690
- display: flex;
3691
- gap: 16px;
3692
- flex-wrap: wrap;
3693
- margin-bottom: 12px;
3694
- font-size: 12px;
3916
+ .search-input:focus {
3917
+ outline: none;
3918
+ border-color: var(--accent-color);
3919
+ background: rgba(255, 255, 255, 0.1);
3920
+ box-shadow: 0 0 0 3px rgba(103, 233, 233, 0.08);
3921
+ }
3922
+
3923
+ .search-input::placeholder {
3695
3924
  color: var(--text-secondary);
3696
- opacity: 0.7;
3925
+ opacity: 0.6;
3697
3926
  }
3698
3927
 
3699
- .detail-label {
3700
- font-weight: 500;
3928
+ .search-clear {
3929
+ position: absolute;
3930
+ right: 12px;
3931
+ top: 50%;
3932
+ transform: translateY(-50%);
3933
+ background: transparent;
3934
+ border: none;
3935
+ color: var(--text-secondary);
3936
+ cursor: pointer;
3937
+ padding: 4px;
3938
+ display: flex;
3939
+ align-items: center;
3940
+ justify-content: center;
3941
+ border-radius: 4px;
3942
+ transition: all 0.3s ease;
3943
+ z-index: 1;
3701
3944
  }
3702
3945
 
3703
- .detail-value {
3704
- font-family: var(--font-mono);
3705
- opacity: 0.8;
3946
+ .search-clear:hover {
3947
+ color: var(--text-primary);
3948
+ background: rgba(255, 255, 255, 0.1);
3706
3949
  }
3707
3950
 
3708
- .error-action {
3951
+ .search-actions {
3709
3952
  display: flex;
3710
3953
  gap: 8px;
3711
- flex-wrap: wrap;
3712
3954
  }
3713
3955
 
3714
- .error-link {
3715
- display: inline-flex;
3956
+ .btn-action {
3957
+ display: flex;
3716
3958
  align-items: center;
3959
+ justify-content: center;
3717
3960
  gap: 6px;
3718
- padding: 6px 12px;
3719
- background: rgba(103, 233, 233, 0.15);
3720
- border: 1px solid rgba(103, 233, 233, 0.3);
3721
- border-radius: 6px;
3722
- color: var(--accent-color);
3723
- text-decoration: none;
3724
- font-size: 13px;
3961
+ padding: 11px 14px;
3962
+ background: var(--bg-secondary);
3963
+ border: 1px solid var(--border-color);
3964
+ border-radius: 10px;
3965
+ color: var(--text-secondary);
3725
3966
  cursor: pointer;
3726
3967
  transition: all 0.3s ease;
3727
3968
  }
3728
3969
 
3729
- .error-link:hover {
3730
- background: rgba(103, 233, 233, 0.25);
3731
- border-color: var(--accent-color);
3732
- }
3733
-
3734
- .error-retry-btn {
3735
- background: rgba(103, 233, 233, 0.2);
3736
- border-color: var(--accent-color);
3970
+ .btn-action:hover {
3971
+ background: rgba(255, 255, 255, 0.1);
3972
+ border-color: rgba(103, 233, 233, 0.5);
3737
3973
  color: var(--accent-color);
3738
3974
  }
3739
3975
 
3740
- .error-retry-btn:hover {
3741
- background: rgba(103, 233, 233, 0.3);
3976
+ .btn-action:active {
3977
+ transform: scale(0.95);
3742
3978
  }
3743
- </style>
3744
- `;
3745
-
3746
-
3747
- /***/ }),
3748
-
3749
- /***/ 7053:
3750
- /***/ ((__unused_webpack_module, exports) => {
3751
3979
 
3980
+ .btn-text {
3981
+ font-size: 13px;
3982
+ font-weight: 500;
3983
+ }
3752
3984
 
3753
- /**
3754
- * JavaScript logic for env setup page
3755
- */
3756
- Object.defineProperty(exports, "__esModule", ({ value: true }));
3757
- exports.getJavaScripts = getJavaScripts;
3758
- function getJavaScripts(wsPort) {
3759
- return `
3760
- <script>
3761
- let selectedEnvId = null;
3985
+ .env-list {
3986
+ max-height: 340px;
3987
+ overflow-y: auto;
3988
+ padding-right: 6px;
3989
+ margin-bottom: 24px;
3990
+ }
3762
3991
 
3763
- // Select environment
3764
- function selectEnv(envId, element) {
3765
- console.log('[env-setup] Selecting environment:', envId);
3766
- selectedEnvId = envId;
3767
-
3768
- // Remove selected class from all items
3769
- document.querySelectorAll('.env-item').forEach(item => {
3770
- item.classList.remove('selected');
3771
- });
3772
-
3773
- // Add selected class to current item
3774
- element.classList.add('selected');
3775
-
3776
- // Enable confirm button
3777
- document.getElementById('confirmBtn').disabled = false;
3992
+ .env-list::-webkit-scrollbar {
3993
+ width: 5px;
3778
3994
  }
3779
3995
 
3780
- // Filter environments
3781
- function filterEnvs(searchTerm) {
3782
- const items = document.querySelectorAll('.env-item');
3783
- const searchClear = document.getElementById('searchClear');
3784
- let visibleCount = 0;
3785
-
3786
- items.forEach(item => {
3787
- const name = item.querySelector('.env-name').textContent.toLowerCase();
3788
- const id = item.querySelector('.env-id').textContent.toLowerCase();
3789
- const match = name.includes(searchTerm.toLowerCase()) ||
3790
- id.includes(searchTerm.toLowerCase());
3791
-
3792
- item.style.display = match ? 'flex' : 'none';
3793
- if (match) visibleCount++;
3794
- });
3795
-
3796
- // Show/hide clear button
3797
- if (searchClear) {
3798
- searchClear.style.display = searchTerm ? 'flex' : 'none';
3799
- }
3800
-
3801
- // Show/hide no results message
3802
- const noResults = document.getElementById('noResults');
3803
- if (noResults) {
3804
- const hasItems = items.length > 0;
3805
- noResults.style.display = visibleCount === 0 && hasItems ? 'block' : 'none';
3806
- }
3996
+ .env-list::-webkit-scrollbar-track {
3997
+ background: transparent;
3807
3998
  }
3808
3999
 
3809
- // Clear search
3810
- function clearSearch() {
3811
- const searchInput = document.getElementById('searchInput');
3812
- if (searchInput) {
3813
- searchInput.value = '';
3814
- filterEnvs('');
3815
- searchInput.focus();
3816
- }
4000
+ .env-list::-webkit-scrollbar-thumb {
4001
+ background: var(--accent-color);
4002
+ border-radius: 3px;
3817
4003
  }
3818
4004
 
3819
- // WebSocket: same host as page so it works in remote VS Code / Cloud IDE (no localhost)
3820
- const wsScheme = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
3821
- const wsUrl = wsScheme + '//' + window.location.host;
3822
- const ws = new WebSocket(wsUrl);
3823
-
3824
- ws.onopen = () => {
3825
- console.log('[env-setup] WebSocket connected');
3826
- // Send session ID to server to associate this WebSocket with the session
3827
- const sessionId = window.location.pathname.split('/').pop();
3828
- ws.send(JSON.stringify({
3829
- type: 'registerSession',
3830
- sessionId: sessionId
3831
- }));
3832
- };
3833
-
3834
- ws.onmessage = (event) => {
3835
- const data = JSON.parse(event.data);
3836
- console.log('[env-setup] Received message:', data);
3837
-
3838
- if (data.type === 'success' && data.envId) {
3839
- showSuccess(data.envId);
3840
- } else if (data.type === 'envListRefreshed') {
3841
- if (data.success) {
3842
- console.log('[env-setup] Environment list refreshed, reloading page');
3843
- // Reload the page to show updated environment list
3844
- window.location.reload();
3845
- } else {
3846
- console.error('[env-setup] Failed to refresh environment list:', data.error);
3847
- alert('刷新环境列表失败: ' + (data.error || '未知错误'));
3848
- }
3849
- }
3850
- };
3851
-
3852
- ws.onerror = (error) => {
3853
- console.error('[env-setup] WebSocket error:', error);
3854
- };
3855
-
3856
- ws.onclose = () => {
3857
- console.log('[env-setup] WebSocket closed');
3858
- };
3859
-
3860
- // Show success state
3861
- function showSuccess(envId) {
3862
- document.querySelector('.content').style.display = 'none';
3863
- const successState = document.getElementById('successState');
3864
- const selectedEnvDisplay = document.getElementById('selectedEnvDisplay');
3865
-
3866
- if (successState && selectedEnvDisplay) {
3867
- selectedEnvDisplay.textContent = envId;
3868
- successState.style.display = 'block';
3869
- }
4005
+ /* Env item styles */
4006
+ .env-item {
4007
+ display: flex;
4008
+ align-items: center;
4009
+ gap: 14px;
4010
+ padding: 14px 16px;
4011
+ background: var(--bg-secondary);
4012
+ border: 1px solid var(--border-color);
4013
+ border-radius: 10px;
4014
+ margin-bottom: 10px;
4015
+ cursor: pointer;
4016
+ transition: all 0.3s ease;
4017
+ position: relative;
3870
4018
  }
3871
4019
 
3872
- // Confirm selection
3873
- function confirm() {
3874
- if (!selectedEnvId) {
3875
- console.warn('[env-setup] No environment selected');
3876
- return;
3877
- }
3878
-
3879
- console.log('[env-setup] Confirming selection:', selectedEnvId);
3880
-
3881
- if (ws.readyState === WebSocket.OPEN) {
3882
- ws.send(JSON.stringify({
3883
- type: 'envId',
3884
- data: selectedEnvId,
3885
- cancelled: false
3886
- }));
3887
-
3888
- // Close window immediately after sending confirmation
3889
- setTimeout(() => {
3890
- window.close();
3891
- }, 100);
3892
- } else {
3893
- console.error('[env-setup] WebSocket not connected');
3894
- alert('连接已断开,请刷新页面重试');
3895
- }
4020
+ .env-item:hover {
4021
+ background: rgba(255, 255, 255, 0.1);
4022
+ border-color: rgba(103, 233, 233, 0.5);
4023
+ transform: translateX(2px);
3896
4024
  }
3897
4025
 
3898
- // Cancel
3899
- function cancel() {
3900
- console.log('[env-setup] Cancelling');
3901
- if (ws.readyState === WebSocket.OPEN) {
3902
- ws.send(JSON.stringify({
3903
- type: 'envId',
3904
- data: null,
3905
- cancelled: true
3906
- }));
3907
-
3908
- // Close window immediately after sending cancellation
3909
- setTimeout(() => {
3910
- window.close();
3911
- }, 100);
3912
- }
4026
+ .env-item.selected {
4027
+ background: rgba(103, 233, 233, 0.12);
4028
+ border-color: var(--accent-color);
4029
+ box-shadow: 0 0 0 1px rgba(103, 233, 233, 0.2);
3913
4030
  }
3914
4031
 
3915
- // Switch account
3916
- function switchAccount() {
3917
- console.log('[env-setup] Switching account');
3918
- if (ws.readyState === WebSocket.OPEN) {
3919
- ws.send(JSON.stringify({
3920
- type: 'envId',
3921
- data: null,
3922
- switch: true
3923
- }));
3924
-
3925
- // Close window immediately after sending switch request
3926
- setTimeout(() => {
3927
- window.close();
3928
- }, 100);
3929
- }
4032
+ .env-item.selected::after {
4033
+ content: '';
4034
+ position: absolute;
4035
+ right: 16px;
4036
+ top: 50%;
4037
+ transform: translateY(-50%);
4038
+ width: 6px;
4039
+ height: 6px;
4040
+ background: var(--accent-color);
4041
+ border-radius: 50%;
4042
+ box-shadow: 0 0 8px var(--accent-color);
3930
4043
  }
3931
4044
 
3932
- // Universal URL opener - works with all IDEs including CodeBuddy
3933
- async function openUrl(event, url) {
3934
- if (event) {
3935
- event.preventDefault();
3936
- }
3937
-
3938
- console.log('[env-setup] Opening URL:', url);
3939
-
3940
- try {
3941
- const response = await fetch('/api/open-url', {
3942
- method: 'POST',
3943
- headers: {
3944
- 'Content-Type': 'application/json',
3945
- },
3946
- body: JSON.stringify({ url }),
3947
- });
3948
-
3949
- const result = await response.json();
3950
-
3951
- if (!result.success) {
3952
- console.error('[env-setup] Failed to open URL:', result.error);
3953
- // Fallback to direct open if API fails
3954
- window.open(url, '_blank');
3955
- }
3956
- } catch (error) {
3957
- console.error('[env-setup] Error opening URL:', error);
3958
- // Fallback to direct open if API fails
3959
- window.open(url, '_blank');
3960
- }
4045
+ .env-info {
4046
+ flex: 1;
4047
+ min-width: 0;
3961
4048
  }
3962
4049
 
3963
- // Create new environment
3964
- function createNewEnv() {
3965
- console.log('[env-setup] Creating new environment');
3966
- openUrl(null, 'https://buy.cloud.tencent.com/lowcode?buyType=tcb&channel=mcp');
4050
+ .env-name {
4051
+ font-size: 15px;
4052
+ font-weight: 500;
4053
+ color: var(--text-primary);
4054
+ margin-bottom: 5px;
4055
+ overflow: hidden;
4056
+ text-overflow: ellipsis;
4057
+ white-space: nowrap;
4058
+ letter-spacing: -0.01em;
3967
4059
  }
3968
4060
 
3969
- // Refresh environment list
3970
- function refreshEnvList() {
3971
- console.log('[env-setup] Refreshing environment list');
3972
- if (ws.readyState === WebSocket.OPEN) {
3973
- ws.send(JSON.stringify({
3974
- type: 'refreshEnvList'
3975
- }));
3976
-
3977
- // Add rotation animation
3978
- const btn = event.target.closest('.btn-refresh');
3979
- if (btn) {
3980
- btn.style.transform = 'rotate(360deg)';
3981
- setTimeout(() => {
3982
- btn.style.transform = 'rotate(0deg)';
3983
- }, 600);
3984
- }
3985
- }
4061
+ .env-name.unnamed {
4062
+ opacity: 0.5;
3986
4063
  }
3987
4064
 
3988
- // Retry init TCB
3989
- function retryInitTcb(sessionId) {
3990
- console.log('[env-setup] Retrying TCB initialization:', sessionId);
3991
- if (ws.readyState === WebSocket.OPEN) {
3992
- ws.send(JSON.stringify({
3993
- type: 'retryInitTcb',
3994
- sessionId: sessionId
3995
- }));
3996
- }
4065
+ .env-id {
4066
+ font-size: 11px;
4067
+ color: var(--text-secondary);
4068
+ font-family: var(--font-mono);
4069
+ word-break: break-all;
4070
+ opacity: 0.8;
3997
4071
  }
3998
4072
 
3999
- // Initialize on page load
4000
- window.addEventListener('load', () => {
4001
- // Auto-select first environment if exists
4002
- const firstEnvItem = document.querySelector('.env-item');
4003
- if (firstEnvItem && !selectedEnvId) {
4004
- const envId = firstEnvItem.getAttribute('onclick')?.match(/selectEnv\\('([^']+)'/)?.[1];
4005
- if (envId) {
4006
- selectEnv(envId, firstEnvItem);
4007
- console.log('[env-setup] Auto-selected first environment:', envId);
4008
- }
4009
- }
4010
- });
4011
- </script>
4012
- `.trim();
4013
- }
4073
+ /* Empty state */
4074
+ .empty-state {
4075
+ padding: 60px 20px;
4076
+ text-align: center;
4077
+ }
4014
4078
 
4079
+ .empty-message {
4080
+ font-size: 14px;
4081
+ color: var(--text-secondary);
4082
+ opacity: 0.7;
4083
+ line-height: 1.6;
4084
+ }
4015
4085
 
4016
- /***/ }),
4086
+ .create-env-link {
4087
+ color: var(--accent-color);
4088
+ text-decoration: none;
4089
+ border-bottom: 1px solid transparent;
4090
+ transition: all 0.3s ease;
4091
+ }
4017
4092
 
4018
- /***/ 7625:
4019
- /***/ ((__unused_webpack_module, exports) => {
4093
+ .create-env-link:hover {
4094
+ border-bottom-color: var(--accent-color);
4095
+ opacity: 0.8;
4096
+ }
4020
4097
 
4098
+ /* Action buttons */
4099
+ .actions {
4100
+ display: flex;
4101
+ gap: 10px;
4102
+ margin-top: 28px;
4103
+ }
4021
4104
 
4022
- /**
4023
- * Reusable UI components for env setup page
4024
- */
4025
- Object.defineProperty(exports, "__esModule", ({ value: true }));
4026
- exports.renderHeader = renderHeader;
4027
- exports.renderSearchBox = renderSearchBox;
4028
- exports.renderEnvItem = renderEnvItem;
4029
- exports.renderEmptyState = renderEmptyState;
4030
- exports.renderNoResultsState = renderNoResultsState;
4031
- exports.renderHelpLinks = renderHelpLinks;
4032
- exports.renderActionButtons = renderActionButtons;
4033
- exports.renderLoadingState = renderLoadingState;
4034
- exports.renderSuccessState = renderSuccessState;
4035
- exports.renderErrorBanner = renderErrorBanner;
4036
- function renderHeader(accountInfo, ide) {
4037
- const hasAccount = !!accountInfo?.uin;
4038
- const isCodeBuddy = ide === "CodeBuddy";
4039
- return `
4040
- <div class="header">
4041
- <div class="header-left">
4042
- <img class="logo" src="https://7463-tcb-advanced-a656fc-1257967285.tcb.qcloud.la/mcp/cloudbase-logo.svg" alt="CloudBase Logo" />
4043
- <span class="title">CloudBase</span>
4044
- </div>
4045
- ${(hasAccount && accountInfo.region !== 'ap-singapore') ? /** 国际站不支持切 */ `
4046
- <div class="header-right">
4047
- <div class="account-section">
4048
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
4049
- <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/>
4050
- <circle cx="12" cy="7" r="4"/>
4051
- </svg>
4052
- <span class="account-uin">${accountInfo.uin}</span>
4053
- ${accountInfo.region ? `<span class="account-region">${accountInfo.region}</span>` : ''}
4054
- ${!isCodeBuddy ? `
4055
- <button class="btn-switch" onclick="switchAccount()" title="切换账号">
4056
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
4057
- <path d="M17 2l4 4-4 4M7 22l-4-4 4-4M21 6H10M3 18h11"/>
4058
- </svg>
4059
- </button>
4060
- ` : ''}
4061
- </div>
4062
- </div>
4063
- ` : ''}
4064
- </div>
4065
- `.trim();
4066
- }
4067
- function renderSearchBox() {
4068
- return `
4069
- <div class="search-section">
4070
- <div class="search-box">
4071
- <svg class="search-icon" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
4072
- <circle cx="11" cy="11" r="8"/>
4073
- <path d="m21 21-4.35-4.35"/>
4074
- </svg>
4075
- <input
4076
- type="text"
4077
- id="searchInput"
4078
- class="search-input"
4079
- placeholder="搜索环境名称或 ID..."
4080
- oninput="filterEnvs(this.value)"
4081
- />
4082
- <button class="search-clear" onclick="clearSearch()" id="searchClear" style="display: none;">
4083
- <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
4084
- <path d="M18 6L6 18M6 6l12 12"/>
4085
- </svg>
4086
- </button>
4087
- </div>
4088
- <div class="search-actions">
4089
- <button class="btn-action" onclick="createNewEnv()" title="新建环境">
4090
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
4091
- <path d="M12 5v14M5 12h14"/>
4092
- </svg>
4093
- <span class="btn-text">新建环境</span>
4094
- </button>
4095
- <button class="btn-action" onclick="refreshEnvList()" title="刷新环境列表">
4096
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
4097
- <path d="M21.5 2v6h-6M2.5 22v-6h6M2 11.5a10 10 0 0 1 18.8-4.3M22 12.5a10 10 0 0 1-18.8 4.2"/>
4098
- </svg>
4099
- </button>
4100
- </div>
4101
- </div>
4102
- `.trim();
4103
- }
4104
- function renderEnvItem(env, index) {
4105
- const alias = env.Alias || '(未命名)';
4106
- const envId = env.EnvId;
4107
- const hasAlias = !!env.Alias;
4108
- return `
4109
- <div class="env-item" onclick="selectEnv('${envId}', this)">
4110
- <div class="env-info">
4111
- <div class="env-name ${!hasAlias ? 'unnamed' : ''}">${alias}</div>
4112
- <div class="env-id">${envId}</div>
4113
- </div>
4114
- </div>
4115
- `.trim();
4116
- }
4117
- function renderEmptyState(hasInitError) {
4118
- return `
4119
- <div class="empty-state">
4120
- <p class="empty-message">
4121
- 暂无环境,请先<a href="https://buy.cloud.tencent.com/lowcode?buyType=tcb&channel=mcp" onclick="openUrl(event, 'https://buy.cloud.tencent.com/lowcode?buyType=tcb&channel=mcp'); return false;" class="create-env-link">创建环境</a>,然后点击刷新按钮重试
4122
- </p>
4123
- </div>
4124
- `.trim();
4125
- }
4126
- function renderNoResultsState() {
4127
- return `
4128
- <div class="empty-state" id="noResults" style="display: none;">
4129
- <svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="opacity: 0.3;">
4130
- <circle cx="11" cy="11" r="8"/>
4131
- <path d="m21 21-4.35-4.35"/>
4132
- </svg>
4133
- <p class="empty-message">未找到匹配的环境</p>
4134
- </div>
4135
- `.trim();
4136
- }
4137
- function renderHelpLinks() {
4138
- return `
4139
- <div class="help-links">
4140
- <a href="https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/" onclick="openUrl(event, 'https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/'); return false;" class="help-link">
4141
- <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
4142
- <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
4143
- <polyline points="14 2 14 8 20 8"/>
4144
- <line x1="16" y1="13" x2="8" y2="13"/>
4145
- <line x1="16" y1="17" x2="8" y2="17"/>
4146
- </svg>
4147
- 帮助文档
4148
- </a>
4149
- <a href="https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/tutorials" onclick="openUrl(event, 'https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/tutorials'); return false;" class="help-link">
4150
- <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
4151
- <polygon points="23 7 16 12 23 17 23 7"/>
4152
- <rect x="1" y="5" width="15" height="14" rx="2" ry="2"/>
4153
- </svg>
4154
- 视频教程
4155
- </a>
4156
- <a href="https://github.com/TencentCloudBase/CloudBase-AI-ToolKit" onclick="openUrl(event, 'https://github.com/TencentCloudBase/CloudBase-AI-ToolKit'); return false;" class="help-link">
4157
- <svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor">
4158
- <path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
4159
- </svg>
4160
- GitHub
4161
- </a>
4162
- </div>
4163
- `.trim();
4164
- }
4165
- function renderActionButtons(hasEnvs, hasInitError) {
4166
- return `
4167
- <div class="actions">
4168
- <button class="btn btn-secondary" onclick="cancel()">
4169
- <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
4170
- <path d="M18 6L6 18M6 6l12 12"/>
4171
- </svg>
4172
- 取消
4173
- </button>
4174
- <button class="btn btn-primary" id="confirmBtn" onclick="confirm()" disabled>
4175
- <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
4176
- <path d="M20 6L9 17l-5-5"/>
4177
- </svg>
4178
- 确认选择
4179
- </button>
4180
- </div>
4181
- `.trim();
4182
- }
4183
- function renderLoadingState() {
4184
- return `
4185
- <div class="loading" id="loading" style="display: none;">
4186
- <div class="spinner"></div>
4187
- <span>正在配置环境...</span>
4188
- </div>
4189
- `.trim();
4190
- }
4191
- function renderSuccessState() {
4192
- return `
4193
- <div class="success-state" id="successState" style="display: none;">
4194
- <div class="success-icon">
4195
- <svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
4196
- <path d="M20 6L9 17l-5-5"/>
4197
- </svg>
4198
- </div>
4199
- <h2 class="success-title">环境配置成功!</h2>
4200
- <p class="success-message">已成功选择 CloudBase 环境</p>
4201
- <div class="selected-env-info">
4202
- <span class="env-label">环境 ID:</span>
4203
- <span class="env-value" id="selectedEnvDisplay"></span>
4204
- </div>
4205
- </div>
4206
- `.trim();
4207
- }
4208
- function renderErrorBanner(errorContext, sessionId) {
4209
- const initTcbError = errorContext?.initTcbError;
4210
- const createEnvError = errorContext?.createEnvError;
4211
- // Only show initTcbError, hide createEnvError
4212
- if (!initTcbError) {
4213
- return '';
4214
- }
4215
- return `
4216
- <div class="info-banner" id="errorBanner">
4217
- ${initTcbError ? `
4218
- <div class="info-item">
4219
- <div class="info-header">
4220
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
4221
- <circle cx="12" cy="12" r="10"/>
4222
- <line x1="12" y1="8" x2="12" y2="12"/>
4223
- <line x1="12" y1="16" x2="12.01" y2="16"/>
4224
- </svg>
4225
- <span class="info-title">${escapeHtml(initTcbError.message)}</span>
4226
- </div>
4227
- <div class="info-message">${escapeHtml(initTcbError.actionText || '')}</div>
4228
- ${initTcbError.requestId ? `
4229
- <div class="info-details">
4230
- <span class="detail-label">错误码:</span> <span class="detail-value">${escapeHtml(initTcbError.code)}</span>
4231
- <span class="detail-label">请求 ID:</span> <span class="detail-value">${escapeHtml(initTcbError.requestId)}</span>
4232
- </div>
4233
- ` : ''}
4234
- ${initTcbError.needRealNameAuth ? `
4235
- <div class="error-action">
4236
- <a href="${initTcbError.helpUrl || 'https://buy.cloud.tencent.com/lowcode?buyType=tcb&channel=mcp'}" onclick="openUrl(event, '${initTcbError.helpUrl || 'https://buy.cloud.tencent.com/lowcode?buyType=tcb&channel=mcp'}'); return false;" class="error-link">
4237
- 前往实名认证
4238
- </a>
4239
- </div>
4240
- ` : ''}
4241
- ${initTcbError.needCamAuth ? `
4242
- <div class="error-action">
4243
- <a href="${initTcbError.helpUrl || 'https://buy.cloud.tencent.com/lowcode?buyType=tcb&channel=mcp'}" onclick="openUrl(event, '${initTcbError.helpUrl || 'https://buy.cloud.tencent.com/lowcode?buyType=tcb&channel=mcp'}'); return false;" class="error-link">
4244
- 前往开通 CloudBase 服务
4245
- </a>
4246
- ${sessionId ? `
4247
- <button class="error-link error-retry-btn" onclick="retryInitTcb('${sessionId}')">
4248
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
4249
- <path d="M23 4v6h-6M1 20v-6h6M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/>
4250
- </svg>
4251
- 重试
4252
- </button>
4253
- ` : ''}
4254
- </div>
4255
- ` : ''}
4256
- ${!initTcbError.needRealNameAuth && !initTcbError.needCamAuth && initTcbError.helpUrl ? `
4257
- <div class="error-action">
4258
- <a href="${initTcbError.helpUrl}" onclick="openUrl(event, '${initTcbError.helpUrl}'); return false;" class="error-link">
4259
- 前往开通 CloudBase 服务
4260
- </a>
4261
- ${sessionId ? `
4262
- <button class="error-link error-retry-btn" onclick="retryInitTcb('${sessionId}')">
4263
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
4264
- <path d="M23 4v6h-6M1 20v-6h6M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/>
4265
- </svg>
4266
- 重试
4267
- </button>
4268
- ` : ''}
4269
- </div>
4270
- ` : ''}
4271
- </div>
4272
- ` : ''}
4273
- </div>
4274
- `.trim();
4275
- }
4276
- // Helper function to escape HTML
4277
- function escapeHtml(text) {
4278
- const map = {
4279
- '&': '&amp;',
4280
- '<': '&lt;',
4281
- '>': '&gt;',
4282
- '"': '&quot;',
4283
- "'": '&#039;'
4284
- };
4285
- return text.replace(/[&<>"']/g, (m) => map[m]);
4286
- }
4105
+ .btn {
4106
+ flex: 1;
4107
+ padding: 12px 20px;
4108
+ border: none;
4109
+ border-radius: 10px;
4110
+ font-size: 13px;
4111
+ font-weight: 500;
4112
+ cursor: pointer;
4113
+ transition: all 0.3s ease;
4114
+ display: flex;
4115
+ align-items: center;
4116
+ justify-content: center;
4117
+ gap: 6px;
4118
+ font-family: var(--font-mono);
4119
+ letter-spacing: -0.01em;
4120
+ }
4121
+
4122
+ .btn-primary {
4123
+ background: var(--accent-color);
4124
+ color: var(--primary-color);
4125
+ border: 1px solid var(--accent-color);
4126
+ }
4127
+
4128
+ .btn-primary:hover:not(:disabled) {
4129
+ background: var(--accent-hover);
4130
+ box-shadow: 0 4px 12px rgba(103, 233, 233, 0.3);
4131
+ }
4132
+
4133
+ .btn-primary:disabled {
4134
+ background: var(--bg-secondary);
4135
+ color: var(--text-secondary);
4136
+ cursor: not-allowed;
4137
+ opacity: 0.5;
4138
+ border-color: var(--border-color);
4139
+ }
4140
+
4141
+ .btn-secondary {
4142
+ background: transparent;
4143
+ color: var(--text-primary);
4144
+ border: 1px solid var(--border-color);
4145
+ }
4146
+
4147
+ .btn-secondary:hover {
4148
+ background: var(--bg-secondary);
4149
+ border-color: rgba(255, 255, 255, 0.3);
4150
+ }
4151
+
4152
+ /* Help links */
4153
+ .help-links {
4154
+ display: flex;
4155
+ gap: 20px;
4156
+ justify-content: center;
4157
+ margin-top: 24px;
4158
+ padding-top: 24px;
4159
+ border-top: 1px solid rgba(255, 255, 255, 0.06);
4160
+ }
4161
+
4162
+ .help-link {
4163
+ display: flex;
4164
+ align-items: center;
4165
+ gap: 6px;
4166
+ color: var(--text-secondary);
4167
+ text-decoration: none;
4168
+ font-size: 12px;
4169
+ padding: 6px 10px;
4170
+ border-radius: 6px;
4171
+ transition: all 0.3s ease;
4172
+ opacity: 0.8;
4173
+ }
4287
4174
 
4175
+ .help-link:hover {
4176
+ background: rgba(103, 233, 233, 0.08);
4177
+ color: var(--accent-color);
4178
+ opacity: 1;
4179
+ }
4288
4180
 
4289
- /***/ }),
4181
+ /* Loading state */
4182
+ .loading {
4183
+ display: none;
4184
+ flex-direction: column;
4185
+ align-items: center;
4186
+ justify-content: center;
4187
+ padding: 40px;
4188
+ gap: 20px;
4189
+ }
4290
4190
 
4291
- /***/ 9529:
4292
- /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
4191
+ .spinner {
4192
+ width: 40px;
4193
+ height: 40px;
4194
+ border: 3px solid var(--border-color);
4195
+ border-top-color: var(--accent-color);
4196
+ border-radius: 50%;
4197
+ animation: spin 0.8s linear infinite;
4198
+ }
4293
4199
 
4200
+ @keyframes spin {
4201
+ to { transform: rotate(360deg); }
4202
+ }
4294
4203
 
4295
- /**
4296
- * Main renderer for env setup page
4297
- */
4298
- Object.defineProperty(exports, "__esModule", ({ value: true }));
4299
- exports.renderEnvSetupPage = renderEnvSetupPage;
4300
- const components_js_1 = __webpack_require__(7625);
4301
- const html_js_1 = __webpack_require__(4112);
4302
- const scripts_js_1 = __webpack_require__(7053);
4303
- const styles_js_1 = __webpack_require__(6975);
4304
- /**
4305
- * Render the complete env setup page
4306
- */
4307
- function renderEnvSetupPage(options) {
4308
- const { envs = [], accountInfo, errorContext, sessionId, wsPort, ide } = options;
4309
- const hasEnvs = envs.length > 0;
4310
- const hasInitError = !!errorContext?.initTcbError;
4311
- const hasErrors = !!(errorContext?.initTcbError || errorContext?.createEnvError);
4312
- // Build env list HTML
4313
- let envListHTML = '';
4314
- if (hasEnvs) {
4315
- envListHTML = `
4316
- ${(0, components_js_1.renderSearchBox)()}
4317
- <div class="env-list" id="envList">
4318
- ${envs.map((env, index) => (0, components_js_1.renderEnvItem)(env, index)).join('\n')}
4319
- </div>
4320
- ${(0, components_js_1.renderNoResultsState)()}
4321
- `;
4204
+ .loading span {
4205
+ color: var(--text-secondary);
4206
+ font-size: 14px;
4207
+ }
4208
+
4209
+ /* Success state */
4210
+ .success-state {
4211
+ text-align: center;
4212
+ padding: 40px 20px;
4213
+ animation: fadeInUp 0.8s ease-out both;
4214
+ }
4215
+
4216
+ .success-icon {
4217
+ margin-bottom: 20px;
4218
+ color: var(--accent-color);
4219
+ animation: successPulse 2s ease-in-out infinite;
4220
+ }
4221
+
4222
+ @keyframes successPulse {
4223
+ 0%, 100% {
4224
+ transform: scale(1);
4225
+ filter: drop-shadow(0 0 8px rgba(103, 233, 233, 0.3));
4322
4226
  }
4323
- else {
4324
- // 暂无环境时也显示搜索框、新建和刷新按钮
4325
- envListHTML = `
4326
- ${(0, components_js_1.renderSearchBox)()}
4327
- <div class="env-list" id="envList">
4328
- ${(0, components_js_1.renderEmptyState)(hasInitError)}
4329
- </div>
4330
- ${(0, components_js_1.renderNoResultsState)()}
4331
- `;
4227
+ 50% {
4228
+ transform: scale(1.1);
4229
+ filter: drop-shadow(0 0 16px rgba(103, 233, 233, 0.6));
4332
4230
  }
4333
- // Build body HTML
4334
- const bodyHTML = `
4335
- <div class="modal">
4336
- ${(0, components_js_1.renderHeader)(accountInfo, ide)}
4337
- <div class="content">
4338
- <h1 class="content-title">选择环境</h1>
4339
-
4340
- ${hasErrors ? (0, components_js_1.renderErrorBanner)(errorContext, sessionId) : ''}
4341
-
4342
- ${envListHTML}
4343
-
4344
- ${(0, components_js_1.renderActionButtons)(hasEnvs, hasInitError)}
4345
-
4346
- ${(0, components_js_1.renderHelpLinks)()}
4347
-
4348
- ${(0, components_js_1.renderLoadingState)()}
4349
-
4350
- ${(0, components_js_1.renderSuccessState)()}
4351
- </div>
4352
- </div>
4353
- `;
4354
- // Get JavaScript with WebSocket port
4355
- const scripts = (0, scripts_js_1.getJavaScripts)(wsPort);
4356
- // Assemble final HTML
4357
- return (0, html_js_1.buildHTMLPage)(styles_js_1.CSS_STYLES, bodyHTML, scripts);
4358
- }
4231
+ }
4232
+
4233
+ .success-title {
4234
+ font-size: 24px;
4235
+ font-weight: 700;
4236
+ color: var(--text-primary);
4237
+ margin-bottom: 12px;
4238
+ }
4239
+
4240
+ .success-message {
4241
+ color: var(--text-secondary);
4242
+ font-size: 16px;
4243
+ line-height: 1.5;
4244
+ }
4245
+
4246
+ .selected-env-info {
4247
+ margin-top: 20px;
4248
+ padding: 16px;
4249
+ background: rgba(103, 233, 233, 0.1);
4250
+ border: 1px solid var(--accent-color);
4251
+ border-radius: 12px;
4252
+ display: flex;
4253
+ align-items: center;
4254
+ gap: 12px;
4255
+ }
4256
+
4257
+ .env-label {
4258
+ color: var(--text-secondary);
4259
+ font-size: 14px;
4260
+ font-weight: 500;
4261
+ }
4262
+
4263
+ .env-value {
4264
+ color: var(--accent-color);
4265
+ font-size: 16px;
4266
+ font-weight: 600;
4267
+ font-family: var(--font-mono);
4268
+ }
4269
+
4270
+ /* Info banner (for non-critical notifications) */
4271
+ .info-banner {
4272
+ margin-bottom: 20px;
4273
+ padding: 16px;
4274
+ background: rgba(103, 233, 233, 0.08);
4275
+ border: 1px solid rgba(103, 233, 233, 0.2);
4276
+ border-radius: 12px;
4277
+ }
4278
+
4279
+ .info-item {
4280
+ margin-bottom: 16px;
4281
+ }
4282
+
4283
+ .info-item:last-child {
4284
+ margin-bottom: 0;
4285
+ }
4286
+
4287
+ .info-header {
4288
+ display: flex;
4289
+ align-items: center;
4290
+ gap: 8px;
4291
+ margin-bottom: 8px;
4292
+ }
4293
+
4294
+ .info-header svg {
4295
+ color: var(--accent-color);
4296
+ }
4297
+
4298
+ .info-title {
4299
+ color: var(--text-primary);
4300
+ font-weight: 600;
4301
+ font-size: 14px;
4302
+ }
4303
+
4304
+ .info-message {
4305
+ color: var(--text-secondary);
4306
+ font-size: 13px;
4307
+ line-height: 1.5;
4308
+ margin-bottom: 12px;
4309
+ }
4310
+
4311
+ .info-details {
4312
+ display: flex;
4313
+ gap: 16px;
4314
+ flex-wrap: wrap;
4315
+ margin-bottom: 12px;
4316
+ font-size: 12px;
4317
+ color: var(--text-secondary);
4318
+ opacity: 0.7;
4319
+ }
4320
+
4321
+ .detail-label {
4322
+ font-weight: 500;
4323
+ }
4324
+
4325
+ .detail-value {
4326
+ font-family: var(--font-mono);
4327
+ opacity: 0.8;
4328
+ }
4329
+
4330
+ .error-action {
4331
+ display: flex;
4332
+ gap: 8px;
4333
+ flex-wrap: wrap;
4334
+ }
4335
+
4336
+ .error-link {
4337
+ display: inline-flex;
4338
+ align-items: center;
4339
+ gap: 6px;
4340
+ padding: 6px 12px;
4341
+ background: rgba(103, 233, 233, 0.15);
4342
+ border: 1px solid rgba(103, 233, 233, 0.3);
4343
+ border-radius: 6px;
4344
+ color: var(--accent-color);
4345
+ text-decoration: none;
4346
+ font-size: 13px;
4347
+ cursor: pointer;
4348
+ transition: all 0.3s ease;
4349
+ }
4350
+
4351
+ .error-link:hover {
4352
+ background: rgba(103, 233, 233, 0.25);
4353
+ border-color: var(--accent-color);
4354
+ }
4355
+
4356
+ .error-retry-btn {
4357
+ background: rgba(103, 233, 233, 0.2);
4358
+ border-color: var(--accent-color);
4359
+ color: var(--accent-color);
4360
+ }
4361
+
4362
+ .error-retry-btn:hover {
4363
+ background: rgba(103, 233, 233, 0.3);
4364
+ }
4365
+ </style>
4366
+ `;
4367
+
4368
+
4369
+ /***/ },
4370
+
4371
+ /***/ 2674
4372
+ (module) {
4373
+
4374
+ module.exports = __WEBPACK_EXTERNAL_MODULE_express__;
4375
+
4376
+ /***/ },
4377
+
4378
+ /***/ 1622
4379
+ (module) {
4380
+
4381
+ module.exports = __WEBPACK_EXTERNAL_MODULE_open__;
4382
+
4383
+ /***/ },
4384
+
4385
+ /***/ 6220
4386
+ (module, __unused_webpack_exports, __webpack_require__) {
4359
4387
 
4388
+ var x = (y) => {
4389
+ var x = {}; __webpack_require__.d(x, y); return x
4390
+ }
4391
+ var y = (x) => (() => (x))
4392
+ module.exports = x({ ["WebSocket"]: () => (__WEBPACK_EXTERNAL_MODULE_ws__.WebSocket), ["WebSocketServer"]: () => (__WEBPACK_EXTERNAL_MODULE_ws__.WebSocketServer) });
4360
4393
 
4361
- /***/ })
4394
+ /***/ }
4362
4395
 
4363
4396
  };