aicodeswitch 2.0.11 → 2.1.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.
@@ -287,6 +287,13 @@ class OpenAIToClaudeEventTransform extends stream_1.Transform {
287
287
  callback();
288
288
  return;
289
289
  }
290
+ // 检查是否是 OpenAI Responses API 的事件
291
+ // Responses API 事件类型如:response.reasoning_text.delta, response.output_text.delta 等
292
+ if (event.event && event.event.startsWith('response.')) {
293
+ this.handleResponsesAPIEvent(event);
294
+ callback();
295
+ return;
296
+ }
290
297
  const chunk = event.data;
291
298
  if (!chunk) {
292
299
  callback();
@@ -384,6 +391,7 @@ class OpenAIToClaudeEventTransform extends stream_1.Transform {
384
391
  },
385
392
  });
386
393
  }
394
+ // 处理 OpenAI Chat Completions API 的 thinking content
387
395
  if (typeof ((_a = delta.thinking) === null || _a === void 0 ? void 0 : _a.content) === 'string') {
388
396
  this.ensureMessageStart();
389
397
  if (this.thinkingBlockIndex === null) {
@@ -448,6 +456,107 @@ class OpenAIToClaudeEventTransform extends stream_1.Transform {
448
456
  }
449
457
  }
450
458
  }
459
+ // 处理 OpenAI Responses API 的流式事件
460
+ handleResponsesAPIEvent(event) {
461
+ const type = event.event;
462
+ const data = event.data;
463
+ // 处理 reasoning 文本增量(完整推理过程)
464
+ if (type === 'response.reasoning_text.delta' && (data === null || data === void 0 ? void 0 : data.delta)) {
465
+ this.ensureMessageStart();
466
+ if (this.thinkingBlockIndex === null) {
467
+ this.thinkingBlockIndex = this.assignContentBlockIndex();
468
+ this.pushEvent('content_block_start', {
469
+ type: 'content_block_start',
470
+ index: this.thinkingBlockIndex,
471
+ content_block: { type: 'thinking', thinking: '' },
472
+ });
473
+ }
474
+ this.pushEvent('content_block_delta', {
475
+ type: 'content_block_delta',
476
+ index: this.thinkingBlockIndex,
477
+ delta: {
478
+ type: 'thinking_delta',
479
+ thinking: data.delta,
480
+ },
481
+ });
482
+ }
483
+ // 处理 reasoning summary 文本增量(推理摘要)
484
+ if (type === 'response.reasoning_summary_text.delta' && (data === null || data === void 0 ? void 0 : data.delta)) {
485
+ this.ensureMessageStart();
486
+ if (this.thinkingBlockIndex === null) {
487
+ this.thinkingBlockIndex = this.assignContentBlockIndex();
488
+ this.pushEvent('content_block_start', {
489
+ type: 'content_block_start',
490
+ index: this.thinkingBlockIndex,
491
+ content_block: { type: 'thinking', thinking: '' },
492
+ });
493
+ }
494
+ this.pushEvent('content_block_delta', {
495
+ type: 'content_block_delta',
496
+ index: this.thinkingBlockIndex,
497
+ delta: {
498
+ type: 'thinking_delta',
499
+ thinking: data.delta,
500
+ },
501
+ });
502
+ }
503
+ // 处理普通文本增量
504
+ if (type === 'response.output_text.delta' && (data === null || data === void 0 ? void 0 : data.delta)) {
505
+ this.ensureMessageStart();
506
+ if (this.textBlockIndex === null) {
507
+ this.textBlockIndex = this.assignContentBlockIndex();
508
+ this.pushEvent('content_block_start', {
509
+ type: 'content_block_start',
510
+ index: this.textBlockIndex,
511
+ content_block: { type: 'text' },
512
+ });
513
+ }
514
+ this.pushEvent('content_block_delta', {
515
+ type: 'content_block_delta',
516
+ index: this.textBlockIndex,
517
+ delta: {
518
+ type: 'text_delta',
519
+ text: data.delta,
520
+ },
521
+ });
522
+ }
523
+ // 处理拒绝内容增量(内容过滤等)
524
+ if (type === 'response.refusal.delta' && (data === null || data === void 0 ? void 0 : data.delta)) {
525
+ // 拒绝内容可以作为文本发送
526
+ this.ensureMessageStart();
527
+ if (this.textBlockIndex === null) {
528
+ this.textBlockIndex = this.assignContentBlockIndex();
529
+ this.pushEvent('content_block_start', {
530
+ type: 'content_block_start',
531
+ index: this.textBlockIndex,
532
+ content_block: { type: 'text' },
533
+ });
534
+ }
535
+ this.pushEvent('content_block_delta', {
536
+ type: 'content_block_delta',
537
+ index: this.textBlockIndex,
538
+ delta: {
539
+ type: 'text_delta',
540
+ text: data.delta,
541
+ },
542
+ });
543
+ }
544
+ // 处理函数调用参数增量
545
+ if (type === 'response.function_call_arguments.delta' && (data === null || data === void 0 ? void 0 : data.delta)) {
546
+ // OpenAI Responses API 的函数调用
547
+ // 这需要与现有的 tool_calls 处理逻辑配合
548
+ // 暂时先跳过,因为 Responses API 使用不同的函数调用格式
549
+ }
550
+ // 处理响应完成事件
551
+ if (type === 'response.completed' || type === 'response.failed' || type === 'response.incomplete') {
552
+ // 确保所有内容块都已关闭
553
+ this.finalize();
554
+ }
555
+ // 处理响应创建和进行中事件
556
+ if (type === 'response.created' || type === 'response.in_progress') {
557
+ this.ensureMessageStart();
558
+ }
559
+ }
451
560
  finalize() {
452
561
  if (this.finalized)
453
562
  return;
@@ -536,6 +645,12 @@ class ClaudeToOpenAIChatEventTransform extends stream_1.Transform {
536
645
  writable: true,
537
646
  value: null
538
647
  });
