@cloudbase/cloudbase-mcp 2.22.0 → 2.23.1

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,12 +1,9 @@
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__ = {
1
+ export const __webpack_id__ = 341;
2
+ export const __webpack_ids__ = [341];
3
+ export const __webpack_modules__ = {
7
4
 
8
- /***/ 6267
9
- (__unused_webpack_module, exports, __webpack_require__) {
5
+ /***/ 2341:
6
+ /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
10
7
 
11
8
 
12
9
  var __importDefault = (this && this.__importDefault) || function (mod) {
@@ -22,8 +19,8 @@ const http_1 = __importDefault(__webpack_require__(3782));
22
19
  const child_process_1 = __webpack_require__(5814);
23
20
  const open_1 = __importDefault(__webpack_require__(1622));
24
21
  const ws_1 = __webpack_require__(6220);
25
- const index_js_1 = __webpack_require__(9903);
26
- const logger_js_1 = __webpack_require__(781);
22
+ const index_js_1 = __webpack_require__(9529);
23
+ const logger_js_1 = __webpack_require__(3039);
27
24
  function isVSCodeEnvironment() {
28
25
  return Boolean(process.env.VSCODE_IPC_HOOK_CLI ||
29
26
  process.env.VSCODE_PID ||
@@ -2979,873 +2976,254 @@ async function getInteractiveServerSafe(mcpServer) {
2979
2976
  }
2980
2977
 
2981
2978
 
2982
- /***/ },
2979
+ /***/ }),
2983
2980
 
2984
- /***/ 4415
2985
- (__unused_webpack_module, exports) {
2981
+ /***/ 4112:
2982
+ /***/ ((__unused_webpack_module, exports) => {
2986
2983
 
2987
- var __webpack_unused_export__;
2988
2984
 
2989
2985
  /**
2990
- * Reusable UI components for env setup page
2986
+ * HTML template structure
2991
2987
  */
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";
3006
- return `
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>
3032
- `.trim();
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() {
2988
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
2989
+ exports.buildHTMLPage = buildHTMLPage;
2990
+ function buildHTMLPage(css, body, scripts) {
3159
2991
  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>
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>
3173
3005
  `.trim();
3174
3006
  }
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
- }
3254
3007
 
3255
3008
 
3256
- /***/ },
3009
+ /***/ }),
3257
3010
 
3258
- /***/ 4182
3259
- (__unused_webpack_module, exports) {
3011
+ /***/ 6975:
3012
+ /***/ ((__unused_webpack_module, exports) => {
3260
3013
 
3261
- var __webpack_unused_export__;
3262
3014
 
3263
3015
  /**
3264
- * HTML template structure
3016
+ * CSS styles for env setup page
3265
3017
  */
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
- }
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');
3285
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
+ }
3286
3040
 
3287
- /***/ },
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
+ }
3288
3053
 
3289
- /***/ 9903
3290
- (__unused_webpack_module, exports, __webpack_require__) {
3054
+ /* Custom scrollbar styles */
3055
+ ::-webkit-scrollbar {
3056
+ width: 8px;
3057
+ }
3291
3058
 
3292
- var __webpack_unused_export__;
3059
+ ::-webkit-scrollbar-track {
3060
+ background: rgba(255, 255, 255, 0.05);
3061
+ border-radius: 4px;
3062
+ }
3293
3063
 
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
- }
3064
+ ::-webkit-scrollbar-thumb {
3065
+ background: var(--accent-color);
3066
+ border-radius: 4px;
3067
+ }
3358
3068
 
3069
+ ::-webkit-scrollbar-thumb:hover {
3070
+ background: var(--accent-hover);
3071
+ }
3359
3072
 
3360
- /***/ },
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
+ }
3361
3081
 
3362
- /***/ 7335
3363
- (__unused_webpack_module, exports) {
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
+ }
3364
3093
 
3365
- var __webpack_unused_export__;
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
+ }
3366
3098
 
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;
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
+ }
3376
3111
 
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;
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;
3392
3119
  }
3393
3120
 
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';
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);
3413
3130
  }
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';
3131
+ to {
3132
+ opacity: 1;
3133
+ transform: scale(1) translateY(0);
3420
3134
  }
3421
3135
  }
3422
3136
 
3423
- // Clear search
3424
- function clearSearch() {
3425
- const searchInput = document.getElementById('searchInput');
3426
- if (searchInput) {
3427
- searchInput.value = '';
3428
- filterEnvs('');
3429
- searchInput.focus();
3430
- }
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;
3431
3146
  }
3432
3147
 
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
- };
3465
-
3466
- ws.onerror = (error) => {
3467
- console.error('[env-setup] WebSocket error:', error);
3468
- };
3469
-
3470
- ws.onclose = () => {
3471
- console.log('[env-setup] WebSocket closed');
3472
- };
3473
-
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
- }
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;
3484
3155
  }
3485
3156
 
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
- }
3157
+ @keyframes headerShimmer {
3158
+ 0% { transform: translateX(-100%); }
3159
+ 100% { transform: translateX(100%); }
3510
3160
  }
3511
3161
 
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
- }
3162
+ .header-left {
3163
+ display: flex;
3164
+ align-items: center;
3165
+ gap: 16px;
3166
+ z-index: 1;
3527
3167
  }
3528
3168
 
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
- }
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;
3544
3174
  }
3545
3175
 
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
- }
3176
+ @keyframes logoFloat {
3177
+ 0%, 100% { transform: translateY(0px); }
3178
+ 50% { transform: translateY(-3px); }
3575
3179
  }
3576
3180
 
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');
3181
+ .title {
3182
+ font-size: 18px;
3183
+ font-weight: 600;
3184
+ text-shadow: 0 2px 4px rgba(0,0,0,0.1);
3581
3185
  }
3582
3186
 
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
- }
3187
+ .header-right {
3188
+ display: flex;
3189
+ align-items: center;
3190
+ gap: 16px;
3191
+ z-index: 1;
3600
3192
  }
3601
3193
 
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
- }
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;
3611
3202
  }
3612
3203
 
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
- }
3628
-
3629
-
3630
- /***/ },
3204
+ .account-uin {
3205
+ font-size: 12px;
3206
+ color: var(--text-secondary);
3207
+ font-family: var(--font-mono);
3208
+ }
3631
3209
 
3632
- /***/ 7373
3633
- (__unused_webpack_module, exports) {
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
+ }
3634
3222
 
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;
3667
- display: flex;
3668
- align-items: center;
3669
- justify-content: center;
3670
- padding: 20px;
3671
- position: relative;
3672
- overflow-x: hidden;
3673
- overflow-y: auto;
3674
- }
3675
-
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 {
3687
- background: var(--accent-color);
3688
- border-radius: 4px;
3689
- }
3690
-
3691
- ::-webkit-scrollbar-thumb:hover {
3692
- background: var(--accent-hover);
3693
- }
3694
-
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;
3702
- }
3703
-
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;
3714
- }
3715
-
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); }
3719
- }
3720
-
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;
3732
- }
3733
-
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;
3741
- }
3742
-
3743
- @keyframes shimmer {
3744
- 0% { transform: translateX(-100%); }
3745
- 100% { transform: translateX(100%); }
3746
- }
3747
-
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
- }
3757
- }
3758
-
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;
3768
- }
3769
-
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;
3777
- }
3778
-
3779
- @keyframes headerShimmer {
3780
- 0% { transform: translateX(-100%); }
3781
- 100% { transform: translateX(100%); }
3782
- }
3783
-
3784
- .header-left {
3785
- display: flex;
3786
- align-items: center;
3787
- gap: 16px;
3788
- z-index: 1;
3789
- }
3790
-
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;
3796
- }
3797
-
3798
- @keyframes logoFloat {
3799
- 0%, 100% { transform: translateY(0px); }
3800
- 50% { transform: translateY(-3px); }
3801
- }
3802
-
3803
- .title {
3804
- font-size: 18px;
3805
- font-weight: 600;
3806
- text-shadow: 0 2px 4px rgba(0,0,0,0.1);
3807
- }
3808
-
3809
- .header-right {
3810
- display: flex;
3811
- align-items: center;
3812
- gap: 16px;
3813
- z-index: 1;
3814
- }
3815
-
3816
- .account-section {
3817
- display: flex;
3818
- align-items: center;
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;
3824
- }
3825
-
3826
- .account-uin {
3827
- font-size: 12px;
3828
- color: var(--text-secondary);
3829
- font-family: var(--font-mono);
3830
- }
3831
-
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);
3847
- color: var(--accent-color);
3848
- }
3223
+ .btn-switch:hover {
3224
+ background: rgba(255, 255, 255, 0.1);
3225
+ color: var(--accent-color);
3226
+ }
3849
3227
 
3850
3228
  .btn-icon-link {
3851
3229
  display: flex;
@@ -4197,200 +3575,789 @@ exports.CSS_STYLES = `
4197
3575
  animation: spin 0.8s linear infinite;
4198
3576
  }
4199
3577
 
4200
- @keyframes spin {
4201
- to { transform: rotate(360deg); }
4202
- }
3578
+ @keyframes spin {
3579
+ to { transform: rotate(360deg); }
3580
+ }
3581
+
3582
+ .loading span {
3583
+ color: var(--text-secondary);
3584
+ font-size: 14px;
3585
+ }
3586
+
3587
+ /* Success state */
3588
+ .success-state {
3589
+ text-align: center;
3590
+ padding: 40px 20px;
3591
+ animation: fadeInUp 0.8s ease-out both;
3592
+ }
3593
+
3594
+ .success-icon {
3595
+ margin-bottom: 20px;
3596
+ color: var(--accent-color);
3597
+ animation: successPulse 2s ease-in-out infinite;
3598
+ }
3599
+
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
+ }
3609
+ }
3610
+
3611
+ .success-title {
3612
+ font-size: 24px;
3613
+ font-weight: 700;
3614
+ color: var(--text-primary);
3615
+ margin-bottom: 12px;
3616
+ }
3617
+
3618
+ .success-message {
3619
+ color: var(--text-secondary);
3620
+ font-size: 16px;
3621
+ line-height: 1.5;
3622
+ }
3623
+
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;
3630
+ display: flex;
3631
+ align-items: center;
3632
+ gap: 12px;
3633
+ }
3634
+
3635
+ .env-label {
3636
+ color: var(--text-secondary);
3637
+ font-size: 14px;
3638
+ font-weight: 500;
3639
+ }
3640
+
3641
+ .env-value {
3642
+ color: var(--accent-color);
3643
+ font-size: 16px;
3644
+ font-weight: 600;
3645
+ font-family: var(--font-mono);
3646
+ }
3647
+
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;
3655
+ }
3656
+
3657
+ .info-item {
3658
+ margin-bottom: 16px;
3659
+ }
3660
+
3661
+ .info-item:last-child {
3662
+ margin-bottom: 0;
3663
+ }
3664
+
3665
+ .info-header {
3666
+ display: flex;
3667
+ align-items: center;
3668
+ gap: 8px;
3669
+ margin-bottom: 8px;
3670
+ }
3671
+
3672
+ .info-header svg {
3673
+ color: var(--accent-color);
3674
+ }
3675
+
3676
+ .info-title {
3677
+ color: var(--text-primary);
3678
+ font-weight: 600;
3679
+ font-size: 14px;
3680
+ }
3681
+
3682
+ .info-message {
3683
+ color: var(--text-secondary);
3684
+ font-size: 13px;
3685
+ line-height: 1.5;
3686
+ margin-bottom: 12px;
3687
+ }
3688
+
3689
+ .info-details {
3690
+ display: flex;
3691
+ gap: 16px;
3692
+ flex-wrap: wrap;
3693
+ margin-bottom: 12px;
3694
+ font-size: 12px;
3695
+ color: var(--text-secondary);
3696
+ opacity: 0.7;
3697
+ }
3698
+
3699
+ .detail-label {
3700
+ font-weight: 500;
3701
+ }
3702
+
3703
+ .detail-value {
3704
+ font-family: var(--font-mono);
3705
+ opacity: 0.8;
3706
+ }
3707
+
3708
+ .error-action {
3709
+ display: flex;
3710
+ gap: 8px;
3711
+ flex-wrap: wrap;
3712
+ }
3713
+
3714
+ .error-link {
3715
+ display: inline-flex;
3716
+ align-items: center;
3717
+ 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;
3725
+ cursor: pointer;
3726
+ transition: all 0.3s ease;
3727
+ }
3728
+
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);
3737
+ color: var(--accent-color);
3738
+ }
3739
+
3740
+ .error-retry-btn:hover {
3741
+ background: rgba(103, 233, 233, 0.3);
3742
+ }
3743
+ </style>
3744
+ `;
3745
+
3746
+
3747
+ /***/ }),
3748
+
3749
+ /***/ 7053:
3750
+ /***/ ((__unused_webpack_module, exports) => {
3751
+
3752
+
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;
3762
+
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;
3778
+ }
3779
+
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
+ }
3807
+ }
3808
+
3809
+ // Clear search
3810
+ function clearSearch() {
3811
+ const searchInput = document.getElementById('searchInput');
3812
+ if (searchInput) {
3813
+ searchInput.value = '';
3814
+ filterEnvs('');
3815
+ searchInput.focus();
3816
+ }
3817
+ }
3818
+
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
+ }
3870
+ }
3871
+
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
+ }
3896
+ }
3897
+
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
+ }
3913
+ }
3914
+
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
+ }
3930
+ }
3931
+
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
+ }
3961
+ }
3962
+
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');
3967
+ }
3968
+
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
+ }
3986
+ }
3987
+
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
+ }
3997
+ }
3998
+
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
+ }
4014
+
4015
+
4016
+ /***/ }),
4017
+
4018
+ /***/ 7625:
4019
+ /***/ ((__unused_webpack_module, exports) => {
4020
+
4021
+
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
+ }
4287
+
4203
4288
 
4204
- .loading span {
4205
- color: var(--text-secondary);
4206
- font-size: 14px;
4207
- }
4289
+ /***/ }),
4208
4290
 
4209
- /* Success state */
4210
- .success-state {
4211
- text-align: center;
4212
- padding: 40px 20px;
4213
- animation: fadeInUp 0.8s ease-out both;
4214
- }
4291
+ /***/ 9529:
4292
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
4215
4293
 
4216
- .success-icon {
4217
- margin-bottom: 20px;
4218
- color: var(--accent-color);
4219
- animation: successPulse 2s ease-in-out infinite;
4220
- }
4221
4294
 
4222
- @keyframes successPulse {
4223
- 0%, 100% {
4224
- transform: scale(1);
4225
- filter: drop-shadow(0 0 8px rgba(103, 233, 233, 0.3));
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
+ `;
4226
4322
  }
4227
- 50% {
4228
- transform: scale(1.1);
4229
- filter: drop-shadow(0 0 16px rgba(103, 233, 233, 0.6));
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
+ `;
4230
4332
  }
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__) {
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
+ }
4387
4359
 
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) });
4393
4360
 
4394
- /***/ }
4361
+ /***/ })
4395
4362
 
4396
4363
  };