@cloudbase/cloudbase-mcp
Version:
CloudBase MCP Server — operate Tencent CloudBase (database, auth, functions, storage, hosting) from AI coding tools via the Model Context Protocol. Part of CloudBase AI Toolkit.
1,677 lines (1,508 loc) • 153 kB
JavaScript
exports.id = 602;
exports.ids = [602];
exports.modules = {
/***/ 6975:
/***/ ((__unused_webpack_module, exports) => {
"use strict";
/**
* CSS styles for env setup page
*/
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.CSS_STYLES = void 0;
exports.CSS_STYLES = `
<style>
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&display=swap');
* { margin: 0; padding: 0; box-sizing: border-box; }
:root {
--primary-color: #1a1a1a;
--primary-hover: #000000;
--accent-color: #67E9E9;
--accent-hover: #2BCCCC;
--text-primary: #ffffff;
--text-secondary: #a0a0a0;
--border-color: rgba(255, 255, 255, 0.15);
--bg-secondary: rgba(255, 255, 255, 0.08);
--bg-glass: rgba(26, 26, 26, 0.95);
--shadow: 0 25px 50px rgba(0, 0, 0, 0.3), 0 10px 20px rgba(0, 0, 0, 0.2);
--font-mono: 'JetBrains Mono', 'SF Mono', 'Monaco', monospace;
--header-bg: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 50%, #0d1117 100%);
}
body {
font-family: var(--font-mono);
background: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 100%);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
position: relative;
overflow-x: hidden;
overflow-y: auto;
}
/* Custom scrollbar styles */
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: rgba(255, 255, 255, 0.05);
border-radius: 4px;
}
::-webkit-scrollbar-thumb {
background: var(--accent-color);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--accent-hover);
}
body::before {
content: '';
position: fixed;
top: 0; left: 0; right: 0; bottom: 0;
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;
pointer-events: none;
z-index: -1;
}
body::after {
content: '';
position: fixed;
top: 50%; left: 50%;
width: 500px; height: 500px;
background: radial-gradient(circle, rgba(103, 233, 233, 0.05) 0%, transparent 70%);
transform: translate(-50%, -50%);
pointer-events: none;
z-index: -1;
animation: pulse 8s ease-in-out infinite;
}
@keyframes pulse {
0%, 100% { opacity: 0.3; transform: translate(-50%, -50%) scale(1); }
50% { opacity: 0.6; transform: translate(-50%, -50%) scale(1.1); }
}
.modal {
background: var(--bg-glass);
backdrop-filter: blur(20px);
border-radius: 20px;
box-shadow: var(--shadow);
border: 1px solid var(--border-color);
width: 100%;
max-width: 640px;
overflow: hidden;
animation: modalIn 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275);
position: relative;
}
.modal::before {
content: '';
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.02) 50%, transparent 70%);
animation: shimmer 3s infinite;
pointer-events: none;
}
@keyframes shimmer {
0% { transform: translateX(-100%); }
100% { transform: translateX(100%); }
}
@keyframes modalIn {
from {
opacity: 0;
transform: scale(0.9) translateY(-20px);
}
to {
opacity: 1;
transform: scale(1) translateY(0);
}
}
.header {
background: var(--header-bg);
color: var(--text-primary);
padding: 20px 32px;
display: flex;
align-items: center;
justify-content: space-between;
position: relative;
overflow: hidden;
}
.header::before {
content: '';
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.03) 50%, transparent 70%);
animation: headerShimmer 4s infinite;
pointer-events: none;
}
@keyframes headerShimmer {
0% { transform: translateX(-100%); }
100% { transform: translateX(100%); }
}
.header-left {
display: flex;
align-items: center;
gap: 16px;
z-index: 1;
}
.logo {
width: 32px;
height: 32px;
filter: drop-shadow(0 4px 8px rgba(0,0,0,0.2));
animation: logoFloat 3s ease-in-out infinite;
}
@keyframes logoFloat {
0%, 100% { transform: translateY(0px); }
50% { transform: translateY(-3px); }
}
.title {
font-size: 18px;
font-weight: 600;
text-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.header-right {
display: flex;
align-items: center;
gap: 16px;
z-index: 1;
}
.account-section {
display: flex;
align-items: center;
gap: 8px;
padding: 6px 12px;
background: rgba(255, 255, 255, 0.04);
border: 1px solid var(--border-color);
border-radius: 8px;
}
.account-uin {
font-size: 12px;
color: var(--text-secondary);
font-family: var(--font-mono);
}
.btn-switch {
display: flex;
align-items: center;
justify-content: center;
padding: 4px;
background: transparent;
border: none;
color: var(--text-secondary);
cursor: pointer;
transition: all 0.3s ease;
border-radius: 4px;
}
.btn-switch:hover {
background: rgba(255, 255, 255, 0.1);
color: var(--accent-color);
}
.btn-icon-link {
display: flex;
align-items: center;
justify-content: center;
padding: 7px;
background: transparent;
border: 1px solid var(--border-color);
border-radius: 8px;
color: var(--text-primary);
cursor: pointer;
transition: all 0.3s ease;
text-decoration: none;
}
.btn-icon-link:hover {
background: rgba(255, 255, 255, 0.08);
border-color: var(--accent-color);
}
.content {
padding: 32px 32px 28px;
}
.content-title {
font-size: 20px;
font-weight: 600;
color: var(--text-primary);
margin-bottom: 28px;
text-align: center;
letter-spacing: -0.01em;
}
/* Search section styles */
.search-section {
display: flex;
gap: 10px;
margin-bottom: 24px;
}
.search-box {
position: relative;
flex: 1;
}
.search-icon {
position: absolute;
left: 14px;
top: 50%;
transform: translateY(-50%);
color: var(--text-secondary);
pointer-events: none;
z-index: 1;
}
.search-input {
width: 100%;
padding: 11px 38px 11px 38px;
background: var(--bg-secondary);
border: 1px solid var(--border-color);
border-radius: 10px;
color: var(--text-primary);
font-size: 13px;
font-family: var(--font-mono);
transition: all 0.3s ease;
}
.search-input:focus {
outline: none;
border-color: var(--accent-color);
background: rgba(255, 255, 255, 0.1);
box-shadow: 0 0 0 3px rgba(103, 233, 233, 0.08);
}
.search-input::placeholder {
color: var(--text-secondary);
opacity: 0.6;
}
.search-clear {
position: absolute;
right: 12px;
top: 50%;
transform: translateY(-50%);
background: transparent;
border: none;
color: var(--text-secondary);
cursor: pointer;
padding: 4px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
transition: all 0.3s ease;
z-index: 1;
}
.search-clear:hover {
color: var(--text-primary);
background: rgba(255, 255, 255, 0.1);
}
.search-actions {
display: flex;
gap: 8px;
}
.btn-action {
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
padding: 11px 14px;
background: var(--bg-secondary);
border: 1px solid var(--border-color);
border-radius: 10px;
color: var(--text-secondary);
cursor: pointer;
transition: all 0.3s ease;
}
.btn-action:hover {
background: rgba(255, 255, 255, 0.1);
border-color: rgba(103, 233, 233, 0.5);
color: var(--accent-color);
}
.btn-action:active {
transform: scale(0.95);
}
.btn-text {
font-size: 13px;
font-weight: 500;
}
.env-list {
max-height: 340px;
overflow-y: auto;
padding-right: 6px;
margin-bottom: 24px;
}
.env-list::-webkit-scrollbar {
width: 5px;
}
.env-list::-webkit-scrollbar-track {
background: transparent;
}
.env-list::-webkit-scrollbar-thumb {
background: var(--accent-color);
border-radius: 3px;
}
/* Env item styles */
.env-item {
display: flex;
align-items: center;
gap: 14px;
padding: 14px 16px;
background: var(--bg-secondary);
border: 1px solid var(--border-color);
border-radius: 10px;
margin-bottom: 10px;
cursor: pointer;
transition: all 0.3s ease;
position: relative;
}
.env-item:hover {
background: rgba(255, 255, 255, 0.1);
border-color: rgba(103, 233, 233, 0.5);
transform: translateX(2px);
}
.env-item.selected {
background: rgba(103, 233, 233, 0.12);
border-color: var(--accent-color);
box-shadow: 0 0 0 1px rgba(103, 233, 233, 0.2);
}
.env-item.selected::after {
content: '';
position: absolute;
right: 16px;
top: 50%;
transform: translateY(-50%);
width: 6px;
height: 6px;
background: var(--accent-color);
border-radius: 50%;
box-shadow: 0 0 8px var(--accent-color);
}
.env-info {
flex: 1;
min-width: 0;
}
.env-name {
font-size: 15px;
font-weight: 500;
color: var(--text-primary);
margin-bottom: 5px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
letter-spacing: -0.01em;
}
.env-name.unnamed {
opacity: 0.5;
}
.env-id {
font-size: 11px;
color: var(--text-secondary);
font-family: var(--font-mono);
word-break: break-all;
opacity: 0.8;
}
/* Empty state */
.empty-state {
padding: 60px 20px;
text-align: center;
}
.empty-message {
font-size: 14px;
color: var(--text-secondary);
opacity: 0.7;
line-height: 1.6;
}
.create-env-link {
color: var(--accent-color);
text-decoration: none;
border-bottom: 1px solid transparent;
transition: all 0.3s ease;
}
.create-env-link:hover {
border-bottom-color: var(--accent-color);
opacity: 0.8;
}
/* Action buttons */
.actions {
display: flex;
gap: 10px;
margin-top: 28px;
}
.btn {
flex: 1;
padding: 12px 20px;
border: none;
border-radius: 10px;
font-size: 13px;
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
font-family: var(--font-mono);
letter-spacing: -0.01em;
}
.btn-primary {
background: var(--accent-color);
color: var(--primary-color);
border: 1px solid var(--accent-color);
}
.btn-primary:hover:not(:disabled) {
background: var(--accent-hover);
box-shadow: 0 4px 12px rgba(103, 233, 233, 0.3);
}
.btn-primary:disabled {
background: var(--bg-secondary);
color: var(--text-secondary);
cursor: not-allowed;
opacity: 0.5;
border-color: var(--border-color);
}
.btn-secondary {
background: transparent;
color: var(--text-primary);
border: 1px solid var(--border-color);
}
.btn-secondary:hover {
background: var(--bg-secondary);
border-color: rgba(255, 255, 255, 0.3);
}
/* Help links */
.help-links {
display: flex;
gap: 20px;
justify-content: center;
margin-top: 24px;
padding-top: 24px;
border-top: 1px solid rgba(255, 255, 255, 0.06);
}
.help-link {
display: flex;
align-items: center;
gap: 6px;
color: var(--text-secondary);
text-decoration: none;
font-size: 12px;
padding: 6px 10px;
border-radius: 6px;
transition: all 0.3s ease;
opacity: 0.8;
}
.help-link:hover {
background: rgba(103, 233, 233, 0.08);
color: var(--accent-color);
opacity: 1;
}
/* Loading state */
.loading {
display: none;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 40px;
gap: 20px;
}
.spinner {
width: 40px;
height: 40px;
border: 3px solid var(--border-color);
border-top-color: var(--accent-color);
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
.loading span {
color: var(--text-secondary);
font-size: 14px;
}
/* Success state */
.success-state {
text-align: center;
padding: 40px 20px;
animation: fadeInUp 0.8s ease-out both;
}
.success-icon {
margin-bottom: 20px;
color: var(--accent-color);
animation: successPulse 2s ease-in-out infinite;
}
@keyframes successPulse {
0%, 100% {
transform: scale(1);
filter: drop-shadow(0 0 8px rgba(103, 233, 233, 0.3));
}
50% {
transform: scale(1.1);
filter: drop-shadow(0 0 16px rgba(103, 233, 233, 0.6));
}
}
.success-title {
font-size: 24px;
font-weight: 700;
color: var(--text-primary);
margin-bottom: 12px;
}
.success-message {
color: var(--text-secondary);
font-size: 16px;
line-height: 1.5;
}
.selected-env-info {
margin-top: 20px;
padding: 16px;
background: rgba(103, 233, 233, 0.1);
border: 1px solid var(--accent-color);
border-radius: 12px;
display: flex;
align-items: center;
gap: 12px;
}
.env-label {
color: var(--text-secondary);
font-size: 14px;
font-weight: 500;
}
.env-value {
color: var(--accent-color);
font-size: 16px;
font-weight: 600;
font-family: var(--font-mono);
}
/* Info banner (for non-critical notifications) */
.info-banner {
margin-bottom: 20px;
padding: 16px;
background: rgba(103, 233, 233, 0.08);
border: 1px solid rgba(103, 233, 233, 0.2);
border-radius: 12px;
}
.info-item {
margin-bottom: 16px;
}
.info-item:last-child {
margin-bottom: 0;
}
.info-header {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 8px;
}
.info-header svg {
color: var(--accent-color);
}
.info-title {
color: var(--text-primary);
font-weight: 600;
font-size: 14px;
}
.info-message {
color: var(--text-secondary);
font-size: 13px;
line-height: 1.5;
margin-bottom: 12px;
}
.info-details {
display: flex;
gap: 16px;
flex-wrap: wrap;
margin-bottom: 12px;
font-size: 12px;
color: var(--text-secondary);
opacity: 0.7;
}
.detail-label {
font-weight: 500;
}
.detail-value {
font-family: var(--font-mono);
opacity: 0.8;
}
.error-action {
display: flex;
gap: 8px;
flex-wrap: wrap;
}
.error-link {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 6px 12px;
background: rgba(103, 233, 233, 0.15);
border: 1px solid rgba(103, 233, 233, 0.3);
border-radius: 6px;
color: var(--accent-color);
text-decoration: none;
font-size: 13px;
cursor: pointer;
transition: all 0.3s ease;
}
.error-link:hover {
background: rgba(103, 233, 233, 0.25);
border-color: var(--accent-color);
}
.error-retry-btn {
background: rgba(103, 233, 233, 0.2);
border-color: var(--accent-color);
color: var(--accent-color);
}
.error-retry-btn:hover {
background: rgba(103, 233, 233, 0.3);
}
</style>
`;
/***/ }),
/***/ 19246:
/***/ ((module) => {
function webpackEmptyContext(req) {
var e = new Error("Cannot find module '" + req + "'");
e.code = 'MODULE_NOT_FOUND';
throw e;
}
webpackEmptyContext.keys = () => ([]);
webpackEmptyContext.resolve = webpackEmptyContext;
webpackEmptyContext.id = 19246;
module.exports = webpackEmptyContext;
/***/ }),
/***/ 47053:
/***/ ((__unused_webpack_module, exports) => {
"use strict";
/**
* JavaScript logic for env setup page
*/
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.getJavaScripts = getJavaScripts;
function getJavaScripts(wsPort) {
return `
<script>
let selectedEnvId = null;
// Select environment
function selectEnv(envId, element) {
console.log('[env-setup] Selecting environment:', envId);
selectedEnvId = envId;
// Remove selected class from all items
document.querySelectorAll('.env-item').forEach(item => {
item.classList.remove('selected');
});
// Add selected class to current item
element.classList.add('selected');
// Enable confirm button
document.getElementById('confirmBtn').disabled = false;
}
// Filter environments
function filterEnvs(searchTerm) {
const items = document.querySelectorAll('.env-item');
const searchClear = document.getElementById('searchClear');
let visibleCount = 0;
items.forEach(item => {
const name = item.querySelector('.env-name').textContent.toLowerCase();
const id = item.querySelector('.env-id').textContent.toLowerCase();
const match = name.includes(searchTerm.toLowerCase()) ||
id.includes(searchTerm.toLowerCase());
item.style.display = match ? 'flex' : 'none';
if (match) visibleCount++;
});
// Show/hide clear button
if (searchClear) {
searchClear.style.display = searchTerm ? 'flex' : 'none';
}
// Show/hide no results message
const noResults = document.getElementById('noResults');
if (noResults) {
const hasItems = items.length > 0;
noResults.style.display = visibleCount === 0 && hasItems ? 'block' : 'none';
}
}
// Clear search
function clearSearch() {
const searchInput = document.getElementById('searchInput');
if (searchInput) {
searchInput.value = '';
filterEnvs('');
searchInput.focus();
}
}
// WebSocket: same host as page so it works in remote VS Code / Cloud IDE (no localhost)
const wsScheme = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
const wsUrl = wsScheme + '//' + window.location.host;
const ws = new WebSocket(wsUrl);
ws.onopen = () => {
console.log('[env-setup] WebSocket connected');
// Send session ID to server to associate this WebSocket with the session
const sessionId = window.location.pathname.split('/').pop();
ws.send(JSON.stringify({
type: 'registerSession',
sessionId: sessionId
}));
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log('[env-setup] Received message:', data);
if (data.type === 'success' && data.envId) {
showSuccess(data.envId);
} else if (data.type === 'envListRefreshed') {
if (data.success) {
console.log('[env-setup] Environment list refreshed, reloading page');
// Reload the page to show updated environment list
window.location.reload();
} else {
console.error('[env-setup] Failed to refresh environment list:', data.error);
alert('刷新环境列表失败: ' + (data.error || '未知错误'));
}
}
};
ws.onerror = (error) => {
console.error('[env-setup] WebSocket error:', error);
};
ws.onclose = () => {
console.log('[env-setup] WebSocket closed');
};
// Show success state
function showSuccess(envId) {
document.querySelector('.content').style.display = 'none';
const successState = document.getElementById('successState');
const selectedEnvDisplay = document.getElementById('selectedEnvDisplay');
if (successState && selectedEnvDisplay) {
selectedEnvDisplay.textContent = envId;
successState.style.display = 'block';
}
}
// Confirm selection
function confirm() {
if (!selectedEnvId) {
console.warn('[env-setup] No environment selected');
return;
}
console.log('[env-setup] Confirming selection:', selectedEnvId);
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({
type: 'envId',
data: selectedEnvId,
cancelled: false
}));
// Close window immediately after sending confirmation
setTimeout(() => {
window.close();
}, 100);
} else {
console.error('[env-setup] WebSocket not connected');
alert('连接已断开,请刷新页面重试');
}
}
// Cancel
function cancel() {
console.log('[env-setup] Cancelling');
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({
type: 'envId',
data: null,
cancelled: true
}));
// Close window immediately after sending cancellation
setTimeout(() => {
window.close();
}, 100);
}
}
// Switch account
function switchAccount() {
console.log('[env-setup] Switching account');
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({
type: 'envId',
data: null,
switch: true
}));
// Close window immediately after sending switch request
setTimeout(() => {
window.close();
}, 100);
}
}
// Universal URL opener - works with all IDEs including CodeBuddy
async function openUrl(event, url) {
if (event) {
event.preventDefault();
}
console.log('[env-setup] Opening URL:', url);
try {
const response = await fetch('/api/open-url', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ url }),
});
const result = await response.json();
if (!result.success) {
console.error('[env-setup] Failed to open URL:', result.error);
// Fallback to direct open if API fails
window.open(url, '_blank');
}
} catch (error) {
console.error('[env-setup] Error opening URL:', error);
// Fallback to direct open if API fails
window.open(url, '_blank');
}
}
// Create new environment
function createNewEnv() {
console.log('[env-setup] Creating new environment');
openUrl(null, 'https://buy.cloud.tencent.com/lowcode?buyType=tcb&channel=mcp');
}
// Refresh environment list
function refreshEnvList() {
console.log('[env-setup] Refreshing environment list');
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({
type: 'refreshEnvList'
}));
// Add rotation animation
const btn = event.target.closest('.btn-refresh');
if (btn) {
btn.style.transform = 'rotate(360deg)';
setTimeout(() => {
btn.style.transform = 'rotate(0deg)';
}, 600);
}
}
}
// Retry init TCB
function retryInitTcb(sessionId) {
console.log('[env-setup] Retrying TCB initialization:', sessionId);
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({
type: 'retryInitTcb',
sessionId: sessionId
}));
}
}
// Initialize on page load
window.addEventListener('load', () => {
// Auto-select first environment if exists
const firstEnvItem = document.querySelector('.env-item');
if (firstEnvItem && !selectedEnvId) {
const envId = firstEnvItem.getAttribute('onclick')?.match(/selectEnv\\('([^']+)'/)?.[1];
if (envId) {
selectEnv(envId, firstEnvItem);
console.log('[env-setup] Auto-selected first environment:', envId);
}
}
});
</script>
`.trim();
}
/***/ }),
/***/ 64112:
/***/ ((__unused_webpack_module, exports) => {
"use strict";
/**
* HTML template structure
*/
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.buildHTMLPage = buildHTMLPage;
function buildHTMLPage(css, body, scripts) {
return `
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CloudBase MCP - 环境配置</title>
${css}
</head>
<body>
${body}
${scripts}
</body>
</html>
`.trim();
}
/***/ }),
/***/ 67625:
/***/ ((__unused_webpack_module, exports) => {
"use strict";
/**
* Reusable UI components for env setup page
*/
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.renderHeader = renderHeader;
exports.renderSearchBox = renderSearchBox;
exports.renderEnvItem = renderEnvItem;
exports.renderEmptyState = renderEmptyState;
exports.renderNoResultsState = renderNoResultsState;
exports.renderHelpLinks = renderHelpLinks;
exports.renderActionButtons = renderActionButtons;
exports.renderLoadingState = renderLoadingState;
exports.renderSuccessState = renderSuccessState;
exports.renderErrorBanner = renderErrorBanner;
function renderHeader(accountInfo, ide) {
const hasAccount = !!accountInfo?.uin;
const isCodeBuddy = ide === "CodeBuddy";
return `
<div class="header">
<div class="header-left">
<img class="logo" src="https://7463-tcb-advanced-a656fc-1257967285.tcb.qcloud.la/mcp/cloudbase-logo.svg" alt="CloudBase Logo" />
<span class="title">CloudBase</span>
</div>
${(hasAccount && accountInfo.region !== 'ap-singapore') ? /** 国际站不支持切 */ `
<div class="header-right">
<div class="account-section">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/>
<circle cx="12" cy="7" r="4"/>
</svg>
<span class="account-uin">${accountInfo.uin}</span>
${accountInfo.region ? `<span class="account-region">${accountInfo.region}</span>` : ''}
${!isCodeBuddy ? `
<button class="btn-switch" onclick="switchAccount()" title="切换账号">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<path d="M17 2l4 4-4 4M7 22l-4-4 4-4M21 6H10M3 18h11"/>
</svg>
</button>
` : ''}
</div>
</div>
` : ''}
</div>
`.trim();
}
function renderSearchBox() {
return `
<div class="search-section">
<div class="search-box">
<svg class="search-icon" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<circle cx="11" cy="11" r="8"/>
<path d="m21 21-4.35-4.35"/>
</svg>
<input
type="text"
id="searchInput"
class="search-input"
placeholder="搜索环境名称或 ID..."
oninput="filterEnvs(this.value)"
/>
<button class="search-clear" onclick="clearSearch()" id="searchClear" style="display: none;">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<path d="M18 6L6 18M6 6l12 12"/>
</svg>
</button>
</div>
<div class="search-actions">
<button class="btn-action" onclick="createNewEnv()" title="新建环境">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<path d="M12 5v14M5 12h14"/>
</svg>
<span class="btn-text">新建环境</span>
</button>
<button class="btn-action" onclick="refreshEnvList()" title="刷新环境列表">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<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"/>
</svg>
</button>
</div>
</div>
`.trim();
}
function renderEnvItem(env, index) {
const alias = env.Alias || '(未命名)';
const envId = env.EnvId;
const hasAlias = !!env.Alias;
return `
<div class="env-item" onclick="selectEnv('${envId}', this)">
<div class="env-info">
<div class="env-name ${!hasAlias ? 'unnamed' : ''}">${alias}</div>
<div class="env-id">${envId}</div>
</div>
</div>
`.trim();
}
function renderEmptyState(hasInitError) {
return `
<div class="empty-state">
<p class="empty-message">
暂无环境,请先<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>,然后点击刷新按钮重试
</p>
</div>
`.trim();
}
function renderNoResultsState() {
return `
<div class="empty-state" id="noResults" style="display: none;">
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="opacity: 0.3;">
<circle cx="11" cy="11" r="8"/>
<path d="m21 21-4.35-4.35"/>
</svg>
<p class="empty-message">未找到匹配的环境</p>
</div>
`.trim();
}
function renderHelpLinks() {
return `
<div class="help-links">
<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">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
<polyline points="14 2 14 8 20 8"/>
<line x1="16" y1="13" x2="8" y2="13"/>
<line x1="16" y1="17" x2="8" y2="17"/>
</svg>
帮助文档
</a>
<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">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<polygon points="23 7 16 12 23 17 23 7"/>
<rect x="1" y="5" width="15" height="14" rx="2" ry="2"/>
</svg>
视频教程
</a>
<a href="https://github.com/TencentCloudBase/CloudBase-AI-ToolKit" onclick="openUrl(event, 'https://github.com/TencentCloudBase/CloudBase-AI-ToolKit'); return false;" class="help-link">
<svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor">
<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"/>
</svg>
GitHub
</a>
</div>
`.trim();
}
function renderActionButtons(hasEnvs, hasInitError) {
return `
<div class="actions">
<button class="btn btn-secondary" onclick="cancel()">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<path d="M18 6L6 18M6 6l12 12"/>
</svg>
取消
</button>
<button class="btn btn-primary" id="confirmBtn" onclick="confirm()" disabled>
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<path d="M20 6L9 17l-5-5"/>
</svg>
确认选择
</button>
</div>
`.trim();
}
function renderLoadingState() {
return `
<div class="loading" id="loading" style="display: none;">
<div class="spinner"></div>
<span>正在配置环境...</span>
</div>
`.trim();
}
function renderSuccessState() {
return `
<div class="success-state" id="successState" style="display: none;">
<div class="success-icon">
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M20 6L9 17l-5-5"/>
</svg>
</div>
<h2 class="success-title">环境配置成功!</h2>
<p class="success-message">已成功选择 CloudBase 环境</p>
<div class="selected-env-info">
<span class="env-label">环境 ID:</span>
<span class="env-value" id="selectedEnvDisplay"></span>
</div>
</div>
`.trim();
}
function renderErrorBanner(errorContext, sessionId) {
const initTcbError = errorContext?.initTcbError;
const createEnvError = errorContext?.createEnvError;
// Only show initTcbError, hide createEnvError
if (!initTcbError) {
return '';
}
return `
<div class="info-banner" id="errorBanner">
${initTcbError ? `
<div class="info-item">
<div class="info-header">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="10"/>
<line x1="12" y1="8" x2="12" y2="12"/>
<line x1="12" y1="16" x2="12.01" y2="16"/>
</svg>
<span class="info-title">${escapeHtml(initTcbError.message)}</span>
</div>
<div class="info-message">${escapeHtml(initTcbError.actionText || '')}</div>
${initTcbError.requestId ? `
<div class="info-details">
<span class="detail-label">错误码:</span> <span class="detail-value">${escapeHtml(initTcbError.code)}</span>
<span class="detail-label">请求 ID:</span> <span class="detail-value">${escapeHtml(initTcbError.requestId)}</span>
</div>
` : ''}
${initTcbError.needRealNameAuth ? `
<div class="error-action">
<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">
前往实名认证
</a>
</div>
` : ''}
${initTcbError.needCamAuth ? `
<div class="error-action">
<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">
前往开通 CloudBase 服务
</a>
${sessionId ? `
<button class="error-link error-retry-btn" onclick="retryInitTcb('${sessionId}')">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<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"/>
</svg>
重试
</button>
` : ''}
</div>
` : ''}
${!initTcbError.needRealNameAuth && !initTcbError.needCamAuth && initTcbError.helpUrl ? `
<div class="error-action">
<a href="${initTcbError.helpUrl}" onclick="openUrl(event, '${initTcbError.helpUrl}'); return false;" class="error-link">
前往开通 CloudBase 服务
</a>
${sessionId ? `
<button class="error-link error-retry-btn" onclick="retryInitTcb('${sessionId}')">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<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"/>
</svg>
重试
</button>
` : ''}
</div>
` : ''}
</div>
` : ''}
</div>
`.trim();
}
// Helper function to escape HTML
function escapeHtml(text) {
const map = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
};
return text.replace(/[&<>"']/g, (m) => map[m]);
}
/***/ }),
/***/ 79529:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
"use strict";
/**
* Main renderer for env setup page
*/
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.renderEnvSetupPage = renderEnvSetupPage;
const components_js_1 = __webpack_require__(67625);
const html_js_1 = __webpack_require__(64112);
const scripts_js_1 = __webpack_require__(47053);
const styles_js_1 = __webpack_require__(6975);
/**
* Render the complete env setup page
*/
function renderEnvSetupPage(options) {
const { envs = [], accountInfo, errorContext, sessionId, wsPort, ide } = options;
const hasEnvs = envs.length > 0;
const hasInitError = !!errorContext?.initTcbError;
const hasErrors = !!(errorContext?.initTcbError || errorContext?.createEnvError);
// Build env list HTML
let envListHTML = '';
if (hasEnvs) {
envListHTML = `
${(0, components_js_1.renderSearchBox)()}
<div class="env-list" id="envList">
${envs.map((env, index) => (0, components_js_1.renderEnvItem)(env, index)).join('\n')}
</div>
${(0, components_js_1.renderNoResultsState)()}
`;
}
else {
// 暂无环境时也显示搜索框、新建和刷新按钮
envListHTML = `
${(0, components_js_1.renderSearchBox)()}
<div class="env-list" id="envList">
${(0, components_js_1.renderEmptyState)(hasInitError)}
</div>
${(0, components_js_1.renderNoResultsState)()}
`;
}
// Build body HTML
const bodyHTML = `
<div class="modal">
${(0, components_js_1.renderHeader)(accountInfo, ide)}
<div class="content">
<h1 class="content-title">选择环境</h1>
${hasErrors ? (0, components_js_1.renderErrorBanner)(errorContext, sessionId) : ''}
${envListHTML}
${(0, components_js_1.renderActionButtons)(hasEnvs, hasInitError)}
${(0, components_js_1.renderHelpLinks)()}
${(0, components_js_1.renderLoadingState)()}
${(0, components_js_1.renderSuccessState)()}
</div>
</div>
`;
// Get JavaScript with WebSocket port
const scripts = (0, scripts_js_1.getJavaScripts)(wsPort);
// Assemble final HTML
return (0, html_js_1.buildHTMLPage)(styles_js_1.CSS_STYLES, bodyHTML, scripts);
}
/***/ }),
/***/ 92341:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.InteractiveServer = void 0;
exports.getInteractiveServer = getInteractiveServer;
exports.resetInteractiveServer = resetInteractiveServer;
exports.getInteractiveServerSafe = getInteractiveServerSafe;
const express_1 = __importDefault(__webpack_require__(26083));
const http_1 = __importDefault(__webpack_require__(81630));
const child_process_1 = __webpack_require__(79646);
const open_1 = __importDefault(__webpack_require__(83440));
const ws_1 = __webpack_require__(17699);
const index_js_1 = __webpack_require__(79529);
const logger_js_1 = __webpack_require__(13039);
function isVSCodeEnvironment() {
return Boolean(process.env.VSCODE_IPC_HOOK_CLI ||
process.env.VSCODE_PID ||
process.env.TERM_PROGRAM === "vscode");
}
/**
* Validates that a URL is safe to open, blocking SSRF targets.
* Only allows http/https schemes and rejects private/reserved IP ranges
* and sensitive hostnames.
*/
function isUrlSafeToOpen(url) {
let parsed;
try {
parsed = new URL(url);
}
catch {
return { safe: false, reason: "Invalid URL format" };
}
// Only allow http and https schemes
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
return { safe: false, reason: `Unsupported scheme: ${parsed.protocol}` };
}
const hostname = parsed.hostname.toLowerCase();
// Block common sensitive / internal hostnames
const blockedHostnames = [
"localhost",
"localhost.localdomain",
"ip6-localhost",
"ip6-loopback",
"metadata.google.internal",
"metadata.internal",
];
if (blockedHostnames.includes(hostname)) {
return { safe: false, reason: `Blocked hostname: ${hostname}` };
}
// Block hostnames ending with .internal or .local
if (hostname.endsWith(".internal") || hostname.endsWith(".local")) {
return { safe: false, reason: `Blocked internal hostname: ${hostname}` };
}
// Block IP addresses in private/reserved ranges (RFC 1918, loopback, link-local, etc.)
const ipv4Regex = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
const match = ipv4Regex.exec(hostname);
if (match) {
const octets = [parseInt(match[1], 10), parseInt(match[2], 10), parseInt(match[3], 10), parseInt(match[4], 10)];
// Loopback: 127.0.0.0/8
if (octets[0] === 127) {
return { safe: false, reason: "Blocked loopback IP address" };
}
// Link-local: 169.254.0.0/16
if (octets[0] === 169 && octets[1] === 254) {
return { safe: false, reason: "Blocked link-local IP address" };
}
// RFC 1918 private: 10.0.0.0/8
if (octets[0] === 10) {
return { safe: false, reason: "Blocked private IP address (10.x.x.x)" };
}
// RFC 1918 private: 172.16.0.0/12
if (octets[0] === 172 && octets[1] >= 16 && octets[1] <= 31) {
return { safe: false, reason: "Blocked private IP address (172.16-31.x.x)" };
}
// RFC 1918 private: 192.168.0.0/16
if (octets[0] === 192 && octets[1] === 168) {
return { safe: false, reason: "Blocked private IP address (192.168.x.x)" };
}
// Broadcast: 0.0.0.0
if (octets[0] === 0 && octets[1] === 0 && octets[2] === 0 && octets[3] === 0) {
return { safe: false, reason: "Blocked broadcast address" };
}
}
// Block IPv6 loopback and link-local
if (hostname.startsWith("[") && hostname.endsWith("]")) {
const ipv6 = hostname.slice(1, -1).toLowerCase();
if (ipv6 === "::1" || ipv6 === "0:0:0:0:0:0:0:1" || ipv6 === "::" || ipv6 === "0:0:0:0:0:0:0:0") {
return { safe: false, reason: "Blocked IPv6 loopback/reserved address" };
}
if (ipv6.startsWith("fe80:")) {
return { safe: false, reason: "Blocked IPv6 link-local address" };
}
if (ipv6.startsWith("fc") || ipv6.startsWith("fd")) {
return { safe: false, reason: "Blocked IPv6 unique-local address" };
}
}
return { safe: true };
}
function parseBrowserCommand(browser) {
const parts = browser.match(/(?:[^\s"]+|"[^"]*")+/g) || [];
return parts.map((item) => item.replace(/^"(.*)"$/, "$1"));
}
async function openUrlByBrowserEnv(url) {
const browser = process.env.BROWSER?.trim();
if (!browser) {
return false;
}
const [command, ...args] = parseBrowserCommand(browser);
if (!command) {
return false;
}
const finalArgs = args.map((arg) => (arg === "%s" ? url : arg));
if (!args.includes("%s")) {
finalArgs.push(url);
}
return new Promise((resolve) => {
(0, child_process_1.execFile)(command, finalArgs, (execError) => {
resolve(!execError);
});
});
}
function shouldUseBrowserEnvFallback() {
return process.platform === "linux" && isVSCodeEnvironment();
}
// Dynamic open behavior with IDE awareness and VSCode/Linux fallback
async function openUrl(url, options, mcpServer) {
// mcpServer 是 ExtendedMcpServer 实例,它有 server 和 ide 属性
// server 属性是 MCP server 的内部 server 实例,有 sendLoggingMessage 方法
const currentIde = mcpServer?.ide || process.env.INTEGRATION_IDE;
const internalServer = mcpServer?.server; // 内部的 server 实例
(0, logger_js_1.debug)(`[openUrl] Checking IDE: ${currentIde}`);
(0, logger_js_1.debug)(`[openUrl] mcpServer type: ${typeof mcpServer}, has server: ${!!mcpServer?.server}, has ide: ${!!mcpServer?.ide}`);
if (internalServer) {
(0, logger_js_1.debug)(`[openUrl] internalServer type: ${typeof internalServer}, has sendLoggingMessage: ${typeof internalServer.sendLoggingMessage === 'function'}`);
}
// 检查是否为 CodeBuddy IDE (优先使用 mcpServer.ide,回退到环境变量)
if (currentIde === "CodeBuddy" && internalServer && typeof internalServer.sendLoggingMessage === 'function') {
try {
// internalServer 是 MCP server 的内部 server 实例,有 sendLoggingMessage 方法
internalServer.sendLoggingMessage({
level: "notice",
data: {
type: "tcb",
url: url,
},
});
(0, logger_js_1.info)(`CodeBuddy IDE: 已发送网页打开通知 - ${url}`);
return;
}
catch (err) {
(0, logger_js_1.error)(`Failed to send logging message for ${url}: ${err instanceof Error ? err.message : err}`, err instanceof Error ? err : new Error(String(err)));
// 如果发送通知失败,在 CodeBuddy IDE 中不打开网页,直接返回
(0, logger_js_1.warn)(`CodeBuddy IDE: 发送通知失败,不打开网页 - ${url}`);
return;
}
}
// 默认行为:直接打开网页(带 VSCode/Linux 降级逻辑)
(0, logger_js_1.debug)(`[openUrl] Opening URL in browser: ${url}`);
try {
const openOptions = options ? { url: true, ...options } : { url: true };
const child = await (0, open_1.default)(url, openOptions);
if (child?.once) {
child.once("error", async () => {
if (shouldUseBrowserEnvFallback()) {
(0, logger_js_1.debug)("[openUrl] open() failed, trying BROWSER fallback");
await openUrlByBrowserEnv(url);
}
});
}
return;
}
catch (err) {
(0, logger_js_1.error)(`Failed to open ${url} ${options} ${err instanceof Error ? err.message : err} `, err instanceof Error ? err : new Error(String(err)));
if (shouldUseBrowserEnvFallback()) {
(0, logger_js_1.debug)("[openUrl] open() threw, trying BROWSER fallback");
await openUrlByBrowserEnv(url);
return;
}
(0, logger_js_1.warn)(`Please manually open: ${url}`);
}
}
class InteractiveServer {
app;
server;
wss;
port = 0;
isRunning = false;
currentResolver = null;
sessionData = new Map();
_mcpServer = null; // 保存 MCP server 实例引用
// 公共 getter 和 setter
get mcpServer() {
return this._mcpServer;
}
set mcpServer(server) {
this._mcpServer = server;
}
DEFAULT_PORT = 3721;
FALLBACK_PORTS = [
3722, 3723, 3724, 3725, 3726, 3727, 3728, 3729, 3730, 3731, 3732, 3733,
3734, 3735,
];
/** Idle timeout for HTTP/WS connections (e.g. long login). Avoids "connection disconnected" after ~1 min. */
static SERVER_IDLE_MS = 30 * 60 * 1000; // 30 minutes
/** WebSocket ping interval to keep connection alive past proxies/firewalls. */
static WS_PING_INTERVAL_MS = 25 * 1000; // 25 seconds
constructor(mcpServer) {
this._mcpServer = mcpServer;
this.app = (0, express_1.default)();
this.server = http_1.default.createServer(this.app);
this.applyServerTimeouts();
this.wss = new ws_1.WebSocketServer({ server: this.server });
this.setupExpress();
this.setupWebSocket();
process.on("exit", () => this.cleanup());
process.on("SIGINT", () => this.cleanup());
process.on("SIGTERM", () => this.cleanup());
}
cleanup() {
if (this.isRunning) {
(0, logger_js_1.debug)("Cleaning up interactive server resources...");
this.server.close();
this.wss.close();
this.isRunning = false;
}
}
/** Apply timeouts so long-lived login does not cause "connection disconnected". */
applyServerTimeouts() {
this.server.timeout = 0;
if (typeof this.server.keepAliveTimeout === "number") {
this.server.keepAliveTimeout = InteractiveServer.SERVER_IDLE_MS;
}
if (typeof this.server.headersTimeout === "number") {
this.server.headersTimeout = Math.max(this.server.headersTimeout || 0, InteractiveServer.SERVER_IDLE_MS);
}
}
setupExpress() {
this.app.use(express_1.default.json());
this.app.get("/env-setup/:sessionId", (req, res) => {
const { sessionId } = req.params;
const sessionData = this.sessionData.get(sessionId);
if (!sessionData) {
res.status(404).send("会话不存在或已过期");
return;
}
res.send(this.getEnvSetupHTML(sessionData.envs, sessionData.accountInfo, sessionData.errorContext, // Pass error context
sessionId // Pass sessionId for retry functionality
));
});
this.app.get("/clarification/:sessionId", (req, res) => {
const { sessionId } = req.params;
const sessionData = this.sessionData.get(sessionId);
if (!sessionData) {
res.status(404).send("会话不存在或已过期");
return;
}
res.send(this.getClarificationHTML(sessionData.message, sessionData.options));
});
this.app.post("/api/submit", (req, res) => {
const { type, data } = req.body;
(0, logger_js_1.debug)("Received submit request", { type, data });
if (this.currentResolver) {
(0, logger_js_1.info)("Resolving with user data");
this.currentResolver({ type, data });
this.currentResolv