648
+ Object.defineProperty(this, "stopReason", {
649
+ enumerable: true,
650
+ configurable: true,
651
+ writable: true,
652
+ value: 'stop'
653
+ }); // OpenAI 的 finish_reason
539
654
  Object.defineProperty(this, "errorEmitted", {
540
655
  enumerable: true,
541
656
  configurable: true,
@@ -573,6 +688,9 @@ class ClaudeToOpenAIChatEventTransform extends stream_1.Transform {
573
688
  if (data.content_block.type === 'text') {
574
689
  // 文本块开始
575
690
  }
691
+ else if (data.content_block.type === 'thinking') {
692
+ // thinking 块开始(无需特殊处理)
693
+ }
576
694
  else if (data.content_block.type === 'tool_use') {
577
695
  this.pendingToolCallId = data.content_block.id;
578
696
  this.pendingToolName = data.content_block.name;
@@ -588,6 +706,14 @@ class ClaudeToOpenAIChatEventTransform extends stream_1.Transform {
588
706
  this.push({ event: null, data: { id: '', model: this.model, choices: [{ index: 0, delta: { content: text } }] } });
589
707
  }
590
708
  }
709
+ else if (data.delta.type === 'thinking_delta') {
710
+ // 处理 thinking 增量,转换为 OpenAI 格式
711
+ const thinking = data.delta.thinking || '';
712
+ if (thinking) {
713
+ // OpenAI 兼容格式:使用 delta.thinking.content
714
+ this.push({ event: null, data: { id: '', model: this.model, choices: [{ index: 0, delta: { thinking: { content: thinking } } }] } });
715
+ }
716
+ }
591
717
  else if (data.delta.type === 'input_json_delta') {
592
718
  this.pendingToolArgs += data.delta.partial_json || '';
593
719
  }
@@ -616,11 +742,30 @@ class ClaudeToOpenAIChatEventTransform extends stream_1.Transform {
616
742
  }
617
743
  if (type === 'message_stop' || (data === null || data === void 0 ? void 0 : data.type) === 'message_stop') {
618
744
  this.finished = true;
619
- this.push({ event: null, data: { id: '', model: this.model, choices: [{ index: 0, delta: {}, finish_reason: 'stop' }] } });
745
+ // 使用映射后的 stop reason
746
+ this.push({ event: null, data: { id: '', model: this.model, choices: [{ index: 0, delta: {}, finish_reason: this.stopReason }] } });
620
747
  this.push({ event: 'done', data: { type: 'done' } });
621
748
  callback();
622
749
  return;
623
750
  }
751
+ // 处理 message_delta 事件(包含 stop_reason 和 usage)
752
+ if (type === 'message_delta' && (data === null || data === void 0 ? void 0 : data.delta)) {
753
+ // 映射 Claude 的 stop_reason 到 OpenAI 的 finish_reason
754
+ if (data.delta.stop_reason) {
755
+ this.stopReason = this.mapStopReason(data.delta.stop_reason);
756
+ }
757
+ // 处理 usage 信息
758
+ if (data.usage) {
759
+ this.usage = {
760
+ prompt_tokens: data.usage.input_tokens || 0,
761
+ completion_tokens: data.usage.output_tokens || 0,
762
+ total_tokens: (data.usage.input_tokens || 0) + (data.usage.output_tokens || 0),
763
+ };
764
+ }
765
+ // 不发送 delta 事件,只在最终 message_stop 时发送 finish_reason
766
+ callback();
767
+ return;
768
+ }
624
769
  if (data === null || data === void 0 ? void 0 : data.usage) {
625
770
  this.usage = {
626
771
  prompt_tokens: data.usage.input_tokens || 0,
@@ -639,7 +784,7 @@ class ClaudeToOpenAIChatEventTransform extends stream_1.Transform {
639
784
  try {
640
785
  if (!this.finished) {
641
786
  this.finished = true;
642
- this.push({ event: null, data: { id: '', model: this.model, choices: [{ index: 0, delta: {}, finish_reason: 'stop' }] } });
787
+ this.push({ event: null, data: { id: '', model: this.model, choices: [{ index: 0, delta: {}, finish_reason: this.stopReason }] } });
643
788
  this.push({ event: 'done', data: { type: 'done' } });
644
789
  }
645
790
  callback();
@@ -649,5 +794,27 @@ class ClaudeToOpenAIChatEventTransform extends stream_1.Transform {
649
794
  callback();
650
795
  }
651
796
  }
797
+ /**
798
+ * 将 Claude 的 stop_reason 映射到 OpenAI 的 finish_reason
799
+ * Claude: "end_turn" | "max_tokens" | "tool_use" | "stop_sequence" | "max_thinking_length"
800
+ * OpenAI: "stop" | "length" | "tool_calls" | "content_filter"
801
+ */
802
+ mapStopReason(stopReason) {
803
+ switch (stopReason) {
804
+ case 'end_turn':
805
+ return 'stop';
806
+ case 'max_tokens':
807
+ case 'max_thinking_length':
808
+ return 'length';
809
+ case 'tool_use':
810
+ return 'tool_calls';
811
+ case 'stop_sequence':
812
+ return 'stop';
813
+ case 'content_filter':
814
+ return 'content_filter';
815
+ default:
816
+ return 'stop';
817
+ }
818
+ }
652
819
  }
653
820
  exports.ClaudeToOpenAIChatEventTransform = ClaudeToOpenAIChatEventTransform;
@@ -0,0 +1 @@
1
+ .app{display:flex;width:100%;height:100%}.sidebar{width:260px;background:var(--bg-sidebar);color:var(--text-primary);display:flex;flex-direction:column;padding:0 0 80px;border-radius:20px;box-shadow:0 4px 12px #00000026;margin:16px;position:relative;z-index:1;border:1px solid rgba(255,255,255,.15)}.logo{padding:28px 20px;border-bottom:2px solid rgba(255,255,255,.2);text-align:center;position:relative;overflow:hidden}.logo:before{content:"✨";position:absolute;top:12px;left:12px;font-size:16px;opacity:.7;transition:all .3s ease}.logo:after{content:"🌟";position:absolute;top:12px;right:12px;font-size:16px;opacity:.7;transition:all .3s ease}.logo h2{font-size:22px;font-weight:800;background:linear-gradient(135deg,#fff,#f8f8ff,#e6e6fa);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;text-shadow:0 2px 4px rgba(0,0,0,.1);position:relative;z-index:1;letter-spacing:1px;text-transform:uppercase;transition:all .3s ease}.nav-menu{list-style:none;padding:16px 0;margin:0}.nav-menu li{margin:8px 12px}.nav-menu a{display:block;padding:14px 20px;color:var(--text-sidebar);text-decoration:none;border-radius:12px;transition:all .3s ease-out;font-weight:500;position:relative;overflow:hidden}.nav-menu a:before{content:"";position:absolute;top:0;left:-100%;width:100%;height:100%;background:linear-gradient(90deg,transparent,rgba(255,255,255,.15),transparent);transition:left .5s ease-out}.nav-menu a:hover:before{left:100%}.nav-menu a:hover{background-color:#ffffff1a;transform:translate(4px)}.nav-menu a.active{background:linear-gradient(135deg,var(--accent-primary),var(--accent-secondary))}.main-content{flex:1;padding:24px;overflow-y:auto;background:var(--bg-primary);position:relative;z-index:1;margin:16px 16px 16px 0;border-radius:20px}.main-content:before{content:"";position:absolute;top:0;left:0;right:0;bottom:0;background-image:radial-gradient(circle at 20% 80%,rgba(255,206,92,.1) 0%,transparent 50%),radial-gradient(circle at 80% 20%,rgba(134,204,202,.1) 0%,transparent 50%),radial-gradient(circle at 40% 40%,rgba(255,113,206,.05) 0%,transparent 50%);pointer-events:none}.page-header{margin-bottom:24px;position:relative;z-index:1}.page-header h1{font-family:Fredoka,sans-serif;font-size:28px;font-weight:700;color:var(--accent-primary);margin-bottom:8px;text-shadow:0 2px 4px var(--shadow-primary)}.page-header p{color:var(--text-muted);font-size:16px;font-weight:400}.card{background:var(--bg-card);border-radius:20px;padding:24px;box-shadow:0 2px 8px #00000014;margin-bottom:24px;border:1px solid var(--border-primary);position:relative;overflow:hidden;transition:all .3s ease-out}.card:before{content:"";position:absolute;top:0;left:0;right:0;height:4px;background:linear-gradient(90deg,var(--accent-primary),var(--accent-secondary));border-radius:20px 20px 0 0}.card:hover{transform:translateY(-2px);box-shadow:0 4px 12px #0000001f}.btn{padding:10px 20px;border:none;border-radius:12px;cursor:pointer;font-size:14px;font-weight:600;transition:all .3s ease-out;position:relative;overflow:hidden;white-space:nowrap}.btn:before{content:"";position:absolute;top:50%;left:50%;width:0;height:0;background:#ffffff4d;border-radius:50%;transform:translate(-50%,-50%);transition:width .6s,height .6s}.btn:hover:before{width:300px;height:300px}.btn:hover{transform:translateY(-1px)}.btn:active{transform:translateY(0)}.btn:disabled{opacity:.4;cursor:not-allowed}.btn-primary{background:linear-gradient(135deg,var(--accent-primary),var(--accent-secondary));color:#fff;position:relative;overflow:hidden}.btn-primary:before{content:"";position:absolute;top:0;left:-100%;width:100%;height:100%;background:linear-gradient(90deg,transparent,rgba(255,255,255,.3),transparent);transition:left .5s ease}.btn-primary:hover:before{left:100%}.btn-primary:hover{transform:translateY(-2px)}.btn-danger{background:var(--accent-danger);color:#fff}.btn-danger:hover{background:#ea580c}.btn-success{background:var(--accent-success);color:#fff}.btn-success:hover{background:#059669}.btn-secondary{background:var(--accent-secondary);color:#fff}.btn-secondary:hover{background:var(--accent-primary)}.btn-sm{padding:4px 8px}table{width:100%;border-collapse:collapse;margin-top:16px;border-radius:12px;overflow:hidden}table th,table td{padding:16px;text-align:left;border-bottom:1px solid var(--border-secondary);color:var(--text-primary)}table th{background:var(--bg-table-header);font-weight:700;color:var(--text-secondary);font-family:Fredoka,sans-serif;font-size:14px}.form-group{margin-bottom:20px}.form-group label{display:block;margin-bottom:8px;color:var(--text-primary);font-size:14px;font-weight:600;font-family:Nunito,sans-serif}.form-group input,.form-group select,.form-group textarea{width:100%;padding:12px 16px;border:2px solid var(--border-primary);border-radius:12px;font-size:14px;font-family:Nunito,sans-serif;background:var(--bg-secondary);color:var(--text-primary);transition:all .3s ease-out}.form-group input:focus,.form-group select:focus,.form-group textarea:focus{outline:none;border-color:var(--accent-primary);box-shadow:0 0 0 3px var(--shadow-secondary);background:var(--bg-secondary)}.form-group input:disabled,.form-group select:disabled,.form-group textarea:disabled{background:var(--bg-input-disabled);cursor:not-allowed;color:var(--text-input-disabled);opacity:.7}.form-group label small{font-size:.8em;color:var(--text-light)}@keyframes modalFadeIn{0%{opacity:0}to{opacity:1}}.modal{background:var(--bg-secondary);border-radius:24px;padding:32px 28px 32px 32px;min-width:500px;width:800px;max-width:90%;max-height:90vh;box-shadow:0 8px 24px #0003;border:1px solid var(--border-secondary);animation:modalSlideIn .4s ease-out;overflow:hidden;display:flex;flex-direction:column}.modal-container{overflow-y:auto;overflow-x:hidden;margin-right:-8px;padding-right:8px;scrollbar-gutter:stable;scrollbar-width:thin;scrollbar-color:var(--border-secondary) transparent}.modal-container::-webkit-scrollbar{width:8px}.modal-container::-webkit-scrollbar-track{background:transparent;border-radius:4px;margin:4px}.modal-container::-webkit-scrollbar-thumb{background:var(--border-secondary);border-radius:4px;border:2px solid transparent}.modal-container::-webkit-scrollbar-thumb:hover{background:var(--text-muted)}.modal-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:#0009;display:flex;justify-content:center;align-items:center;z-index:1000;animation:modalFadeIn .3s ease-out}.modal-close-btn{position:absolute;top:20px;right:20px;width:48px;height:48px;border:none;background:var(--accent-light);color:var(--text-primary);font-size:32px;line-height:1;cursor:pointer;border-radius:50%;transition:all .2s ease;display:flex;align-items:center;justify-content:center;padding:0;border:1px solid rgba(255,255,255,.3);z-index:1001}.modal-close-btn:hover{background:var(--accent-danger);color:#fff;transform:scale(1.05)}.modal-close-btn:active{transform:scale(.95)}@keyframes modalSlideIn{0%{opacity:0;transform:translateY(-20px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}.modal-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px;position:relative}.modal-header h2{font-size:20px;color:var(--text-primary);flex:1}.modal-footer{display:flex;justify-content:flex-end;gap:10px;margin-top:20px}.action-buttons{display:flex;gap:8px}.badge{display:inline-block;padding:6px 12px;border-radius:20px;font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;white-space:nowrap}.badge-success{background:var(--accent-success);color:#fff}.badge-warning{background:var(--accent-warning);color:#fff}.badge-danger{background:var(--accent-danger);color:#fff}.badge-claude-code{background:#ce653c;color:#fff}.badge-codex{background:#1f2937;color:#fff}.empty-state{text-align:center;padding:60px 20px;color:var(--text-muted);font-family:Nunito,sans-serif}.empty-state p{margin-bottom:20px;font-size:16px;font-weight:500}.pagination{display:flex;justify-content:space-between;align-items:center;margin-top:20px;padding:16px;background:var(--bg-secondary);border-radius:12px;border:1px solid var(--border-primary);gap:20px;flex-wrap:wrap}.pagination-info{color:var(--text-muted);font-size:14px;font-weight:500}.pagination-controls{display:flex;align-items:center;gap:10px}.pagination-btn{padding:6px 14px;border:1px solid var(--border-primary);background:var(--bg-card);color:var(--text-primary);border-radius:8px;cursor:pointer;font-size:14px;font-weight:500;transition:all .2s ease}.pagination-btn:hover:not(:disabled){background:var(--accent-primary);color:#fff;border-color:var(--accent-primary)}.pagination-btn:disabled{opacity:.4;cursor:not-allowed;background:var(--bg-secondary)}.pagination-size{display:flex;align-items:center;gap:8px;color:var(--text-primary);font-size:14px;font-weight:500}.pagination-select{padding:6px 10px;border:1px solid var(--border-primary);background:var(--bg-card);color:var(--text-primary);border-radius:8px;cursor:pointer;font-size:14px;outline:none;transition:all .2s ease}.pagination-select:hover{border-color:var(--accent-primary)}.pagination-select:focus{border-color:var(--accent-primary);box-shadow:0 0 0 2px #3498db1a}.toolbar{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px}.theme-toggle{position:absolute;bottom:20px;left:20px;right:20px;display:flex;align-items:center;justify-content:space-between;gap:12px}.github-link{background:none;border:none;color:var(--text-sidebar);cursor:pointer;padding:8px;border-radius:8px;transition:all .3s ease-out;display:flex;align-items:center;justify-content:center;opacity:.8;margin-left:auto}.github-link:hover{background:#ffffff26;opacity:1}.theme-toggle button{background:none;border:none;color:var(--text-sidebar);cursor:pointer;padding:8px;border-radius:8px;transition:all .3s ease-out;display:flex;align-items:center;justify-content:center}.version-info{font-size:12px;color:var(--text-sidebar);opacity:.7;font-family:Monaco,Menlo,monospace;font-weight:500;-webkit-user-select:none;user-select:none;transition:opacity .3s ease}.version-info:hover{opacity:1}.theme-toggle button:hover{background:#ffffff26}.theme-toggle button.active{background:linear-gradient(135deg,var(--accent-primary),var(--accent-secondary));color:#fff;animation:pulse 2s ease-in-out infinite}@keyframes pulse{0%,to{transform:scale(1)}50%{transform:scale(1.05)}}.update-notification{position:absolute;bottom:48px;left:20px;right:20px;background:#10b98126;border:1px solid rgba(16,185,129,.4);border-radius:12px;padding:8px;animation:slideUp .3s ease-out;box-shadow:0 2px 8px #0000001a;margin-bottom:12px}@keyframes slideUp{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.update-notification-content{display:flex;align-items:center;gap:10px}.update-icon{font-size:18px;animation:bounce 1s ease-in-out infinite}@keyframes bounce{0%,to{transform:translateY(0)}50%{transform:translateY(-3px)}}.update-text{flex:1}.update-title{font-size:13px;font-weight:600;color:var(--text-sidebar);margin-bottom:2px}.update-versions{font-size:11px;color:#ffffffb3;font-family:Monaco,Menlo,monospace}.update-message{font-size:10px;color:var(--text-sidebar);margin-bottom:2px}.update-message code{background:#ffffff1a;padding:2px 4px;border-radius:4px;font-family:Monaco,Menlo,monospace;margin-top:2px;display:inline-block}.update-link{display:block;text-align:center;padding:6px 12px;background:linear-gradient(135deg,var(--accent-success),#059669);color:#fff;text-decoration:none;border-radius:8px;font-size:12px;font-weight:600;transition:all .3s ease-out}.update-link:hover{transform:translateY(-1px)}@media (prefers-reduced-motion: reduce){.nav-menu a,.card,.btn,.form-group input,.form-group select,.form-group textarea,.modal-overlay,.modal,table tr{transition:none;animation:none}.nav-menu a:hover,.card:hover,.btn:hover,table tr:hover{transform:none}.btn:before{display:none}}.markdown-content{line-height:1.7;color:var(--text-primary);max-width:100%;overflow-x:auto}.markdown-content h1{font-size:2em;font-weight:700;margin-top:0;margin-bottom:.8em;color:var(--text-primary);border-bottom:2px solid var(--border-color);padding-bottom:.3em}.markdown-content h2{font-size:1.6em;font-weight:600;margin-top:1.5em;margin-bottom:.6em;color:var(--text-primary);border-bottom:1px solid var(--border-color);padding-bottom:.25em}.markdown-content h3{font-size:1.3em;font-weight:600;margin-top:1.2em;margin-bottom:.5em;color:var(--text-primary)}.markdown-content h4{font-size:1.1em;font-weight:600;margin-top:1em;margin-bottom:.4em;color:var(--text-primary)}.markdown-content p{margin-bottom:1em;line-height:1.8}.markdown-content ul,.markdown-content ol{margin-bottom:1em;padding-left:2em}.markdown-content li{margin-bottom:.5em;line-height:1.7}.markdown-content code{background:var(--bg-secondary);padding:.2em .4em;border-radius:4px;font-size:.9em;font-family:Monaco,Menlo,Ubuntu Mono,Consolas,monospace;color:var(--accent-secondary);border:1px solid var(--border-color)}.markdown-content pre{background:var(--bg-secondary);padding:1em;border-radius:8px;overflow-x:auto;margin-bottom:1em;border:1px solid var(--border-color)}.markdown-content pre code{background:none;padding:0;border:none;color:var(--text-primary);font-size:.95em}.markdown-content blockquote{border-left:4px solid var(--accent-primary);padding-left:1em;margin-left:0;margin-bottom:1em;color:var(--text-secondary);font-style:italic}.markdown-content a{color:var(--accent-primary);text-decoration:none;border-bottom:1px solid var(--accent-secondary);transition:all .2s ease}.markdown-content a:hover{color:var(--accent-secondary)}.markdown-content table{width:100%;border-collapse:collapse;margin-bottom:1em}.markdown-content table th,.markdown-content table td{padding:.75em;text-align:left;border:1px solid var(--border-color)}.markdown-content table th{background:var(--bg-secondary);font-weight:600}.markdown-content hr{border:none;border-top:2px solid var(--border-color);margin:2em 0}.markdown-content strong{font-weight:600;color:var(--text-primary)}.markdown-content em{font-style:italic}.markdown-content img{max-width:100%;height:auto;border-radius:8px;margin:1em 0}.config-status-indicator{display:inline-block}.status-badge{display:inline-block;padding:4px 10px;border-radius:12px;font-size:11px;font-weight:600}.status-active{background:linear-gradient(135deg,#4caf50,#45a049);color:#fff}.status-backup{background:linear-gradient(135deg,#ff9800,#f57c00);color:#fff}.status-inactive{background:linear-gradient(135deg,#9e9e9e,#757575);color:#fff}.skills-header-row{display:flex;justify-content:space-between;align-items:flex-start;gap:16px;flex-wrap:wrap}.skills-header-actions{margin-top:8px}.skills-discover-btn{padding:18px 36px;font-size:16px;font-weight:700;border-radius:14px;box-shadow:0 4px 12px #00000026;position:relative}.skills-discover-btn:after{content:"";position:absolute;top:-6px;right:-6px;bottom:-6px;left:-6px;border-radius:18px;border:2px solid rgba(16,185,129,.35);opacity:.6}.skills-section-header{display:flex;flex-direction:column;gap:6px;margin-bottom:20px}.skills-section-header h2{margin:0;font-size:22px;color:var(--text-primary)}.skills-section-header span{color:var(--text-muted);font-size:14px}.skills-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(360px,1fr));gap:16px}.skill-card{display:flex;flex-direction:column;gap:16px;min-height:180px}.skill-title{font-size:18px;font-weight:700;color:var(--text-primary);margin-bottom:8px}.skill-description{color:var(--text-muted);font-size:14px;line-height:1.6;flex:1}.skill-tags{display:flex;flex-wrap:wrap;gap:8px}.skills-discover{display:flex;flex-direction:column;gap:20px}.skills-search-card{display:flex;flex-direction:column;gap:16px}.skills-search-header h3{margin:0 0 6px;font-size:18px;color:var(--text-primary)}.skills-search-header p{margin:0;color:var(--text-muted);font-size:14px}.skills-search-input{width:100%;padding:12px 14px;border-radius:12px;border:1px solid var(--border-primary);background:var(--bg-secondary);color:var(--text-primary);resize:vertical;min-height:120px;font-size:14px;line-height:1.6}.skills-search-actions{display:flex;justify-content:flex-end}.skills-results{display:flex;flex-direction:column;gap:16px}.skills-result-actions{display:flex;justify-content:flex-end;gap:8px}.badge-secondary{background:#0f513226;color:var(--text-primary)}.switch{position:relative;width:44px;height:24px;border-radius:12px;border:none;cursor:pointer;background-color:#4b5563;transition:background-color .2s}.switch.active{background-color:var(--primary-color)}.switch:disabled{cursor:not-allowed;opacity:.6}.switch:focus{outline:none;box-shadow:0 0 0 2px var(--primary-color)}.switch::-moz-focus-inner{border:0}*{margin:0;padding:0;box-sizing:border-box}:root{--primary-color: #14532D;--error-color: #DC2626;--bg-primary: linear-gradient(135deg, #F7FEE7 0%, #F0FDF4 100%);--bg-secondary: rgba(255, 255, 255, .95);--bg-sidebar: linear-gradient(135deg, #0F5132 0%, #065F46 100%);--bg-card: rgba(255, 255, 255, .98);--bg-code: #f4fff7;--bg-table-header: linear-gradient(135deg, #A7F3D0 0%, #6EE7B7 100%);--text-primary: #14532D;--text-secondary: #064E3B;--text-muted: #065F46;--text-sidebar: #FFFFFF;--text-on-dark: #FFFFFF;--border-primary: rgba(15, 81, 50, .2);--border-secondary: rgba(6, 95, 70, .2);--accent-primary: #0F5132;--accent-secondary: #047857;--accent-light: #a1e9c7;--accent-success: #047857;--accent-warning: #D97706;--accent-danger: #DC2626;--shadow-primary: rgba(15, 81, 50, .3);--shadow-secondary: rgba(15, 81, 50, .15);--bg-route-item: rgba(248, 249, 250, .9);--bg-route-item-hover: rgba(230, 244, 234, .95);--bg-route-item-selected: rgba(161, 233, 199, .25);--text-route-muted: #6c757d;--text-info: #2faeee;--text-light: #018038;--bg-info-box: #f8f9fa;--border-info-box: #e0e0e0;--text-info-box: #666;--bg-info-blue: #e3f2fd;--border-info-blue: #2196f3;--bg-info-green: #f1f8e9;--border-info-green: #8bc34a;--bg-info-orange: #fff3e0;--border-info-orange: #ff9800;--bg-info-yellow: #fff8e1;--border-info-yellow: #ffc107;--bg-assembled-text: #f8f9fa;--bg-thinking-box: #fff9e6;--border-thinking-box: #e0e0e0;--text-thinking-title: #f39c12;--bg-thinking-content: #fff;--border-thinking-content: #f0e6d3;--text-thinking-content: #555;--text-reply-title: #333;--bg-reply-content: #fff;--border-reply-content: #ddd;--text-reply-content: #333;--bg-input-disabled: #e5e7eb;--text-input-disabled: #9ca3af}[data-theme=dark]{--bg-primary: linear-gradient(135deg, #0A1A0F 0%, #0F2415 100%);--bg-secondary: rgba(15, 36, 21, .9);--bg-sidebar: linear-gradient(135deg, #0F5132 0%, #065F46 100%);--bg-card: rgba(25, 51, 31, .95);--bg-code: #0f172a;--bg-table-header: linear-gradient(135deg, #0F5132 0%, #047857 100%);--text-primary: #ECFEF5;--text-secondary: #A7F3D0;--text-muted: #6EE7B7;--text-sidebar: #FFFFFF;--text-on-dark: #ECFEF5;--border-primary: rgba(15, 81, 50, .5);--border-secondary: rgba(6, 95, 70, .5);--accent-primary: #0F5132;--accent-secondary: #047857;--accent-light: #002d18;--accent-success: #10B981;--accent-warning: #F59E0B;--accent-danger: #EF4444;--shadow-primary: rgba(15, 81, 50, .4);--shadow-secondary: rgba(6, 95, 70, .3);--bg-route-item: rgba(20, 46, 28, .7);--bg-route-item-hover: rgba(30, 60, 38, .85);--bg-route-item-selected: rgba(16, 185, 129, .15);--text-route-muted: #A7F3D0;--text-light: #999999;--bg-info-box: rgba(20, 46, 28, .6);--border-info-box: rgba(161, 233, 199, .2);--text-info-box: #A7F3D0;--bg-info-blue: rgba(13, 71, 161, .25);--border-info-blue: #1976d2;--bg-info-green: rgba(27, 94, 32, .25);--border-info-green: #689f38;--bg-info-orange: rgba(230, 81, 0, .2);--border-info-orange: #f57c00;--bg-info-yellow: rgba(255, 193, 7, .15);--border-info-yellow: #ffb300;--bg-assembled-text: rgba(15, 23, 42, .5);--bg-thinking-box: rgba(230, 81, 0, .15);--border-thinking-box: rgba(245, 158, 11, .3);--text-thinking-title: #fbbf24;--bg-thinking-content: rgba(15, 23, 42, .4);--border-thinking-content: rgba(245, 158, 11, .2);--text-thinking-content: #d1d5db;--text-reply-title: #e5e7eb;--bg-reply-content: rgba(15, 23, 42, .4);--border-reply-content: rgba(161, 233, 199, .2);--text-reply-content: #e5e7eb;--bg-input-disabled: #2d3748;--text-input-disabled: #718096}body{font-family:Nunito,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background:var(--bg-primary);color:var(--text-primary);transition:all .3s ease;min-height:100vh}code{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}#root{width:100vw;height:100vh;overflow:hidden}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-track{background:var(--bg-secondary);border-radius:6px}::-webkit-scrollbar-thumb{background:var(--accent-secondary);border-radius:6px;border:2px solid var(--bg-secondary)}::-webkit-scrollbar-thumb:hover{background:var(--accent-primary)}::-webkit-scrollbar-corner{background:var(--bg-secondary)}*{scrollbar-width:thin;scrollbar-color:var(--accent-primary) var(--bg-secondary)}::-webkit-scrollbar-button{display:none}html{scroll-behavior:smooth}.datetime-picker-input{cursor:pointer}.datetime-picker-input::-webkit-calendar-picker-indicator{cursor:pointer;opacity:1;filter:brightness(0);padding:2px 4px}.datetime-picker-input::-webkit-calendar-picker-indicator:hover{filter:brightness(.3)}.datetime-picker-input::-moz-calendar-picker-indicator{cursor:pointer;opacity:1;filter:brightness(0);padding:2px 4px}.datetime-picker-input::-moz-calendar-picker-indicator:hover{filter:brightness(.3)}[data-theme=dark] .datetime-picker-input::-webkit-calendar-picker-indicator{filter:brightness(0) invert(1)}[data-theme=dark] .datetime-picker-input::-webkit-calendar-picker-indicator:hover{filter:brightness(.2) invert(1)}[data-theme=dark] .datetime-picker-input::-moz-calendar-picker-indicator{filter:brightness(0) invert(1)}[data-theme=dark] .datetime-picker-input::-moz-calendar-picker-indicator:hover{filter:brightness(.2) invert(1)}