@cloudbase/cloudbase-mcp 1.7.0 → 1.7.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.
@@ -83,15 +83,24 @@ export class InteractiveServer {
83
83
  // API接口
84
84
  this.app.post('/api/submit', (req, res) => {
85
85
  const { type, data } = req.body;
86
+ debug('🔥 === /api/submit 收到请求 ===');
87
+ debug('🔥 请求体 req.body:', JSON.stringify(req.body, null, 2));
88
+ debug('🔥 解析后 type:', type);
89
+ debug('🔥 解析后 data:', data);
90
+ debug('🔥 当前 currentResolver 状态:', this.currentResolver ? '有' : '无');
86
91
  debug('Received submit request', { type, data });
87
92
  if (this.currentResolver) {
88
93
  info('Resolving with user data');
94
+ debug('🔥 调用 currentResolver,参数:', { type, data });
89
95
  this.currentResolver({ type, data });
90
96
  this.currentResolver = null;
97
+ debug('🔥 已清空 currentResolver');
91
98
  }
92
99
  else {
93
100
  warn('No resolver waiting for response');
101
+ debug('🔥 ❌ 没有等待响应的resolver!');
94
102
  }
103
+ debug('🔥 返回成功响应');
95
104
  res.json({ success: true });
96
105
  });
97
106
  this.app.post('/api/cancel', (req, res) => {
@@ -252,158 +261,311 @@ export class InteractiveServer {
252
261
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
253
262
  <title>CloudBase AI Toolkit - 环境配置</title>
254
263
  <style>
264
+ @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&display=swap');
265
+
255
266
  * { margin: 0; padding: 0; box-sizing: border-box; }
256
267
  :root {
257
- --primary-color: #4F46E5;
258
- --primary-hover: #4338CA;
259
- --text-primary: #1F2937;
260
- --text-secondary: #6B7280;
261
- --border-color: #E5E7EB;
262
- --bg-secondary: #F9FAFB;
263
- --shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
264
- --font-mono: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', 'Source Code Pro', monospace;
268
+ --primary-color: #1a1a1a;
269
+ --primary-hover: #000000;
270
+ --accent-color: #67E9E9;
271
+ --accent-hover: #2BCCCC;
272
+ --text-primary: #ffffff;
273
+ --text-secondary: #a0a0a0;
274
+ --border-color: rgba(255, 255, 255, 0.15);
275
+ --bg-secondary: rgba(255, 255, 255, 0.08);
276
+ --bg-glass: rgba(26, 26, 26, 0.95);
277
+ --shadow: 0 25px 50px rgba(0, 0, 0, 0.3), 0 10px 20px rgba(0, 0, 0, 0.2);
278
+ --font-mono: 'JetBrains Mono', 'SF Mono', 'Monaco', monospace;
279
+ --header-bg: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 50%, #0d1117 100%);
265
280
  }
281
+
266
282
  body {
267
283
  font-family: var(--font-mono);
268
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
284
+ background: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 100%);
269
285
  min-height: 100vh;
270
286
  display: flex;
271
287
  align-items: center;
272
288
  justify-content: center;
273
289
  padding: 20px;
290
+ position: relative;
291
+ overflow-x: hidden;
292
+ overflow-y: auto;
293
+ }
294
+
295
+ /* Custom scrollbar styles */
296
+ ::-webkit-scrollbar {
297
+ width: 8px;
298
+ }
299
+
300
+ ::-webkit-scrollbar-track {
301
+ background: rgba(255, 255, 255, 0.05);
302
+ border-radius: 4px;
303
+ }
304
+
305
+ ::-webkit-scrollbar-thumb {
306
+ background: var(--accent-color);
307
+ border-radius: 4px;
308
+ }
309
+
310
+ ::-webkit-scrollbar-thumb:hover {
311
+ background: var(--accent-hover);
274
312
  }
313
+
314
+ body::before {
315
+ content: '';
316
+ position: fixed;
317
+ top: 0; left: 0; right: 0; bottom: 0;
318
+ 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;
319
+ pointer-events: none;
320
+ z-index: -1;
321
+ }
322
+
323
+ body::after {
324
+ content: '';
325
+ position: fixed;
326
+ top: 50%; left: 50%;
327
+ width: 500px; height: 500px;
328
+ background: radial-gradient(circle, rgba(103, 233, 233, 0.05) 0%, transparent 70%);
329
+ transform: translate(-50%, -50%);
330
+ pointer-events: none;
331
+ z-index: -1;
332
+ animation: pulse 8s ease-in-out infinite;
333
+ }
334
+
335
+ @keyframes pulse {
336
+ 0%, 100% { opacity: 0.3; transform: translate(-50%, -50%) scale(1); }
337
+ 50% { opacity: 0.6; transform: translate(-50%, -50%) scale(1.1); }
338
+ }
339
+
275
340
  .modal {
276
- background: white;
277
- border-radius: 16px;
341
+ background: var(--bg-glass);
342
+ backdrop-filter: blur(20px);
343
+ border-radius: 20px;
278
344
  box-shadow: var(--shadow);
345
+ border: 2px solid var(--border-color);
279
346
  width: 100%;
280
- max-width: 500px;
347
+ max-width: 520px;
281
348
  overflow: hidden;
282
- animation: modalIn 0.3s ease-out;
349
+ animation: modalIn 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275);
350
+ position: relative;
351
+ }
352
+
353
+ .modal::before {
354
+ content: '';
355
+ position: absolute;
356
+ top: 0; left: 0; right: 0; bottom: 0;
357
+ background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.02) 50%, transparent 70%);
358
+ animation: shimmer 3s infinite;
359
+ pointer-events: none;
360
+ }
361
+
362
+ @keyframes shimmer {
363
+ 0% { transform: translateX(-100%); }
364
+ 100% { transform: translateX(100%); }
283
365
  }
366
+
284
367
  @keyframes modalIn {
285
368
  from {
286
369
  opacity: 0;
287
- transform: scale(0.95) translateY(-10px);
370
+ transform: scale(0.9) translateY(-20px);
288
371
  }
289
372
  to {
290
373
  opacity: 1;
291
374
  transform: scale(1) translateY(0);
292
375
  }
293
376
  }
377
+
294
378
  .header {
295
- background: var(--primary-color);
296
- color: white;
297
- padding: 20px 24px;
379
+ background: var(--header-bg);
380
+ color: var(--text-primary);
381
+ padding: 24px 28px;
298
382
  display: flex;
299
383
  align-items: center;
300
384
  justify-content: space-between;
385
+ position: relative;
386
+ overflow: hidden;
301
387
  }
388
+
389
+ .header::before {
390
+ content: '';
391
+ position: absolute;
392
+ top: 0; left: 0; right: 0; bottom: 0;
393
+ background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.03) 50%, transparent 70%);
394
+ animation: headerShimmer 4s infinite;
395
+ pointer-events: none;
396
+ }
397
+
398
+ @keyframes headerShimmer {
399
+ 0% { transform: translateX(-100%); }
400
+ 100% { transform: translateX(100%); }
401
+ }
402
+
302
403
  .header-left {
303
404
  display: flex;
304
405
  align-items: center;
305
- gap: 12px;
406
+ gap: 16px;
407
+ z-index: 1;
306
408
  }
409
+
307
410
  .logo {
308
- width: 28px;
309
- height: 28px;
310
- animation: pulse 2s infinite;
411
+ width: 32px;
412
+ height: 32px;
413
+ filter: drop-shadow(0 4px 8px rgba(0,0,0,0.2));
414
+ animation: logoFloat 3s ease-in-out infinite;
311
415
  }
