File size: 6,350 Bytes
1a2b0fa
a3b49e8
684c8a3
 
4abc17c
1a2b0fa
a3b49e8
1a2b0fa
 
a3b49e8
1a2b0fa
 
 
 
 
 
 
 
 
 
 
 
 
 
a3b49e8
 
 
1a2b0fa
a3b49e8
 
 
1a2b0fa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a3b49e8
1a2b0fa
 
 
a3b49e8
1a2b0fa
 
 
 
 
 
 
 
684c8a3
1a2b0fa
 
 
 
 
684c8a3
 
1a2b0fa
 
 
a3b49e8
 
1a2b0fa
 
 
 
 
 
 
a3b49e8
 
 
1a2b0fa
 
a3b49e8
1a2b0fa
 
 
 
 
 
 
4abc17c
 
 
684c8a3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4abc17c
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# ui/components/modals.py
import gradio as gr
from config import MODEL_OPTIONS, DEFAULT_PROVIDER, DEFAULT_MODEL, GROQ_FAST_MODEL_OPTIONS
from config import BASE_DIR

def create_validated_input(label, placeholder, type="password"):
    """
    Helper: 創建自動驗證的輸入框組件 (無按鈕版)
    回傳: (textbox, status_markdown)
    """
    with gr.Group():
        key_input = gr.Textbox(
            label=label,
            placeholder=placeholder,
            type=type,
            elem_classes="modern-input"
        )
        # 狀態訊息預設為空,驗證後顯示
        status_output = gr.Markdown(value="", elem_classes="api-status-msg")

    return key_input, status_output


def create_settings_modal():
    with gr.Group(visible=False, elem_classes="modal-overlay", elem_id="settings-modal") as modal:
        with gr.Group(elem_classes="modal-box"):
            with gr.Row(elem_classes="modal-header"):
                gr.Markdown("### ⚙️ Hybrid System Configuration", elem_classes="modal-title")

            with gr.Column(elem_classes="modal-content"):
                with gr.Tabs():
                    # === 1. Services ===
                    with gr.TabItem("🌍 Services"):
                        gr.Markdown("External services for maps and weather.", elem_classes="tab-desc")

                        # 🔥 使用新 Helper (沒有按鈕了)
                        g_key, g_stat = create_validated_input("Google Maps Key", "AIza...")
                        w_key, w_stat = create_validated_input("OpenWeather Key", "Enter key...")

                    # === 2. Primary Brain ===
                    with gr.TabItem("🧠 Primary Brain"):
                        gr.Markdown("Select the main intelligence.", elem_classes="tab-desc")

                        # 這裡佈局稍微調整,把 Key 單獨放一行,比較乾淨
                        llm_provider = gr.Dropdown(
                            choices=list(MODEL_OPTIONS.keys()),
                            value=DEFAULT_PROVIDER,
                            label="Main Provider",
                            interactive=True,
                            elem_classes="modern-dropdown"
                        )

                        # 主模型 Key
                        main_key, main_stat = create_validated_input("Main Model API Key", "sk-...")

                        model_sel = gr.Dropdown(
                            choices=MODEL_OPTIONS[DEFAULT_PROVIDER],
                            value=DEFAULT_MODEL,
                            label="Main Model",
                            interactive=True,
                            elem_classes="modern-dropdown"
                        )

                    # === 3. Acceleration ===
                    with gr.TabItem("⚡ Acceleration"):
                        gr.Markdown("Configure Groq for speed.", elem_classes="tab-desc")

                        fast_mode_chk = gr.Checkbox(
                            label="Enable Fast Sub-Mode",
                            value=False,
                            elem_classes="modern-checkbox"
                        )

                        groq_model_sel = gr.Dropdown(
                            choices=GROQ_FAST_MODEL_OPTIONS,
                            value=GROQ_FAST_MODEL_OPTIONS[0][1],
                            label="Model",
                            elem_classes="modern-dropdown",
                            visible = False  # <--- 預設隱藏
                        )

                        # Groq Key
                        groq_key, groq_stat = create_validated_input("Groq API Key", "gsk_...")

                        # 手動設定初始狀態為隱藏 (Gradio 小技巧: 定義後再 update)
                        groq_key.visible = False

                # 全局狀態
                set_stat = gr.Markdown(value="", visible=True)

            with gr.Row(elem_classes="modal-footer"):
                close_btn = gr.Button("Cancel", variant="secondary", elem_classes="btn-cancel")
                save_btn = gr.Button("💾 Save", variant="primary", elem_id="btn-save-config")

    # 🔥 回傳清單變短了 (少了 4 個按鈕)
    return (modal,
            g_key, g_stat,
            w_key, w_stat,
            llm_provider, main_key, main_stat, model_sel,
            fast_mode_chk, groq_model_sel, groq_key, groq_stat,
            close_btn, save_btn, set_stat)


def create_doc_modal():
    """
    創建文檔模態框
    功能:自動讀取 README.md 並【過濾掉】YAML Front Matter
    """

    readme_path = BASE_DIR / "README.md"
    doc_content = ""

    try:
        if readme_path.exists():
            with open(readme_path, "r", encoding="utf-8") as f:
                raw_content = f.read()

            # 🔥🔥🔥 [核心修正] 過濾 YAML Front Matter 🔥🔥🔥
            # 邏輯:YAML 區塊通常夾在兩個 "---" 之間,且位於檔案最上方
            if raw_content.startswith("---"):
                # 使用 split 切割,限制切割次數為 2
                # 結果會是 ['', 'yaml內容', '剩下的Markdown內容']
                parts = raw_content.split("---", 2)
                if len(parts) >= 3:
                    doc_content = parts[2].strip()  # 取出真正的內容並去除首尾空白
                else:
                    doc_content = raw_content  # 格式不對,就顯示原文
            else:
                doc_content = raw_content

        else:
            doc_content = "## ⚠️ Documentation Not Found"

    except Exception as e:
        doc_content = f"## ❌ Error Loading Documentation\n\n{str(e)}"

    # ... (後面的 UI 構建代碼保持不變) ...
    with gr.Group(visible=False, elem_classes="modal-overlay", elem_id="doc-modal") as doc_modal:
        with gr.Group(elem_classes="modal-box"):
            with gr.Row(elem_classes="modal-header"):
                gr.Markdown("### 📖 Documentation", elem_classes="modal-title")

            with gr.Column(elem_classes="modal-content"):
                gr.Markdown(doc_content)  # 這裡現在只會顯示乾淨的 Markdown

            with gr.Row(elem_classes="modal-footer"):
                close_doc_btn = gr.Button("Close", variant="secondary", elem_classes="btn-cancel")

    return doc_modal, close_doc_btn