312
- @keyframes pulse {
313
- 0%, 100% { opacity: 1; }
314
- 50% { opacity: 0.8; }
416
+
417
+ @keyframes logoFloat {
418
+ 0%, 100% { transform: translateY(0px); }
419
+ 50% { transform: translateY(-3px); }
315
420
  }
421
+
316
422
  .title {
317
- font-size: 18px;
318
- font-weight: 600;
319
- letter-spacing: -0.025em;
423
+ font-size: 20px;
424
+ font-weight: 700;
425
+ text-shadow: 0 2px 4px rgba(0,0,0,0.1);
320
426
  }
427
+
321
428
  .github-link {
322
- color: white;
429
+ color: var(--text-primary);
323
430
  text-decoration: none;
324
431
  display: flex;
325
432
  align-items: center;
326
- gap: 6px;
433
+ gap: 8px;
327
434
  font-size: 14px;
328
- opacity: 0.9;
329
- transition: opacity 0.2s;
330
- padding: 6px 10px;
331
- border-radius: 6px;
332
- background: rgba(255,255,255,0.1);
435
+ background: rgba(255,255,255,0.08);
436
+ border: 1px solid rgba(255, 255, 255, 0.12);
437
+ backdrop-filter: blur(10px);
438
+ padding: 8px 16px;
439
+ border-radius: 8px;
440
+ font-weight: 500;
441
+ z-index: 1;
442
+ transition: all 0.3s ease;
333
443
  }
444
+
334
445
  .github-link:hover {
335
- opacity: 1;
336
- background: rgba(255,255,255,0.2);
446
+ background: rgba(255,255,255,0.15);
447
+ transform: translateY(-1px);
448
+ box-shadow: 0 4px 12px rgba(0,0,0,0.3);
337
449
  }
450
+
338
451
  .content {
339
452
  padding: 32px 24px;
453
+ position: relative;
340
454
  }
455
+
341
456
  .content-title {
342
457
  font-size: 24px;
343
458
  font-weight: 700;
344
459
  color: var(--text-primary);
345
460
  margin-bottom: 8px;
461
+ animation: fadeInUp 0.8s ease-out 0.2s both;
346
462
  }
463
+
347
464
  .content-subtitle {
348
465
  color: var(--text-secondary);
349
466
  margin-bottom: 24px;
350
467
  line-height: 1.5;
468
+ animation: fadeInUp 0.8s ease-out 0.4s both;
351
469
  }
470
+
471
+ @keyframes fadeInUp {
472
+ from {
473
+ opacity: 0;
474
+ transform: translateY(20px);
475
+ }
476
+ to {
477
+ opacity: 1;
478
+ transform: translateY(0);
479
+ }
480
+ }
481
+
352
482
  .env-list {
353
483
  border: 1px solid var(--border-color);
354
484
  border-radius: 12px;
355
485
  margin-bottom: 24px;
356
486
  max-height: 300px;
357
487
  overflow-y: auto;
488
+ overflow-x: hidden;
489
+ background: rgba(255, 255, 255, 0.03);
490
+ animation: fadeInUp 0.8s ease-out 0.6s both;
358
491
  }
492
+
359
493
  .env-item {
360
494
  padding: 16px 20px;
361
495
  border-bottom: 1px solid var(--border-color);
362
496
  cursor: pointer;
363
- transition: all 0.2s;
497
+ transition: all 0.3s ease;
364
498
  display: flex;
365
499
  align-items: center;
366
500
  gap: 14px;
501
+ position: relative;
502
+ overflow: hidden;
503
+ color: var(--text-primary);
367
504
  }
505
+
506
+ .env-item::before {
507
+ content: '';
508
+ position: absolute;
509
+ left: 0; top: 0; bottom: 0;
510
+ width: 0;
511
+ background: var(--accent-color);
512
+ transition: width 0.3s ease;
513
+ }
514
+
368
515
  .env-item:last-child {
369
516
  border-bottom: none;
370
517
  }
518
+
371
519
  .env-item:hover {
372
520
  background: var(--bg-secondary);
521
+ transform: translateX(5px);
373
522
  }
523
+
524
+ .env-item:hover::before {
525
+ width: 4px;
526
+ }
527
+
374
528
  .env-item.selected {
375
- background: #EEF2FF;
376
- border-left: 4px solid var(--primary-color);
529
+ background: rgba(103, 233, 233, 0.1);
530
+ border-left: 4px solid var(--accent-color);
531
+ transform: translateX(5px);
377
532
  }
533
+
378
534
  .env-icon {
379
535
  width: 20px;
380
536
  height: 20px;
381
- color: var(--primary-color);
537
+ color: var(--accent-color);
382
538
  flex-shrink: 0;
539
+ animation: iconGlow 2s ease-in-out infinite;
540
+ }
541
+
542
+ @keyframes iconGlow {
543
+ 0%, 100% { filter: drop-shadow(0 0 2px rgba(103, 233, 233, 0.3)); }
544
+ 50% { filter: drop-shadow(0 0 8px rgba(103, 233, 233, 0.6)); }
383
545
  }
546
+
384
547
  .env-info {
385
548
  flex: 1;
386
- min-width: 0;
387
549
  }
550
+
388
551
  .env-name {
389
552
  font-weight: 600;
390
553
  color: var(--text-primary);
391
554
  margin-bottom: 4px;
392
555
  }
393
- .env-id {
394
- font-size: 13px;
556
+
557
+ .env-alias {
395
558
  color: var(--text-secondary);
396
- font-family: var(--font-mono);
397
- background: var(--bg-secondary);
398
- padding: 2px 8px;
399
- border-radius: 4px;
400
- display: inline-block;
559
+ font-size: 14px;
401
560
  }
561
+
402
562
  .actions {
403
563
  display: flex;
404
564
  gap: 12px;
405
565
  justify-content: flex-end;
566
+ animation: fadeInUp 0.8s ease-out 0.8s both;
406
567
  }
568
+
407
569
  .btn {
408
570
  padding: 12px 20px;
409
571
  border: none;
@@ -411,32 +573,58 @@ export class InteractiveServer {
411
573
  font-size: 14px;
412
574
  font-weight: 600;
413
575
  cursor: pointer;
414
- transition: all 0.2s;
576
+ transition: all 0.3s ease;
415
577
  display: flex;
416
578
  align-items: center;
417
579
  gap: 8px;
418
580
  font-family: var(--font-mono);
581
+ position: relative;
582
+ overflow: hidden;
583
+ }
584
+
585
+ .btn::before {
586
+ content: '';
587
+ position: absolute;
588
+ top: 50%; left: 50%;
589
+ width: 0; height: 0;
590
+ background: rgba(255,255,255,0.2);
591
+ border-radius: 50%;
592
+ transition: all 0.3s ease;
593
+ transform: translate(-50%, -50%);
594
+ }
595
+
596
+ .btn:hover::before {
597
+ width: 100px; height: 100px;
419
598
  }
599
+
420
600
  .btn-primary {
421
601
  background: var(--primary-color);
422
- color: white;
602
+ color: var(--text-primary);
603
+ border: 1px solid var(--border-color);
423
604
  }
605
+
424
606
  .btn-primary:hover:not(:disabled) {
425
607
  background: var(--primary-hover);
426
- transform: translateY(-1px);
608
+ transform: translateY(-2px);
609
+ box-shadow: 0 8px 25px rgba(0, 0, 0, 0.3);
427
610
  }
611
+
428
612
  .btn-secondary {
429
613
  background: var(--bg-secondary);
430
614
  color: var(--text-secondary);
431
615
  border: 1px solid var(--border-color);
432
616
  }
617
+
433
618
  .btn-secondary:hover {
434
- background: #F3F4F6;
619
+ background: rgba(255, 255, 255, 0.15);
620
+ color: var(--text-primary);
435
621
  }
622
+
436
623
  .btn:disabled {
437
624
  opacity: 0.5;
438
625
  cursor: not-allowed;
439
626
  }
627
+
440
628
  .loading {
441
629
  display: none;
442
630
  align-items: center;
@@ -446,14 +634,16 @@ export class InteractiveServer {
446
634
  color: var(--text-secondary);
447
635
  font-size: 14px;
448
636
  }
637
+
449
638
  .spinner {
450
639
  width: 16px;
451
640
  height: 16px;
452
641
  border: 2px solid var(--border-color);
453
- border-top: 2px solid var(--primary-color);
642
+ border-top: 2px solid var(--accent-color);
454
643
  border-radius: 50%;
455
644
  animation: spin 1s linear infinite;
456
645
  }
646
+
457
647
  @keyframes spin {
458
648
  0% { transform: rotate(0deg); }
459
649
  100% { transform: rotate(360deg); }
@@ -464,11 +654,7 @@ export class InteractiveServer {
464
654
  <div class="modal">
465
655
  <div class="header">
466
656
  <div class="header-left">
467
- <svg class="logo" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
468
- <path d="M12 2L2 7V17L12 22L22 17V7L12 2Z"/>
469
- <path d="M12 22V12"/>
470
- <path d="M22 7L12 12L2 7"/>
471
- </svg>
657
+ <img class="logo" src="https://7463-tcb-advanced-a656fc-1257967285.tcb.qcloud.la/mcp/cloudbase-logo.svg" alt="CloudBase Logo" />
472
658
  <span class="title">CloudBase AI Toolkit</span>
473
659
  </div>
474
660
  <a href="https://github.com/TencentCloudBase/CloudBase-AI-ToolKit" target="_blank" class="github-link">
@@ -478,13 +664,23 @@ export class InteractiveServer {
478
664
  GitHub
479
665
  </a>
480
666
  </div>
481
-
667
+
482
668
  <div class="content">
483
669
  <h1 class="content-title">选择云开发环境</h1>
484
- <p class="content-subtitle">请选择要使用的云开发环境,系统将自动配置环境ID</p>
670
+ <p class="content-subtitle">请选择您要使用的云开发环境</p>
485
671
 
486
672
  <div class="env-list" id="envList">
487
- <!-- 环境列表将通过JavaScript动态加载 -->
673
+ ${(envs || []).map((env, index) => `
674
+ <div class="env-item" onclick="selectEnv('${env.EnvId}', this)" style="animation-delay: ${index * 0.1}s;">
675
+ <svg class="env-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
676
+ <path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"/>
677
+ </svg>
678
+ <div class="env-info">
679
+ <div class="env-name">${env.EnvId}</div>
680
+ <div class="env-alias">${env.Alias || '无别名'}</div>
681
+ </div>
682
+ </div>
683
+ `).join('')}
488
684
  </div>
489
685
 
490
686
  <div class="actions">
@@ -511,57 +707,97 @@ export class InteractiveServer {
511
707
 
512
708
  <script>
513
709
  let selectedEnvId = null;
514
- const envs = ${JSON.stringify(envs || [])};
515
710
 
516
- function renderEnvList() {
517
- const envList = document.getElementById('envList');
518
- if (envs.length === 0) {
519
- envList.innerHTML = '<div style="padding: 24px; text-align: center; color: var(--text-secondary);">暂无可用环境</div>';
520
- return;
521
- }
711
+ function selectEnv(envId, element) {
712
+ console.log('=== 环境选择事件触发 ===');
713
+ console.log('传入的envId:', envId);
714
+ console.log('传入的element:', element);
715
+ console.log('element类名:', element ? element.className : 'null');
522
716
 
523
- envList.innerHTML = envs.map((env, index) => \`
524
- <div class="env-item" onclick="selectEnv('\${env.EnvId}')">
525
- <svg class="env-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
526
- <path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"/>
527
- </svg>
528
- <div class="env-info">
529
- <div class="env-name">\${env.Alias || env.EnvId}</div>
530
- <div class="env-id">\${env.EnvId}</div>
531
- </div>
532
- </div>
533
- \`).join('');
534
- }
535
-
536
- function selectEnv(envId) {
537
717
  selectedEnvId = envId;
538
- document.querySelectorAll('.env-item').forEach(item => {
718
+ console.log('设置selectedEnvId为:', selectedEnvId);
719
+
720
+ // Remove selected class from all items
721
+ const allItems = document.querySelectorAll('.env-item');
722
+ console.log('找到的所有环境项数量:', allItems.length);
723
+ allItems.forEach(item => {
539
724
  item.classList.remove('selected');
540
725
  });
541
- event.currentTarget.classList.add('selected');
542
- document.getElementById('confirmBtn').disabled = false;
726
+
727
+ // Add selected class to current item
728
+ if (element) {
729
+ element.classList.add('selected');
730
+ console.log('✅ 已添加selected样式到当前项');
731
+ console.log('当前项的最终类名:', element.className);
732
+ } else {
733
+ console.error('❌ element为空,无法添加选中样式');
734
+ }
735
+
736
+ // Enable confirm button
737
+ const confirmBtn = document.getElementById('confirmBtn');
738
+ if (confirmBtn) {
739
+ confirmBtn.disabled = false;
740
+ console.log('✅ 确认按钮已启用');
741
+ } else {
742
+ console.error('❌ 找不到确认按钮');
743
+ }
543
744
  }
544
745
 
545
746
  function confirm() {
546
- if (!selectedEnvId) return;
747
+ console.log('=== CONFIRM BUTTON CLICKED ===');
748
+ console.log('selectedEnvId:', selectedEnvId);
749
+
750
+ if (!selectedEnvId) {
751
+ console.error('❌ 没有选择环境ID!');
752
+ alert('请先选择一个环境');
753
+ return;
754
+ }
755
+
756
+ console.log('✅ 环境ID验证通过,开始发送请求...');
547
757
  document.getElementById('loading').style.display = 'flex';
758
+ document.getElementById('confirmBtn').disabled = true;
759
+
760
+ const requestBody = {
761
+ type: 'envId',
762
+ data: selectedEnvId
763
+ };
764
+
765
+ console.log('📤 发送请求体:', JSON.stringify(requestBody, null, 2));
766
+
548
767
  fetch('/api/submit', {
549
768
  method: 'POST',
550
769
  headers: { 'Content-Type': 'application/json' },
551
- body: JSON.stringify({
552
- type: 'envId',
553
- data: { envId: selectedEnvId }
554
- })
555
- }).then(() => window.close());
770
+ body: JSON.stringify(requestBody)
771
+ }).then(response => {
772
+ console.log('📥 收到响应状态:', response.status);
773
+ console.log('📥 响应头:', [...response.headers.entries()]);
774
+ return response.json();
775
+ }).then(data => {
776
+ console.log('📥 响应数据:', data);
777
+ if (data.success) {
778
+ console.log('✅ 请求成功,即将关闭窗口');
779
+ window.close();
780
+ } else {
781
+ console.error('❌ 请求失败:', data);
782
+ alert('选择环境失败: ' + (data.error || '未知错误'));
783
+ document.getElementById('loading').style.display = 'none';
784
+ document.getElementById('confirmBtn').disabled = false;
785
+ }
786
+ }).catch(err => {
787
+ console.error('❌ 网络请求错误:', err);
788
+ alert('网络请求失败: ' + err.message);
789
+ document.getElementById('loading').style.display = 'none';
790
+ document.getElementById('confirmBtn').disabled = false;
791
+ });
556
792
  }
557
793
 
558
794
  function cancel() {
559
- fetch('/api/cancel', { method: 'POST' }).then(() => window.close());
560
- }
561
-
562
- renderEnvList();
563
- if (envs.length === 1) {
564
- selectEnv(envs[0].EnvId);
795
+ fetch('/api/cancel', {
796
+ method: 'POST',
797
+ headers: { 'Content-Type': 'application/json' }
798
+ }).then(() => {
799
+ window.close();
800
+ });
565
801
  }
566
802
  </script>
567
803
  </body>
@@ -576,72 +812,234 @@ export class InteractiveServer {
576
812
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
577
813
  <title>CloudBase MCP 调试日志</title>
578
814
  <style>
815
+ @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&display=swap');
816
+
579
817
  * { margin: 0; padding: 0; box-sizing: border-box; }
818
+ :root {
819
+ --primary-color: #1a1a1a;
820
+ --primary-hover: #000000;
821
+ --accent-color: #67E9E9;
822
+ --accent-hover: #2BCCCC;
823
+ --text-primary: #ffffff;
824
+ --text-secondary: #a0a0a0;
825
+ --border-color: rgba(255, 255, 255, 0.15);
826
+ --bg-secondary: rgba(255, 255, 255, 0.08);
827
+ --bg-glass: rgba(26, 26, 26, 0.95);
828
+ --shadow: 0 25px 50px rgba(0, 0, 0, 0.3), 0 10px 20px rgba(0, 0, 0, 0.2);
829
+ --font-mono: 'JetBrains Mono', 'SF Mono', 'Monaco', monospace;
830
+ --header-bg: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 50%, #0d1117 100%);
831
+ }
832
+
580
833
  body {
581
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
582
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
834
+ font-family: var(--font-mono);
835
+ background: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 100%);
583
836
  min-height: 100vh;
584
837
  padding: 20px;
838
+ position: relative;
839
+ overflow-x: hidden;
840
+ overflow-y: auto;
841
+ }
842
+
843
+ /* Custom scrollbar styles */
844
+ ::-webkit-scrollbar {
845
+ width: 8px;
585
846
  }
847
+
848
+ ::-webkit-scrollbar-track {
849
+ background: rgba(255, 255, 255, 0.05);
850
+ border-radius: 4px;
851
+ }
852
+
853
+ ::-webkit-scrollbar-thumb {
854
+ background: var(--accent-color);
855
+ border-radius: 4px;
856
+ }
857
+
858
+ ::-webkit-scrollbar-thumb:hover {
859
+ background: var(--accent-hover);
860
+ }
861
+
862
+ body::before {
863
+ content: '';
864
+ position: fixed;
865
+ top: 0; left: 0; right: 0; bottom: 0;
866
+ 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;
867
+ pointer-events: none;
868
+ z-index: -1;
869
+ }
870
+
871
+ body::after {
872
+ content: '';
873
+ position: fixed;
874
+ top: 50%; left: 50%;
875
+ width: 500px; height: 500px;
876
+ background: radial-gradient(circle, rgba(103, 233, 233, 0.05) 0%, transparent 70%);
877
+ transform: translate(-50%, -50%);
878
+ pointer-events: none;
879
+ z-index: -1;
880
+ animation: pulse 8s ease-in-out infinite;
881
+ }
882
+
883
+ @keyframes pulse {
884
+ 0%, 100% { opacity: 0.3; transform: translate(-50%, -50%) scale(1); }
885
+ 50% { opacity: 0.6; transform: translate(-50%, -50%) scale(1.1); }
886
+ }
887
+
586
888
  .container {
587
- background: white;
889
+ background: var(--bg-glass);
890
+ backdrop-filter: blur(20px);
588
891
  border-radius: 20px;
589
892
  padding: 30px;
590
- box-shadow: 0 20px 40px rgba(0,0,0,0.1);
893
+ box-shadow: var(--shadow);
894
+ border: 2px solid var(--border-color);
591
895
  max-width: 1200px;
592
896
  margin: 0 auto;
897
+ animation: modalIn 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275);
898
+ position: relative;
593
899
  }
900
+
901
+ .container::before {
902
+ content: '';
903
+ position: absolute;
904
+ top: 0; left: 0; right: 0; bottom: 0;
905
+ background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.02) 50%, transparent 70%);
906
+ animation: shimmer 3s infinite;
907
+ pointer-events: none;
908
+ border-radius: 20px;
909
+ }
910
+
911
+ @keyframes shimmer {
912
+ 0% { transform: translateX(-100%); }
913
+ 100% { transform: translateX(100%); }
914
+ }
915
+
916
+ @keyframes modalIn {
917
+ from {
918
+ opacity: 0;
919
+ transform: scale(0.9) translateY(-20px);
920
+ }
921
+ to {
922
+ opacity: 1;
923
+ transform: scale(1) translateY(0);
924
+ }
925
+ }
926
+
594
927
  .header {
595
928
  text-align: center;
596
929
  margin-bottom: 30px;
930
+ position: relative;
931
+ z-index: 1;
597
932
  }
598
- .icon {
599
- width: 60px;
600
- height: 60px;
601
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
602
- border-radius: 50%;
603
- margin: 0 auto 20px;
933
+
934
+ .header-top {
604
935
  display: flex;
605
936
  align-items: center;
606
- justify-content: center;
607
- font-size: 30px;
608
- color: white;
937
+ justify-content: space-between;
938
+ margin-bottom: 20px;
939
+ }
940
+
941
+ .header-left {
942
+ display: flex;
943
+ align-items: center;
944
+ gap: 16px;
609
945
  }
946
+
947
+ .logo {
948
+ width: 40px;
949
+ height: 40px;
950
+ filter: drop-shadow(0 4px 8px rgba(0,0,0,0.2));
951
+ animation: logoFloat 3s ease-in-out infinite;
952
+ }
953
+
954
+ @keyframes logoFloat {
955
+ 0%, 100% { transform: translateY(0px); }
956
+ 50% { transform: translateY(-3px); }
957
+ }
958
+
959
+ .github-link {
960
+ color: var(--text-primary);
961
+ text-decoration: none;
962
+ display: flex;
963
+ align-items: center;
964
+ gap: 8px;
965
+ font-size: 14px;
966
+ background: rgba(255,255,255,0.08);
967
+ border: 1px solid rgba(255, 255, 255, 0.12);
968
+ backdrop-filter: blur(10px);
969
+ padding: 8px 16px;
970
+ border-radius: 8px;
971
+ font-weight: 500;
972
+ transition: all 0.3s ease;
973
+ }
974
+
975
+ .github-link:hover {
976
+ background: rgba(255,255,255,0.15);
977
+ transform: translateY(-1px);
978
+ box-shadow: 0 4px 12px rgba(0,0,0,0.3);
979
+ }
980
+
610
981
  h1 {
611
- color: #2d3748;
982
+ color: var(--text-primary);
612
983
  margin-bottom: 10px;
613
- font-size: 24px;
984
+ font-size: 28px;
614
985
  font-weight: 700;
986
+ animation: fadeInUp 0.8s ease-out 0.2s both;
987
+ }
988
+
989
+ .subtitle {
990
+ color: var(--text-secondary);
991
+ font-size: 16px;
992
+ animation: fadeInUp 0.8s ease-out 0.4s both;
615
993
  }
994
+
995
+ @keyframes fadeInUp {
996
+ from {
997
+ opacity: 0;
998
+ transform: translateY(20px);
999
+ }
1000
+ to {
1001
+ opacity: 1;
1002
+ transform: translateY(0);
1003
+ }
1004
+ }
1005
+
616
1006
  .status {
617
- background: #f7fafc;
1007
+ background: rgba(255, 255, 255, 0.05);
1008
+ border: 1px solid var(--border-color);
618
1009
  border-radius: 12px;
619
1010
  padding: 20px;
620
1011
  margin-bottom: 20px;
621
1012
  display: grid;
622
1013
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
623
1014
  gap: 15px;
1015
+ animation: fadeInUp 0.8s ease-out 0.6s both;
624
1016
  }
1017
+
625
1018
  .status-item {
626
1019
  display: flex;
627
1020
  justify-content: space-between;
628
1021
  align-items: center;
629
1022
  }
1023
+
630
1024
  .status-label {
631
1025
  font-weight: 600;
632
- color: #4a5568;
1026
+ color: var(--text-secondary);
633
1027
  }
1028
+
634
1029
  .status-value {
635
- color: #2d3748;
636
- font-family: 'Monaco', 'Menlo', monospace;
1030
+ color: var(--text-primary);
1031
+ font-family: var(--font-mono);
637
1032
  font-size: 14px;
638
1033
  }
1034
+
639
1035
  .enabled {
640
- color: #38a169;
1036
+ color: var(--accent-color);
641
1037
  }
1038
+
642
1039
  .disabled {
643
- color: #e53e3e;
1040
+ color: #ff6b6b;
644
1041
  }
1042
+
645
1043
  .controls {
646
1044
  display: flex;
647
1045
  gap: 15px;
@@ -649,11 +1047,14 @@ export class InteractiveServer {
649
1047
  justify-content: space-between;
650
1048
  align-items: center;
651
1049
  flex-wrap: wrap;
1050
+ animation: fadeInUp 0.8s ease-out 0.8s both;
652
1051
  }
1052
+
653
1053
  .controls-left {
654
1054
  display: flex;
655
1055
  gap: 15px;
656
1056
  }
1057
+
657
1058
  .btn {
658
1059
  padding: 10px 20px;
659
1060
  border: none;
@@ -662,127 +1063,171 @@ export class InteractiveServer {
662
1063
  font-weight: 600;
663
1064
  cursor: pointer;
664
1065
  transition: all 0.3s ease;
1066
+ font-family: var(--font-mono);
1067
+ position: relative;
1068
+ overflow: hidden;
665
1069
  }
1070
+
1071
+ .btn::before {
1072
+ content: '';
1073
+ position: absolute;
1074
+ top: 50%; left: 50%;
1075
+ width: 0; height: 0;
1076
+ background: rgba(255,255,255,0.2);
1077
+ border-radius: 50%;
1078
+ transition: all 0.3s ease;
1079
+ transform: translate(-50%, -50%);
1080
+ }
1081
+
1082
+ .btn:hover::before {
1083
+ width: 100px; height: 100px;
1084
+ }
1085
+
666
1086
  .btn-primary {
667
- background: #667eea;
668
- color: white;
1087
+ background: var(--accent-color);
1088
+ color: var(--primary-color);
669
1089
  }
1090
+
670
1091
  .btn-primary:hover {
671
- background: #5a67d8;
1092
+ background: var(--accent-hover);
1093
+ transform: translateY(-2px);
1094
+ box-shadow: 0 8px 25px rgba(103, 233, 233, 0.3);
672
1095
  }
1096
+
673
1097
  .btn-danger {
674
- background: #e53e3e;
1098
+ background: #ff6b6b;
675
1099
  color: white;
676
1100
  }
1101
+
677
1102
  .btn-danger:hover {
678
- background: #c53030;
1103
+ background: #ff5252;
1104
+ transform: translateY(-2px);
1105
+ box-shadow: 0 8px 25px rgba(255, 107, 107, 0.3);
679
1106
  }
1107
+
680
1108
  .btn-secondary {
681
- background: #e2e8f0;
682
- color: #4a5568;
1109
+ background: var(--bg-secondary);
1110
+ color: var(--text-secondary);
1111
+ border: 1px solid var(--border-color);
683
1112
  }
1113
+
684
1114
  .btn-secondary:hover {
685
- background: #cbd5e0;
1115
+ background: rgba(255, 255, 255, 0.15);
1116
+ color: var(--text-primary);
686
1117
  }
1118
+
687
1119
  .log-container {
688
- background: #1a202c;
1120
+ background: rgba(0, 0, 0, 0.5);
1121
+ border: 1px solid var(--border-color);
689
1122
  border-radius: 12px;
690
1123
  padding: 20px;
691
1124
  height: 500px;
692
1125
  overflow-y: auto;
693
- font-family: 'Monaco', 'Menlo', 'Consolas', monospace;
1126
+ font-family: var(--font-mono);
694
1127
  font-size: 13px;
695
1128
  line-height: 1.4;
1129
+ animation: fadeInUp 0.8s ease-out 1s both;
696
1130
  }
1131
+
697
1132
  .log-container::-webkit-scrollbar {
698
1133
  width: 8px;
699
1134
  }
1135
+
700
1136
  .log-container::-webkit-scrollbar-track {
701
- background: #2d3748;
1137
+ background: rgba(255, 255, 255, 0.1);
702
1138
  border-radius: 4px;
703
1139
  }
1140
+
704
1141
  .log-container::-webkit-scrollbar-thumb {
705
- background: #4a5568;
1142
+ background: var(--accent-color);
706
1143
  border-radius: 4px;
707
1144
  }
1145
+
708
1146
  .log-container::-webkit-scrollbar-thumb:hover {
709
- background: #718096;
1147
+ background: var(--accent-hover);
710
1148
  }
1149
+
711
1150
  .log-line {
712
- color: #e2e8f0;
1151
+ color: var(--text-primary);
713
1152
  margin-bottom: 2px;
714
1153
  word-break: break-all;
1154
+ animation: logSlideIn 0.3s ease-out;
715
1155
  }
1156
+
1157
+ @keyframes logSlideIn {
1158
+ from {
1159
+ opacity: 0;
1160
+ transform: translateX(-10px);
1161
+ }
1162
+ to {
1163
+ opacity: 1;
1164
+ transform: translateX(0);
1165
+ }
1166
+ }
1167
+
716
1168
  .log-line.debug {
717
- color: #a0aec0;
1169
+ color: var(--text-secondary);
718
1170
  }
1171
+
719
1172
  .log-line.info {
720
- color: #63b3ed;
1173
+ color: #74c0fc;
721
1174
  }
1175
+
722
1176
  .log-line.warn {
723
- color: #f6ad55;
1177
+ color: #ffd43b;
724
1178
  }
1179
+
725
1180
  .log-line.error {
726
- color: #fc8181;
1181
+ color: #ff8787;
727
1182
  }
1183
+
728
1184
  .timestamp {
729
- color: #718096;
1185
+ color: var(--text-secondary);
730
1186
  }
1187
+
731
1188
  .level {
732
1189
  font-weight: bold;
733
1190
  margin: 0 8px;
734
1191
  }
1192
+
735
1193
  .empty-state {
736
1194
  text-align: center;
737
- color: #718096;
1195
+ color: var(--text-secondary);
738
1196
  padding: 40px;
739
1197
  font-style: italic;
740
1198
  }
741
- .footer {
742
- margin-top: 30px;
743
- padding-top: 20px;
744
- border-top: 1px solid #e2e8f0;
745
- text-align: center;
746
- }
747
- .footer .brand {
748
- font-size: 16px;
749
- font-weight: 700;
750
- color: #2d3748;
751
- margin-bottom: 10px;
752
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
753
- -webkit-background-clip: text;
754
- -webkit-text-fill-color: transparent;
755
- background-clip: text;
756
- }
757
- .footer .links {
758
- display: flex;
759
- justify-content: center;
760
- gap: 20px;
761
- }
762
- .footer .links a {
763
- color: #718096;
764
- text-decoration: none;
1199
+
1200
+ .log-count {
1201
+ color: var(--text-secondary);
765
1202
  font-size: 14px;
766
- transition: color 0.3s ease;
767
- }
768
- .footer .links a:hover {
769
- color: #667eea;
770
1203
  }
771
1204
  </style>
772
1205
  </head>
773
1206
  <body>
774
1207
  <div class="container">
775
1208
  <div class="header">
776
- <div class="icon">🔍</div>
777
- <h1>CloudBase MCP 调试日志</h1>
778
- <p style="color: #718096;">实时查看 MCP 服务器运行日志</p>
1209
+ <div class="header-top">
1210
+ <div class="header-left">
1211
+ <img class="logo" src="https://7463-tcb-advanced-a656fc-1257967285.tcb.qcloud.la/mcp/cloudbase-logo.svg" alt="CloudBase Logo" />
1212
+ <div style="text-align: left;">
1213
+ <h1>CloudBase MCP 调试日志</h1>
1214
+ <p class="subtitle">实时查看 MCP 服务器运行日志</p>
1215
+ </div>
1216
+ </div>
1217
+ <a href="https://github.com/TencentCloudBase/CloudBase-AI-ToolKit" target="_blank" class="github-link">
1218
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
1219
+ <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"/>
1220
+ </svg>
1221
+ GitHub
1222
+ </a>
1223
+ </div>
779
1224
  </div>
780
1225
 
781
1226
  <div class="status">
782
1227
  <div class="status-item">
783
1228
  <span class="status-label">日志状态:</span>
784
1229
  <span class="status-value ${status.enabled ? 'enabled' : 'disabled'}">
785
- ${status.enabled ? '启用' : '禁用'}
1230
+ ${status.enabled ? '🟢 启用' : '🔴 禁用'}
786
1231
  </span>
787
1232
  </div>
788
1233
  <div class="status-item">
@@ -796,19 +1241,39 @@ export class InteractiveServer {
796
1241
  <div class="status-item">
797
1242
  <span class="status-label">控制台输出:</span>
798
1243
  <span class="status-value ${status.useConsole ? 'enabled' : 'disabled'}">
799
- ${status.useConsole ? '启用' : '禁用'}
1244
+ ${status.useConsole ? '🟢 启用' : '🔴 禁用'}
800
1245
  </span>
801
1246
  </div>
802
1247
  </div>
803
1248
 
804
1249
  <div class="controls">
805
1250
  <div class="controls-left">
806
- <button class="btn btn-primary" onclick="refreshLogs()">刷新日志</button>
807
- <button class="btn btn-danger" onclick="clearLogs()">清空日志</button>
808
- <button class="btn btn-secondary" onclick="window.close()">关闭</button>
1251
+ <button class="btn btn-primary" onclick="refreshLogs()">
1252
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 6px;">
1253
+ <path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"/>
1254
+ <path d="M21 3v5h-5"/>
1255
+ <path d="M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"/>
1256
+ <path d="M8 16H3v5"/>
1257
+ </svg>
1258
+ 刷新日志
1259
+ </button>
1260
+ <button class="btn btn-danger" onclick="clearLogs()">
1261
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 6px;">
1262
+ <path d="M3 6h18"/>
1263
+ <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"/>
1264
+ <path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"/>
1265
+ </svg>
1266
+ 清空日志
1267
+ </button>
1268
+ <button class="btn btn-secondary" onclick="window.close()">
1269
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 6px;">
1270
+ <path d="M18 6L6 18M6 6l12 12"/>
1271
+ </svg>
1272
+ 关闭
1273
+ </button>
809
1274
  </div>
810
1275
  <div>
811
- <span style="color: #718096; font-size: 14px;">共 ${logs.length} 条日志</span>
1276
+ <span class="log-count">📊 ${logs.length} 条日志</span>
812
1277
  </div>
813
1278
  </div>
814
1279
 
@@ -821,15 +1286,7 @@ export class InteractiveServer {
821
1286
  return `<div class="log-line ${levelClass}"><span class="timestamp">[${timestamp}]</span><span class="level ${levelClass}">[${level}]</span>${message}</div>`;
822
1287
  }
823
1288
  return `<div class="log-line">${line}</div>`;
824
- }).join('') : '<div class="empty-state">暂无日志记录</div>'}
825
- </div>
826
-
827
- <div class="footer">
828
- <p class="brand">CloudBase AI ToolKit</p>
829
- <div class="links">
830
- <a href="https://github.com/TencentCloudBase/CloudBase-AI-ToolKit" target="_blank">GitHub</a>
831
- <a href="https://tcb.cloud.tencent.com/dev" target="_blank">控制台</a>
832
- </div>
1289
+ }).join('') : '<div class="empty-state">📝 暂无日志记录</div>'}
833
1290
  </div>
834
1291
  </div>
835
1292
 
@@ -886,7 +1343,7 @@ export class InteractiveServer {
886
1343
  return \`<div class="log-line">\${line}</div>\`;
887
1344
  }).join('');
888
1345
 
889
- logContainer.innerHTML = newContent || '<div class="empty-state">暂无日志记录</div>';
1346
+ logContainer.innerHTML = newContent || '<div class="empty-state">📝 暂无日志记录</div>';
890
1347
 
891
1348
  if (isAtBottom) {
892
1349
  logContainer.scrollTop = logContainer.scrollHeight;
@@ -911,140 +1368,314 @@ export class InteractiveServer {
911
1368
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
912
1369
  <title>CloudBase AI Toolkit - 需求澄清</title>
913
1370
  <style>
1371
+ @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&display=swap');
1372
+
914
1373
  * { margin: 0; padding: 0; box-sizing: border-box; }
915
1374
  :root {
916
- --primary-color: #4F46E5;
917
- --primary-hover: #4338CA;
918
- --text-primary: #1F2937;
919
- --text-secondary: #6B7280;
920
- --border-color: #E5E7EB;
921
- --bg-secondary: #F9FAFB;
922
- --shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
923
- --font-mono: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', 'Source Code Pro', monospace;
1375
+ --primary-color: #1a1a1a;
1376
+ --primary-hover: #000000;
1377
+ --accent-color: #67E9E9;
1378
+ --accent-hover: #2BCCCC;
1379
+ --text-primary: #ffffff;
1380
+ --text-secondary: #a0a0a0;
1381
+ --border-color: rgba(255, 255, 255, 0.15);
1382
+ --bg-secondary: rgba(255, 255, 255, 0.08);
1383
+ --bg-glass: rgba(26, 26, 26, 0.95);
1384
+ --shadow: 0 25px 50px rgba(0, 0, 0, 0.3), 0 10px 20px rgba(0, 0, 0, 0.2);
1385
+ --font-mono: 'JetBrains Mono', 'SF Mono', 'Monaco', monospace;
1386
+ --header-bg: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 50%, #0d1117 100%);
924
1387
  }
1388
+
925
1389
  body {
926
1390
  font-family: var(--font-mono);
927
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
1391
+ background: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 100%);
928
1392
  min-height: 100vh;
929
1393
  display: flex;
930
1394
  align-items: center;
931
1395
  justify-content: center;
932
1396
  padding: 20px;
1397
+ position: relative;
1398
+ overflow-x: hidden;
1399
+ overflow-y: auto;
1400
+ }
1401
+
1402
+ /* Custom scrollbar styles */
1403
+ ::-webkit-scrollbar {
1404
+ width: 8px;
1405
+ }
1406
+
1407
+ ::-webkit-scrollbar-track {
1408
+ background: rgba(255, 255, 255, 0.05);
1409
+ border-radius: 4px;
1410
+ }
1411
+
1412
+ ::-webkit-scrollbar-thumb {
1413
+ background: var(--accent-color);
1414
+ border-radius: 4px;
1415
+ }
1416
+
1417
+ ::-webkit-scrollbar-thumb:hover {
1418
+ background: var(--accent-hover);
933
1419
  }
1420
+
1421
+ body::before {
1422
+ content: '';
1423
+ position: fixed;
1424
+ top: 0; left: 0; right: 0; bottom: 0;
1425
+ 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;
1426
+ pointer-events: none;
1427
+ z-index: -1;
1428
+ }
1429
+
1430
+ body::after {
1431
+ content: '';
1432
+ position: fixed;
1433
+ top: 50%; left: 50%;
1434
+ width: 500px; height: 500px;
1435
+ background: radial-gradient(circle, rgba(103, 233, 233, 0.05) 0%, transparent 70%);
1436
+ transform: translate(-50%, -50%);
1437
+ pointer-events: none;
1438
+ z-index: -1;
1439
+ animation: pulse 8s ease-in-out infinite;
1440
+ }
1441
+
1442
+ @keyframes pulse {
1443
+ 0%, 100% { opacity: 0.3; transform: translate(-50%, -50%) scale(1); }
1444
+ 50% { opacity: 0.6; transform: translate(-50%, -50%) scale(1.1); }
1445
+ }
1446
+
934
1447
  .modal {
935
- background: white;
936
- border-radius: 16px;
1448
+ background: var(--bg-glass);
1449
+ backdrop-filter: blur(20px);
1450
+ border-radius: 20px;
937
1451
  box-shadow: var(--shadow);
1452
+ border: 2px solid var(--border-color);
938
1453
  width: 100%;
939
1454
  max-width: 600px;
940
1455
  overflow: hidden;
941
- animation: modalIn 0.3s ease-out;
1456
+ animation: modalIn 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275);
1457
+ position: relative;
942
1458
  }
1459
+
1460
+ .modal::before {
1461
+ content: '';
1462
+ position: absolute;
1463
+ top: 0; left: 0; right: 0; bottom: 0;
1464
+ background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.02) 50%, transparent 70%);
1465
+ animation: shimmer 3s infinite;
1466
+ pointer-events: none;
1467
+ }
1468
+
1469
+ @keyframes shimmer {
1470
+ 0% { transform: translateX(-100%); }
1471
+ 100% { transform: translateX(100%); }
1472
+ }
1473
+
943
1474
  @keyframes modalIn {
944
1475
  from {
945
1476
  opacity: 0;
946
- transform: scale(0.95) translateY(-10px);
1477
+ transform: scale(0.9) translateY(-20px);
947
1478
  }
948
1479
  to {
949
1480
  opacity: 1;
950
1481
  transform: scale(1) translateY(0);
951
1482
  }
952
1483
  }
1484
+
953
1485
  .header {
954
- background: var(--primary-color);
955
- color: white;
956
- padding: 20px 24px;
1486
+ background: var(--header-bg);
1487
+ color: var(--text-primary);
1488
+ padding: 24px 28px;
957
1489
  display: flex;
958
1490
  align-items: center;
959
1491
  justify-content: space-between;
1492
+ position: relative;
1493
+ overflow: hidden;
960
1494
  }
1495
+
1496
+ .header::before {
1497
+ content: '';
1498
+ position: absolute;
1499
+ top: 0; left: 0; right: 0; bottom: 0;
1500
+ background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.03) 50%, transparent 70%);
1501
+ animation: headerShimmer 4s infinite;
1502
+ pointer-events: none;
1503
+ }
1504
+
1505
+ @keyframes headerShimmer {
1506
+ 0% { transform: translateX(-100%); }
1507
+ 100% { transform: translateX(100%); }
1508
+ }
1509
+
961
1510
  .header-left {
962
1511
  display: flex;
963
1512
  align-items: center;
964
- gap: 12px;
1513
+ gap: 16px;
1514
+ z-index: 1;
965
1515
  }
1516
+
966
1517
  .logo {
967
- width: 28px;
968
- height: 28px;
969
- animation: pulse 2s infinite;
1518
+ width: 32px;
1519
+ height: 32px;
1520
+ filter: drop-shadow(0 4px 8px rgba(0,0,0,0.2));
1521
+ animation: logoFloat 3s ease-in-out infinite;
970
1522
  }
971
- @keyframes pulse {
972
- 0%, 100% { opacity: 1; }
973
- 50% { opacity: 0.8; }
1523
+
1524
+ @keyframes logoFloat {
1525
+ 0%, 100% { transform: translateY(0px); }
1526
+ 50% { transform: translateY(-3px); }
974
1527
  }
1528
+
975
1529
  .title {
976
- font-size: 18px;
977
- font-weight: 600;
978
- letter-spacing: -0.025em;
1530
+ font-size: 20px;
1531
+ font-weight: 700;
1532
+ text-shadow: 0 2px 4px rgba(0,0,0,0.1);
979
1533
  }
1534
+
980
1535
  .github-link {
981
- color: white;
1536
+ color: var(--text-primary);
982
1537
  text-decoration: none;
983
1538
  display: flex;
984
1539
  align-items: center;
985
- gap: 6px;
1540
+ gap: 8px;
986
1541
  font-size: 14px;
987
- opacity: 0.9;
988
- transition: opacity 0.2s;
989
- padding: 6px 10px;
990
- border-radius: 6px;
991
- background: rgba(255,255,255,0.1);
1542
+ background: rgba(255,255,255,0.08);
1543
+ border: 1px solid rgba(255, 255, 255, 0.12);
1544
+ backdrop-filter: blur(10px);
1545
+ padding: 8px 16px;
1546
+ border-radius: 8px;
1547
+ font-weight: 500;
1548
+ z-index: 1;
1549
+ transition: all 0.3s ease;
992
1550
  }
1551
+
993
1552
  .github-link:hover {
994
- opacity: 1;
995
- background: rgba(255,255,255,0.2);
1553
+ background: rgba(255,255,255,0.15);
1554
+ transform: translateY(-1px);
1555
+ box-shadow: 0 4px 12px rgba(0,0,0,0.3);
996
1556
  }
1557
+
997
1558
  .content {
998
1559
  padding: 32px 24px;
1560
+ position: relative;
999
1561
  }
1562
+
1000
1563
  .content-title {
1001
1564
  font-size: 24px;
1002
1565
  font-weight: 700;
1003
1566
  color: var(--text-primary);
1004
1567
  margin-bottom: 8px;
1568
+ animation: fadeInUp 0.8s ease-out 0.2s both;
1005
1569
  }
1570
+
1571
+ @keyframes fadeInUp {
1572
+ from {
1573
+ opacity: 0;
1574
+ transform: translateY(20px);
1575
+ }
1576
+ to {
1577
+ opacity: 1;
1578
+ transform: translateY(0);
1579
+ }
1580
+ }
1581
+
1006
1582
  .message {
1007
- background: #EEF2FF;
1008
- border: 1px solid #C7D2FE;
1009
- border-left: 4px solid var(--primary-color);
1583
+ background: rgba(103, 233, 233, 0.1);
1584
+ border: 1px solid var(--accent-color);
1585
+ border-left: 4px solid var(--accent-color);
1010
1586
  padding: 20px;
1011
1587
  border-radius: 12px;
1012
1588
  margin-bottom: 24px;
1013
1589
  font-size: 15px;
1014
1590
  line-height: 1.6;
1015
1591
  color: var(--text-primary);
1592
+ animation: fadeInUp 0.8s ease-out 0.4s both;
1593
+ position: relative;
1594
+ overflow: hidden;
1595
+ }
1596
+
1597
+ .message::before {
1598
+ content: '';
1599
+ position: absolute;
1600
+ top: 0; left: 0;
1601
+ width: 100%; height: 2px;
1602
+ background: linear-gradient(90deg, var(--accent-color), transparent);
1603
+ animation: progress 2s ease-out;
1604
+ }
1605
+
1606
+ @keyframes progress {
1607
+ from { width: 0%; }
1608
+ to { width: 100%; }
1016
1609
  }
1610
+
1017
1611
  .options {
1018
1612
  margin-bottom: 24px;
1613
+ animation: fadeInUp 0.8s ease-out 0.6s both;
1019
1614
  }
1615
+
1020
1616
  .option-item {
1021
1617
  padding: 16px 20px;
1022
1618
  border: 1px solid var(--border-color);
1023
1619
  border-radius: 12px;
1024
1620
  margin-bottom: 12px;
1025
1621
  cursor: pointer;
1026
- transition: all 0.2s;
1622
+ transition: all 0.3s ease;
1027
1623
  display: flex;
1028
1624
  align-items: center;
1029
1625
  gap: 14px;
1626
+ background: rgba(255, 255, 255, 0.03);
1627
+ position: relative;
1628
+ overflow: hidden;
1629
+ color: var(--text-primary);
1630
+ }
1631
+
1632
+ .option-item::before {
1633
+ content: '';
1634
+ position: absolute;
1635
+ left: 0; top: 0; bottom: 0;
1636
+ width: 0;
1637
+ background: var(--accent-color);
1638
+ transition: width 0.3s ease;
1030
1639
  }
1640
+
1031
1641
  .option-item:hover {
1032
1642
  background: var(--bg-secondary);
1033
- border-color: var(--primary-color);
1643
+ border-color: var(--accent-color);
1644
+ transform: translateX(5px);
1034
1645
  }
1646
+
1647
+ .option-item:hover::before {
1648
+ width: 4px;
1649
+ }
1650
+
1035
1651
  .option-item.selected {
1036
- background: #EEF2FF;
1037
- border-color: var(--primary-color);
1652
+ background: rgba(103, 233, 233, 0.1);
1653
+ border-color: var(--accent-color);
1654
+ transform: translateX(5px);
1038
1655
  }
1656
+
1657
+ .option-item.selected::before {
1658
+ width: 4px;
1659
+ }
1660
+
1039
1661
  .option-icon {
1040
1662
  width: 20px;
1041
1663
  height: 20px;
1042
- color: var(--primary-color);
1664
+ color: var(--accent-color);
1043
1665
  flex-shrink: 0;
1666
+ animation: iconGlow 2s ease-in-out infinite;
1044
1667
  }
1668
+
1669
+ @keyframes iconGlow {
1670
+ 0%, 100% { filter: drop-shadow(0 0 2px rgba(103, 233, 233, 0.3)); }
1671
+ 50% { filter: drop-shadow(0 0 8px rgba(103, 233, 233, 0.6)); }
1672
+ }
1673
+
1045
1674
  .custom-input {
1046
1675
  margin-bottom: 24px;
1676
+ animation: fadeInUp 0.8s ease-out 0.8s both;
1047
1677
  }
1678
+
1048
1679
  .custom-input textarea {
1049
1680
  width: 100%;
1050
1681
  min-height: 120px;
@@ -1054,19 +1685,30 @@ export class InteractiveServer {
1054
1685
  font-size: 15px;
1055
1686
  font-family: var(--font-mono);
1056
1687
  resize: vertical;
1057
- transition: all 0.2s;
1688
+ transition: all 0.3s ease;
1058
1689
  line-height: 1.5;
1690
+ background: rgba(255, 255, 255, 0.03);
1691
+ color: var(--text-primary);
1692
+ }
1693
+
1694
+ .custom-input textarea::placeholder {
1695
+ color: var(--text-secondary);
1059
1696
  }
1697
+
1060
1698
  .custom-input textarea:focus {
1061
1699
  outline: none;
1062
- border-color: var(--primary-color);
1063
- box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1);
1700
+ border-color: var(--accent-color);
1701
+ box-shadow: 0 0 0 3px rgba(103, 233, 233, 0.1);
1702
+ background: rgba(255, 255, 255, 0.05);
1064
1703
  }
1704
+
1065
1705
  .actions {
1066
1706
  display: flex;
1067
1707
  gap: 12px;
1068
1708
  justify-content: flex-end;
1709
+ animation: fadeInUp 0.8s ease-out 1s both;
1069
1710
  }
1711
+
1070
1712
  .btn {
1071
1713
  padding: 12px 20px;
1072
1714
  border: none;
@@ -1074,31 +1716,58 @@ export class InteractiveServer {
1074
1716
  font-size: 14px;
1075
1717
  font-weight: 600;
1076
1718
  cursor: pointer;
1077
- transition: all 0.2s;
1719
+ transition: all 0.3s ease;
1078
1720
  display: flex;
1079
1721
  align-items: center;
1080
1722
  gap: 8px;
1081
1723
  font-family: var(--font-mono);
1724
+ position: relative;
1725
+ overflow: hidden;
1726
+ }
1727
+
1728
+ .btn::before {
1729
+ content: '';
1730
+ position: absolute;
1731
+ top: 50%; left: 50%;
1732
+ width: 0; height: 0;
1733
+ background: rgba(255,255,255,0.2);
1734
+ border-radius: 50%;
1735
+ transition: all 0.3s ease;
1736
+ transform: translate(-50%, -50%);
1737
+ }
1738
+
1739
+ .btn:hover::before {
1740
+ width: 100px; height: 100px;
1082
1741
  }
1742
+
1083
1743
  .btn-primary {
1084
1744
  background: var(--primary-color);
1085
- color: white;
1745
+ color: var(--text-primary);
1746
+ border: 1px solid var(--border-color);
1086
1747
  }
1748
+
1087
1749
  .btn-primary:hover:not(:disabled) {
1088
1750
  background: var(--primary-hover);
1089
- transform: translateY(-1px);
1751
+ transform: translateY(-2px);
1752
+ box-shadow: 0 8px 25px rgba(0, 0, 0, 0.3);
1090
1753
  }
1754
+
1091
1755
  .btn-secondary {
1092
1756
  background: var(--bg-secondary);
1093
1757
  color: var(--text-secondary);
1758
+ border: 1px solid var(--border-color);
1094
1759
  }
1760
+
1095
1761
  .btn-secondary:hover {
1096
- background: #F3F4F6;
1762
+ background: rgba(255, 255, 255, 0.15);
1763
+ color: var(--text-primary);
1097
1764
  }
1765
+
1098
1766
  .btn:disabled {
1099
1767
  opacity: 0.5;
1100
1768
  cursor: not-allowed;
1101
1769
  }
1770
+
1102
1771
  .loading {
1103
1772
  display: none;
1104
1773
  align-items: center;
@@ -1108,14 +1777,16 @@ export class InteractiveServer {
1108
1777
  color: var(--text-secondary);
1109
1778
  font-size: 14px;
1110
1779
  }
1780
+
1111
1781
  .spinner {
1112
1782
  width: 16px;
1113
1783
  height: 16px;
1114
1784
  border: 2px solid var(--border-color);
1115
- border-top: 2px solid var(--primary-color);
1785
+ border-top: 2px solid var(--accent-color);
1116
1786
  border-radius: 50%;
1117
1787
  animation: spin 1s linear infinite;
1118
1788
  }
1789
+
1119
1790
  @keyframes spin {
1120
1791
  0% { transform: rotate(0deg); }
1121
1792
  100% { transform: rotate(360deg); }
@@ -1126,11 +1797,7 @@ export class InteractiveServer {
1126
1797
  <div class="modal">
1127
1798
  <div class="header">
1128
1799
  <div class="header-left">
1129
- <svg class="logo" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1130
- <path d="M12 2L2 7V17L12 22L22 17V7L12 2Z"/>
1131
- <path d="M12 22V12"/>
1132
- <path d="M22 7L12 12L2 7"/>
1133
- </svg>
1800
+ <img class="logo" src="https://7463-tcb-advanced-a656fc-1257967285.tcb.qcloud.la/mcp/cloudbase-logo.svg" alt="CloudBase Logo" />
1134
1801
  <span class="title">CloudBase AI Toolkit</span>
1135
1802
  </div>
1136
1803
  <a href="https://github.com/TencentCloudBase/CloudBase-AI-ToolKit" target="_blank" class="github-link">
@@ -1148,11 +1815,11 @@ export class InteractiveServer {
1148
1815
  ${optionsArray ? `
1149
1816
  <div class="options" id="options">
1150
1817
  ${optionsArray.map((option, index) => `
1151
- <div class="option-item" onclick="selectOption('${option}')">
1818
+ <div class="option-item" onclick="selectOption('${option}')" style="animation-delay: ${index * 0.1}s;">
1152
1819
  <svg class="option-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1153
1820
  <path d="M21 11.5a8.38 8.38 0 01-.9 3.8 8.5 8.5 0 01-7.6 4.7 8.38 8.38 0 01-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 01-.9-3.8 8.5 8.5 0 014.7-7.6 8.38 8.38 0 013.8-.9h.5a8.48 8.48 0 018 8v.5z"/>
1154
1821
  </svg>
1155
- ${option}
1822
+ <span>${option}</span>
1156
1823
  </div>
1157
1824
  `).join('')}
1158
1825
  </div>
@@ -1195,47 +1862,67 @@ export class InteractiveServer {
1195
1862
  });
1196
1863
  event.currentTarget.classList.add('selected');
1197
1864
 
1198
- document.getElementById('customInput').value = option;
1199
1865
  updateSubmitButton();
1200
1866
  }
1201
1867
 
1202
1868
  function updateSubmitButton() {
1203
1869
  const customInput = document.getElementById('customInput').value.trim();
1204
1870
  const submitBtn = document.getElementById('submitBtn');
1205
- submitBtn.disabled = !customInput;
1871
+
1872
+ if (selectedOption || customInput) {
1873
+ submitBtn.disabled = false;
1874
+ submitBtn.style.opacity = '1';
1875
+ } else {
1876
+ submitBtn.disabled = true;
1877
+ submitBtn.style.opacity = '0.5';
1878
+ }
1206
1879
  }
1207
1880
 
1208
1881
  function submit() {
1209
1882
  const customInput = document.getElementById('customInput').value.trim();
1883
+ const data = selectedOption || customInput;
1210
1884
 
1211
- if (!customInput) {
1212
- alert('请输入反馈内容');
1213
- return;
1214
- }
1885
+ if (!data) return;
1215
1886
 
1216
1887
  document.getElementById('loading').style.display = 'flex';
1888
+ document.getElementById('submitBtn').disabled = true;
1217
1889
 
1218
1890
  fetch('/api/submit', {
1219
1891
  method: 'POST',
1220
1892
  headers: { 'Content-Type': 'application/json' },
1221
1893
  body: JSON.stringify({
1222
1894
  type: 'clarification',
1223
- data: { response: customInput }
1895
+ data: data
1224
1896
  })
1225
- }).then(() => window.close());
1897
+ }).then(response => response.json())
1898
+ .then(result => {
1899
+ if (result.success) {
1900
+ window.close();
1901
+ }
1902
+ }).catch(err => {
1903
+ console.error('Error:', err);
1904
+ document.getElementById('loading').style.display = 'none';
1905
+ document.getElementById('submitBtn').disabled = false;
1906
+ });
1226
1907
  }
1227
1908
 
1228
1909
  function cancel() {
1229
- fetch('/api/cancel', { method: 'POST' }).then(() => window.close());
1910
+ fetch('/api/cancel', {
1911
+ method: 'POST',
1912
+ headers: { 'Content-Type': 'application/json' }
1913
+ }).then(() => {
1914
+ window.close();
1915
+ });
1230
1916
  }
1231
1917
 
1918
+ // Initialize
1232
1919
  updateSubmitButton();
1233
1920
  </script>
1234
1921
  </body>
1235
1922
  </html>`;
1236
1923
  }
1237
1924
  getConfirmationHTML(message, risks, options) {
1238
- const confirmOptions = options || ["确认执行", "取消操作", "需要修改"];
1925
+ const availableOptions = options || ['确认执行', '取消操作'];
1239
1926
  return `
1240
1927
  <!DOCTYPE html>
1241
1928
  <html lang="zh-CN">
@@ -1244,254 +1931,383 @@ export class InteractiveServer {
1244
1931
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
1245
1932
  <title>CloudBase AI Toolkit - 操作确认</title>
1246
1933
  <style>
1934
+ @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&display=swap');
1935
+
1247
1936
  * { margin: 0; padding: 0; box-sizing: border-box; }
1248
1937
  :root {
1249
- --primary-color: #4F46E5;
1250
- --primary-hover: #4338CA;
1251
- --text-primary: #1F2937;
1252
- --text-secondary: #6B7280;
1253
- --border-color: #E5E7EB;
1254
- --bg-secondary: #F9FAFB;
1255
- --warning-color: #DC2626;
1256
- --warning-bg: #FEF2F2;
1257
- --warning-border: #FECACA;
1258
- --shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
1259
- --font-mono: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', 'Source Code Pro', monospace;
1938
+ --primary-color: #1a1a1a;
1939
+ --primary-hover: #000000;
1940
+ --accent-color: #67E9E9;
1941
+ --accent-hover: #2BCCCC;
1942
+ --text-primary: #ffffff;
1943
+ --text-secondary: #a0a0a0;
1944
+ --border-color: rgba(255, 255, 255, 0.15);
1945
+ --bg-secondary: rgba(255, 255, 255, 0.08);
1946
+ --bg-glass: rgba(26, 26, 26, 0.95);
1947
+ --warning-color: #ff6b6b;
1948
+ --warning-bg: rgba(255, 107, 107, 0.1);
1949
+ --warning-border: rgba(255, 107, 107, 0.3);
1950
+ --shadow: 0 25px 50px rgba(0, 0, 0, 0.3), 0 10px 20px rgba(0, 0, 0, 0.2);
1951
+ --font-mono: 'JetBrains Mono', 'SF Mono', 'Monaco', monospace;
1952
+ --header-bg: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 50%, #0d1117 100%);
1260
1953
  }
1954
+
1261
1955
  body {
1262
1956
  font-family: var(--font-mono);
1263
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
1957
+ background: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 100%);
1264
1958
  min-height: 100vh;
1265
1959
  display: flex;
1266
1960
  align-items: center;
1267
1961
  justify-content: center;
1268
1962
  padding: 20px;
1963
+ position: relative;
1964
+ overflow-x: hidden;
1965
+ overflow-y: auto;
1966
+ }
1967
+
1968
+ /* Custom scrollbar styles */
1969
+ ::-webkit-scrollbar {
1970
+ width: 8px;
1971
+ }
1972
+
1973
+ ::-webkit-scrollbar-track {
1974
+ background: rgba(255, 255, 255, 0.05);
1975
+ border-radius: 4px;
1976
+ }
1977
+
1978
+ ::-webkit-scrollbar-thumb {
1979
+ background: var(--accent-color);
1980
+ border-radius: 4px;
1269
1981
  }
1982
+
1983
+ ::-webkit-scrollbar-thumb:hover {
1984
+ background: var(--accent-hover);
1985
+ }
1986
+
1987
+ body::before {
1988
+ content: '';
1989
+ position: fixed;
1990
+ top: 0; left: 0; right: 0; bottom: 0;
1991
+ 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;
1992
+ pointer-events: none;
1993
+ z-index: -1;
1994
+ }
1995
+
1996
+ body::after {
1997
+ content: '';
1998
+ position: fixed;
1999
+ top: 50%; left: 50%;
2000
+ width: 500px; height: 500px;
2001
+ background: radial-gradient(circle, rgba(255, 107, 107, 0.03) 0%, transparent 70%);
2002
+ transform: translate(-50%, -50%);
2003
+ pointer-events: none;
2004
+ z-index: -1;
2005
+ animation: pulse 8s ease-in-out infinite;
2006
+ }
2007
+
2008
+ @keyframes pulse {
2009
+ 0%, 100% { opacity: 0.3; transform: translate(-50%, -50%) scale(1); }
2010
+ 50% { opacity: 0.6; transform: translate(-50%, -50%) scale(1.1); }
2011
+ }
2012
+
1270
2013
  .modal {
1271
- background: white;
1272
- border-radius: 16px;
2014
+ background: var(--bg-glass);
2015
+ backdrop-filter: blur(20px);
2016
+ border-radius: 20px;
1273
2017
  box-shadow: var(--shadow);
2018
+ border: 2px solid var(--border-color);
1274
2019
  width: 100%;
1275
2020
  max-width: 600px;
1276
2021
  overflow: hidden;
1277
- animation: modalIn 0.3s ease-out;
2022
+ animation: modalIn 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275);
2023
+ position: relative;
2024
+ }
2025
+
2026
+ .modal::before {
2027
+ content: '';
2028
+ position: absolute;
2029
+ top: 0; left: 0; right: 0; bottom: 0;
2030
+ background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.02) 50%, transparent 70%);
2031
+ animation: shimmer 3s infinite;
2032
+ pointer-events: none;
2033
+ }
2034
+
2035
+ @keyframes shimmer {
2036
+ 0% { transform: translateX(-100%); }
2037
+ 100% { transform: translateX(100%); }
1278
2038
  }
2039
+
1279
2040
  @keyframes modalIn {
1280
2041
  from {
1281
2042
  opacity: 0;
1282
- transform: scale(0.95) translateY(-10px);
2043
+ transform: scale(0.9) translateY(-20px);
1283
2044
  }
1284
2045
  to {
1285
2046
  opacity: 1;
1286
2047
  transform: scale(1) translateY(0);
1287
2048
  }
1288
2049
  }
2050
+
1289
2051
  .header {
1290
- background: var(--primary-color);
1291
- color: white;
1292
- padding: 20px 24px;
2052
+ background: var(--header-bg);
2053
+ color: var(--text-primary);
2054
+ padding: 24px 28px;
1293
2055
  display: flex;
1294
2056
  align-items: center;
1295
2057
  justify-content: space-between;
2058
+ position: relative;
2059
+ overflow: hidden;
2060
+ }
2061
+
2062
+ .header::before {
2063
+ content: '';
2064
+ position: absolute;
2065
+ top: 0; left: 0; right: 0; bottom: 0;
2066
+ background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.03) 50%, transparent 70%);
2067
+ animation: headerShimmer 4s infinite;
2068
+ pointer-events: none;
1296
2069
  }
2070
+
2071
+ @keyframes headerShimmer {
2072
+ 0% { transform: translateX(-100%); }
2073
+ 100% { transform: translateX(100%); }
2074
+ }
2075
+
1297
2076
  .header-left {
1298
2077
  display: flex;
1299
2078
  align-items: center;
1300
- gap: 12px;
2079
+ gap: 16px;
2080
+ z-index: 1;
1301
2081
  }
2082
+
1302
2083
  .logo {
1303
- width: 28px;
1304
- height: 28px;
1305
- animation: pulse 2s infinite;
2084
+ width: 32px;
2085
+ height: 32px;
2086
+ filter: drop-shadow(0 4px 8px rgba(0,0,0,0.2));
2087
+ animation: logoFloat 3s ease-in-out infinite;
2088
+ }
2089
+
2090
+ @keyframes logoFloat {
2091
+ 0%, 100% { transform: translateY(0px); }
2092
+ 50% { transform: translateY(-3px); }
1306
2093
  }
2094
+
1307
2095
  .title {
1308
- font-size: 18px;
1309
- font-weight: 600;
1310
- letter-spacing: -0.025em;
2096
+ font-size: 20px;
2097
+ font-weight: 700;
2098
+ text-shadow: 0 2px 4px rgba(0,0,0,0.1);
1311
2099
  }
2100
+
1312
2101
  .github-link {
1313
- color: white;
2102
+ color: var(--text-primary);
1314
2103
  text-decoration: none;
1315
2104
  display: flex;
1316
2105
  align-items: center;
1317
- gap: 6px;
2106
+ gap: 8px;
1318
2107
  font-size: 14px;
1319
- opacity: 0.9;
1320
- transition: opacity 0.2s;
1321
- padding: 6px 10px;
1322
- border-radius: 6px;
1323
- background: rgba(255,255,255,0.1);
2108
+ background: rgba(255,255,255,0.08);
2109
+ border: 1px solid rgba(255, 255, 255, 0.12);
2110
+ backdrop-filter: blur(10px);
2111
+ padding: 8px 16px;
2112
+ border-radius: 8px;
2113
+ font-weight: 500;
2114
+ z-index: 1;
2115
+ transition: all 0.3s ease;
1324
2116
  }
2117
+
1325
2118
  .github-link:hover {
1326
- opacity: 1;
1327
- background: rgba(255,255,255,0.2);
2119
+ background: rgba(255,255,255,0.15);
2120
+ transform: translateY(-1px);
2121
+ box-shadow: 0 4px 12px rgba(0,0,0,0.3);
1328
2122
  }
2123
+
1329
2124
  .content {
1330
2125
  padding: 32px 24px;
2126
+ position: relative;
1331
2127
  }
1332
- @keyframes slideIn {
2128
+
2129
+ @keyframes fadeInUp {
1333
2130
  from {
1334
2131
  opacity: 0;
1335
- transform: translateY(-20px);
2132
+ transform: translateY(20px);
1336
2133
  }
1337
2134
  to {
1338
2135
  opacity: 1;
1339
2136
  transform: translateY(0);
1340
2137
  }
1341
2138
  }
1342
- @keyframes pulse {
1343
- 0% {
1344
- transform: scale(1);
1345
- }
1346
- 50% {
1347
- transform: scale(1.05);
1348
- }
1349
- 100% {
1350
- transform: scale(1);
1351
- }
1352
- }
1353
- .title {
1354
- font-size: 20px;
1355
- margin-bottom: 16px;
2139
+
2140
+ .content-title {
2141
+ font-size: 24px;
2142
+ margin-bottom: 8px;
1356
2143
  color: var(--text-primary);
1357
2144
  display: flex;
1358
2145
  align-items: center;
1359
2146
  gap: 12px;
1360
2147
  position: relative;
2148
+ animation: fadeInUp 0.8s ease-out 0.2s both;
1361
2149
  }
1362
- .title:after {
1363
- content: '';
1364
- position: absolute;
1365
- bottom: -8px;
1366
- left: 0;
1367
- width: 40px;
1368
- height: 3px;
1369
- background: var(--primary-color);
1370
- border-radius: 2px;
1371
- }
2150
+
1372
2151
  .message {
1373
- background: var(--bg-secondary);
1374
- border-left: 3px solid var(--primary-color);
1375
- padding: 16px;
1376
- border-radius: 6px;
2152
+ background: rgba(103, 233, 233, 0.1);
2153
+ border: 1px solid var(--accent-color);
2154
+ border-left: 4px solid var(--accent-color);
2155
+ padding: 20px;
2156
+ border-radius: 12px;
1377
2157
  margin-bottom: 24px;
1378
2158
  font-size: 15px;
1379
2159
  line-height: 1.6;
1380
2160
  color: var(--text-primary);
2161
+ animation: fadeInUp 0.8s ease-out 0.4s both;
2162
+ position: relative;
2163
+ overflow: hidden;
1381
2164
  }
2165
+
2166
+ .message::before {
2167
+ content: '';
2168
+ position: absolute;
2169
+ top: 0; left: 0;
2170
+ width: 100%; height: 2px;
2171
+ background: linear-gradient(90deg, var(--accent-color), transparent);
2172
+ animation: progress 2s ease-out;
2173
+ }
2174
+
2175
+ @keyframes progress {
2176
+ from { width: 0%; }
2177
+ to { width: 100%; }
2178
+ }
2179
+
1382
2180
  .risks {
1383
2181
  background: var(--warning-bg);
1384
- border: 1px solid var(--warning-color);
1385
- border-radius: 6px;
1386
- padding: 16px;
2182
+ border: 1px solid var(--warning-border);
2183
+ border-radius: 12px;
2184
+ padding: 20px;
1387
2185
  margin-bottom: 24px;
2186
+ animation: fadeInUp 0.8s ease-out 0.6s both;
1388
2187
  }
2188
+
1389
2189
  .risks-title {
1390
2190
  color: var(--warning-color);
1391
- font-weight: 500;
2191
+ font-weight: 600;
1392
2192
  margin-bottom: 12px;
1393
2193
  display: flex;
1394
2194
  align-items: center;
1395
2195
  gap: 8px;
2196
+ animation: warningGlow 2s ease-in-out infinite;
2197
+ }
2198
+
2199
+ @keyframes warningGlow {
2200
+ 0%, 100% { filter: drop-shadow(0 0 2px rgba(255, 107, 107, 0.3)); }
2201
+ 50% { filter: drop-shadow(0 0 8px rgba(255, 107, 107, 0.6)); }
1396
2202
  }
2203
+
1397
2204
  .risk-item {
1398
2205
  color: var(--text-primary);
1399
2206
  margin-bottom: 8px;
1400
2207
  padding-left: 24px;
1401
2208
  position: relative;
1402
2209
  }
2210
+
1403
2211
  .risk-item:before {
1404
- content: "";
2212
+ content: "⚠️";
1405
2213
  position: absolute;
1406
- left: 8px;
2214
+ left: 0;
1407
2215
  color: var(--warning-color);
1408
2216
  }
2217
+
1409
2218
  .options {
1410
2219
  margin-bottom: 24px;
2220
+ animation: fadeInUp 0.8s ease-out 0.8s both;
1411
2221
  }
2222
+
1412
2223
  .option-item {
1413
- padding: 16px;
2224
+ padding: 16px 20px;
1414
2225
  border: 1px solid var(--border-color);
1415
- border-radius: 6px;
2226
+ border-radius: 12px;
1416
2227
  margin-bottom: 12px;
1417
2228
  cursor: pointer;
1418
- transition: all 0.2s;
2229
+ transition: all 0.3s ease;
1419
2230
  display: flex;
1420
2231
  align-items: center;
1421
- gap: 12px;
1422
- }
1423
- .option-item:hover {
1424
- background: var(--bg-secondary);
2232
+ gap: 14px;
2233
+ background: rgba(255, 255, 255, 0.03);
2234
+ position: relative;
2235
+ overflow: hidden;
2236
+ color: var(--text-primary);
1425
2237
  }
1426
- .option-item.selected {
1427
- background: rgba(0, 82, 217, 0.1);
1428
- border-color: var(--primary-color);
2238
+
2239
+ .option-item::before {
2240
+ content: '';
2241
+ position: absolute;
2242
+ left: 0; top: 0; bottom: 0;
2243
+ width: 0;
2244
+ background: var(--accent-color);
2245
+ transition: width 0.3s ease;
1429
2246
  }
1430
- .button-group {
1431
- display: flex;
1432
- gap: 12px;
1433
- justify-content: flex-end;
2247
+
2248
+ .option-item.confirm::before {
2249
+ background: var(--accent-color);
1434
2250
  }
1435
- .btn {
1436
- padding: 10px 20px;
1437
- border: none;
1438
- border-radius: 8px;
1439
- font-size: 14px;
1440
- font-weight: 500;
1441
- cursor: pointer;
1442
- transition: all 0.2s;
1443
- display: flex;
1444
- align-items: center;
1445
- gap: 8px;
1446
- font-family: var(--font-mono);
1447
- text-transform: uppercase;
1448
- letter-spacing: 0.5px;
2251
+
2252
+ .option-item.cancel::before {
2253
+ background: var(--warning-color);
1449
2254
  }
1450
- .btn-primary {
1451
- background: var(--primary-color);
1452
- color: white;
1453
- box-shadow: 0 4px 12px rgba(0,82,217,0.2);
2255
+
2256
+ .option-item:hover {
2257
+ background: var(--bg-secondary);
2258
+ transform: translateX(5px);
1454
2259
  }
1455
- .btn-primary:hover {
1456
- background: var(--hover-color);
1457
- transform: translateY(-1px);
1458
- box-shadow: 0 6px 16px rgba(0,82,217,0.3);
2260
+
2261
+ .option-item:hover::before {
2262
+ width: 4px;
1459
2263
  }
1460
- .btn-secondary {
1461
- background: var(--bg-secondary);
1462
- color: var(--text-secondary);
2264
+
2265
+ .option-item.selected {
2266
+ background: rgba(103, 233, 233, 0.1);
2267
+ border-color: var(--accent-color);
2268
+ transform: translateX(5px);
1463
2269
  }
1464
- .btn-secondary:hover {
1465
- background: #E0E0E0;
1466
- transform: translateY(-1px);
2270
+
2271
+ .option-item.selected.cancel {
2272
+ background: rgba(255, 107, 107, 0.1);
2273
+ border-color: var(--warning-color);
1467
2274
  }
1468
- .btn-warning {
1469
- background: var(--warning-color);
1470
- color: white;
2275
+
2276
+ .option-item.selected::before {
2277
+ width: 4px;
1471
2278
  }
1472
- .btn-warning:hover {
1473
- background: #FF7875;
2279
+
2280
+ .option-icon {
2281
+ width: 20px;
2282
+ height: 20px;
2283
+ color: var(--accent-color);
2284
+ flex-shrink: 0;
1474
2285
  }
1475
- .btn:disabled {
1476
- opacity: 0.6;
1477
- cursor: not-allowed;
2286
+
2287
+ .option-item.cancel .option-icon {
2288
+ color: var(--warning-color);
1478
2289
  }
2290
+
1479
2291
  .loading {
1480
2292
  display: none;
1481
2293
  align-items: center;
2294
+ justify-content: center;
1482
2295
  gap: 8px;
1483
2296
  margin-top: 16px;
1484
2297
  color: var(--text-secondary);
1485
2298
  font-size: 14px;
2299
+ animation: fadeInUp 0.8s ease-out 1s both;
1486
2300
  }
2301
+
1487
2302
  .spinner {
1488
2303
  width: 16px;
1489
2304
  height: 16px;
1490
2305
  border: 2px solid var(--border-color);
1491
- border-top: 2px solid var(--primary-color);
2306
+ border-top: 2px solid var(--accent-color);
1492
2307
  border-radius: 50%;
1493
2308
  animation: spin 1s linear infinite;
1494
2309
  }
2310
+
1495
2311
  @keyframes spin {
1496
2312
  0% { transform: rotate(0deg); }
1497
2313
  100% { transform: rotate(360deg); }
@@ -1502,11 +2318,7 @@ export class InteractiveServer {
1502
2318
  <div class="modal">
1503
2319
  <div class="header">
1504
2320
  <div class="header-left">
1505
- <svg class="logo" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1506
- <path d="M12 2L2 7V17L12 22L22 17V7L12 2Z"/>
1507
- <path d="M12 22V12"/>
1508
- <path d="M22 7L12 12L2 7"/>
1509
- </svg>
2321
+ <img class="logo" src="https://7463-tcb-advanced-a656fc-1257967285.tcb.qcloud.la/mcp/cloudbase-logo.svg" alt="CloudBase Logo" />
1510
2322
  <span class="title">CloudBase AI Toolkit</span>
1511
2323
  </div>
1512
2324
  <a href="https://github.com/TencentCloudBase/CloudBase-AI-ToolKit" target="_blank" class="github-link">
@@ -1517,57 +2329,55 @@ export class InteractiveServer {
1517
2329
  </a>
1518
2330
  </div>
1519
2331
 
1520
- <div class="content">
1521
- <h1 class="content-title">
1522
- <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1523
- <path d="M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z"/>
1524
- <path d="M12 16V12"/>
1525
- <path d="M12 8H12.01"/>
2332
+ <div class="content">
2333
+ <h1 class="content-title">
2334
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
2335
+ <path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/>
2336
+ <line x1="12" y1="9" x2="12" y2="13"/>
2337
+ <line x1="12" y1="17" x2="12.01" y2="17"/>
2338
+ </svg>
2339
+ 操作确认
2340
+ </h1>
2341
+ <div class="message">${message}</div>
2342
+
2343
+ ${risks && risks.length > 0 ? `
2344
+ <div class="risks">
2345
+ <div class="risks-title">
2346
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
2347
+ <path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/>
2348
+ <line x1="12" y1="9" x2="12" y2="13"/>
2349
+ <line x1="12" y1="17" x2="12.01" y2="17"/>
1526
2350
  </svg>
1527
- 操作确认
1528
- </h1>
1529
-
1530
- <div class="message">${message}</div>
1531
-
1532
- ${risks && risks.length > 0 ? `
1533
- <div class="risks">
1534
- <div class="risks-title">
1535
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1536
- <path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"/>
1537
- <path d="M12 9v4"/>
1538
- <path d="M12 17h.01"/>
1539
- </svg>
1540
- 风险提示
1541
- </div>
1542
- ${risks.map(risk => `<div class="risk-item">${risk}</div>`).join('')}
2351
+ 风险提示
1543
2352
  </div>
1544
- ` : ''}
1545
-
1546
- <div class="options">
1547
- ${confirmOptions.map((option, index) => {
1548
- const className = option.includes('确认') ? 'confirm' : option.includes('取消') ? 'cancel' : '';
1549
- const iconPath = option.includes('确认') ?
1550
- '<path d="M20 6L9 17l-5-5"/>' :
1551
- option.includes('取消') ?
1552
- '<path d="M18 6L6 18M6 6l12 12"/>' :
1553
- '<path d="M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z"/>';
2353
+ ${risks.map(risk => `<div class="risk-item">${risk}</div>`).join('')}
2354
+ </div>
2355
+ ` : ''}
2356
+
2357
+ <div class="options">
2358
+ ${availableOptions.map((option, index) => {
2359
+ const isCancel = option.includes('取消') || option.toLowerCase().includes('cancel');
2360
+ const className = isCancel ? 'cancel' : 'confirm';
2361
+ const iconPath = isCancel
2362
+ ? '<path d="M18 6L6 18M6 6l12 12"/>'
2363
+ : '<path d="M20 6L9 17l-5-5"/>';
1554
2364
  return `
1555
- <div class="option-item ${className}" onclick="selectOption('${option}')">
1556
- <svg class="option-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1557
- ${iconPath}
1558
- </svg>
1559
- ${option}
1560
- </div>
1561
- `;
2365
+ <div class="option-item ${className}" onclick="selectOption('${option}')" style="animation-delay: ${index * 0.1}s;">
2366
+ <svg class="option-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
2367
+ ${iconPath}
2368
+ </svg>
2369
+ <span>${option}</span>
2370
+ </div>
2371
+ `;
1562
2372
  }).join('')}
1563
- </div>
1564
-
1565
- <div class="loading" id="loading">
1566
- <div class="spinner"></div>
1567
- <span>正在处理...</span>
1568
- </div>
2373
+ </div>
2374
+
2375
+ <div class="loading" id="loading">
2376
+ <div class="spinner"></div>
2377
+ <span>正在处理...</span>
1569
2378
  </div>
1570
2379
  </div>
2380
+ </div>
1571
2381
 
1572
2382
  <script>
1573
2383
  let selectedOption = null;
@@ -1580,31 +2390,47 @@ export class InteractiveServer {
1580
2390
  });
1581
2391
  event.currentTarget.classList.add('selected');
1582
2392
 
1583
- if (option.includes('确认')) {
2393
+ // Auto submit after selection
2394
+ setTimeout(() => {
1584
2395
  submit();
1585
- } else if (option.includes('取消')) {
1586
- cancel();
1587
- } else {
1588
- // 需要修改的情况
1589
- cancel();
1590
- }
2396
+ }, 500);
1591
2397
  }
1592
2398
 
1593
2399
  function submit() {
2400
+ if (!selectedOption) return;
2401
+
1594
2402
  document.getElementById('loading').style.display = 'flex';
1595
2403
 
2404
+ const isConfirmed = !selectedOption.includes('取消') && !selectedOption.toLowerCase().includes('cancel');
2405
+
1596
2406
  fetch('/api/submit', {
1597
2407
  method: 'POST',
1598
2408
  headers: { 'Content-Type': 'application/json' },
1599
2409
  body: JSON.stringify({
1600
2410
  type: 'confirmation',
1601
- data: { response: selectedOption || '确认执行' }
2411
+ data: {
2412
+ confirmed: isConfirmed,
2413
+ option: selectedOption
2414
+ }
1602
2415
  })
1603
- }).then(() => window.close());
2416
+ }).then(response => response.json())
2417
+ .then(result => {
2418
+ if (result.success) {
2419
+ window.close();
2420
+ }
2421
+ }).catch(err => {
2422
+ console.error('Error:', err);
2423
+ document.getElementById('loading').style.display = 'none';
2424
+ });
1604
2425
  }
1605
2426
 
1606
2427
  function cancel() {
1607
- fetch('/api/cancel', { method: 'POST' }).then(() => window.close());
2428
+ fetch('/api/cancel', {
2429
+ method: 'POST',
2430
+ headers: { 'Content-Type': 'application/json' }
2431
+ }).then(() => {
2432
+ window.close();
2433
+ });
1608
2434
  }
1609
2435
  </script>
1610
2436
  </body>