@pheem49/mint 1.5.5 → 1.6.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.
Files changed (222) hide show
  1. package/.codex +0 -0
  2. package/.github/FUNDING.yml +2 -0
  3. package/.github/workflows/ci.yml +45 -0
  4. package/.github/workflows/release.yml +79 -0
  5. package/Cargo.lock +5792 -0
  6. package/Cargo.toml +32 -0
  7. package/README.md +387 -353
  8. package/assets/icon.png +0 -0
  9. package/bin/mint +0 -0
  10. package/crates/mint-cli/Cargo.toml +23 -0
  11. package/crates/mint-cli/src/agent.rs +851 -0
  12. package/crates/mint-cli/src/gmail.rs +216 -0
  13. package/crates/mint-cli/src/image.rs +142 -0
  14. package/crates/mint-cli/src/main.rs +2837 -0
  15. package/crates/mint-cli/src/mcp.rs +63 -0
  16. package/crates/mint-cli/src/onboard.rs +1149 -0
  17. package/crates/mint-cli/src/setup.rs +390 -0
  18. package/crates/mint-cli/src/skills.rs +8 -0
  19. package/crates/mint-cli/src/updater.rs +279 -0
  20. package/crates/mint-core/Cargo.toml +22 -0
  21. package/crates/mint-core/src/agent_loop.rs +94 -0
  22. package/crates/mint-core/src/api_server.rs +991 -0
  23. package/crates/mint-core/src/channels.rs +248 -0
  24. package/crates/mint-core/src/chat.rs +895 -0
  25. package/crates/mint-core/src/code_tools.rs +729 -0
  26. package/crates/mint-core/src/config.rs +368 -0
  27. package/crates/mint-core/src/files.rs +159 -0
  28. package/crates/mint-core/src/knowledge.rs +541 -0
  29. package/crates/mint-core/src/lib.rs +84 -0
  30. package/crates/mint-core/src/mcp.rs +273 -0
  31. package/crates/mint-core/src/memory.rs +673 -0
  32. package/crates/mint-core/src/orchestration.rs +2157 -0
  33. package/crates/mint-core/src/pictures.rs +314 -0
  34. package/crates/mint-core/src/plugins.rs +727 -0
  35. package/crates/mint-core/src/safety.rs +416 -0
  36. package/crates/mint-core/src/semantic.rs +254 -0
  37. package/crates/mint-core/src/shell.rs +317 -0
  38. package/crates/mint-core/src/skills.rs +71 -0
  39. package/crates/mint-core/src/symbols.rs +157 -0
  40. package/crates/mint-core/src/tasks.rs +308 -0
  41. package/crates/mint-core/src/tts.rs +92 -0
  42. package/crates/mint-core/src/weather.rs +93 -0
  43. package/crates/mint-core/src/web_search.rs +200 -0
  44. package/crates/mint-core/src/workflows.rs +81 -0
  45. package/crates/mint-core/tests/mcp_stdio.rs +45 -0
  46. package/crates/mint-core/tests/memory_persistence.rs +172 -0
  47. package/crates/mint-core/tests/pictures_storage.rs +14 -0
  48. package/crates/mint-core/tests/task_lifecycle.rs +87 -0
  49. package/package.json +35 -99
  50. package/src/bin/index.js +16 -0
  51. package/src/renderer/index-web.html +17 -0
  52. package/src/renderer/index.html +17 -0
  53. package/src/renderer/public/Live2DCubismCore.js +9 -0
  54. package/src/renderer/public/assets/icon.png +0 -0
  55. package/src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.model3.json +36 -0
  56. package/src/renderer/src/App.tsx +33 -0
  57. package/src/renderer/src/calculator.ts +47 -0
  58. package/src/renderer/src/components/ChatPanel.tsx +1598 -0
  59. package/src/renderer/src/components/DashboardSidebar.tsx +358 -0
  60. package/src/renderer/src/components/Live2DStage.tsx +374 -0
  61. package/src/renderer/src/components/MintDashboard.tsx +950 -0
  62. package/src/renderer/src/components/ModelPanel.tsx +154 -0
  63. package/src/renderer/src/components/PicturesLibrary.tsx +46 -0
  64. package/src/renderer/src/components/ProactiveGlow.tsx +19 -0
  65. package/src/renderer/src/components/ScreenPicker.tsx +579 -0
  66. package/src/renderer/src/components/SettingsWindow.tsx +1467 -0
  67. package/src/renderer/src/components/SpotlightWindow.tsx +280 -0
  68. package/src/renderer/src/components/WidgetWindow.tsx +36 -0
  69. package/src/renderer/src/components/WorkspacePanel.tsx +268 -0
  70. package/src/{UI → renderer/src/css}/settings.css +69 -16
  71. package/src/renderer/src/css/spotlight.css +113 -0
  72. package/src/renderer/src/css/styles.css +3722 -0
  73. package/src/renderer/src/css/widget.css +185 -0
  74. package/src/renderer/src/env.d.ts +116 -0
  75. package/src/renderer/src/index.css +379 -0
  76. package/src/renderer/src/main.tsx +13 -0
  77. package/src/renderer/src/tauri.ts +996 -0
  78. package/src/renderer/src-web/App.tsx +25 -0
  79. package/src/renderer/src-web/calculator.ts +47 -0
  80. package/src/renderer/src-web/components/ChatPanel.tsx +1662 -0
  81. package/src/renderer/src-web/components/DashboardSidebar.tsx +242 -0
  82. package/src/renderer/src-web/components/MintDashboard.tsx +763 -0
  83. package/src/renderer/src-web/components/PicturesLibrary.tsx +73 -0
  84. package/src/renderer/src-web/components/SettingsWindow.tsx +1500 -0
  85. package/src/renderer/src-web/css/settings.css +1100 -0
  86. package/src/{UI → renderer/src-web/css}/spotlight.css +4 -4
  87. package/src/{UI → renderer/src-web/css}/styles.css +1055 -159
  88. package/src/{UI → renderer/src-web/css}/widget.css +2 -2
  89. package/src/renderer/src-web/env.d.ts +107 -0
  90. package/src/renderer/src-web/index.css +379 -0
  91. package/src/renderer/src-web/main.tsx +13 -0
  92. package/src/renderer/src-web/tauri.ts +983 -0
  93. package/tsconfig.json +30 -0
  94. package/vite.config.ts +33 -0
  95. package/vite.config.web.ts +51 -0
  96. package/GUIDE_TH.md +0 -125
  97. package/assets/Agent_Mint.png +0 -0
  98. package/assets/CLI_Screen.png +0 -0
  99. package/assets/Settings.png +0 -0
  100. package/benchmark_ai.js +0 -71
  101. package/install.ps1 +0 -64
  102. package/install.sh +0 -54
  103. package/main.js +0 -139
  104. package/mint-cli-logic.js +0 -3
  105. package/mint-cli.js +0 -410
  106. package/models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.model3.json +0 -47
  107. package/models/Shiroko_Model/Shiroko//342/232/241/351/253/230/344/272/256/342/232/241/344/275/277/347/224/250/346/225/231/347/250/213/344/270/216/346/263/250/346/204/217/344/272/213/351/241/271.txt +0 -23
  108. package/preload-picker.js +0 -11
  109. package/preload-settings.js +0 -11
  110. package/preload.js +0 -41
  111. package/scripts/install_linux_desktop_entry.js +0 -48
  112. package/src/AI_Brain/Gemini_API.js +0 -813
  113. package/src/AI_Brain/agent_orchestrator.js +0 -73
  114. package/src/AI_Brain/autonomous_brain.js +0 -179
  115. package/src/AI_Brain/behavior_memory.js +0 -135
  116. package/src/AI_Brain/headless_agent.js +0 -143
  117. package/src/AI_Brain/knowledge_base.js +0 -349
  118. package/src/AI_Brain/memory_store.js +0 -662
  119. package/src/AI_Brain/proactive_engine.js +0 -172
  120. package/src/AI_Brain/provider_adapter.js +0 -365
  121. package/src/Automation_Layer/browser_automation.js +0 -149
  122. package/src/Automation_Layer/file_operations.js +0 -286
  123. package/src/Automation_Layer/open_app.js +0 -85
  124. package/src/Automation_Layer/open_website.js +0 -38
  125. package/src/CLI/approval_handler.js +0 -47
  126. package/src/CLI/chat_router.js +0 -247
  127. package/src/CLI/chat_ui.js +0 -1159
  128. package/src/CLI/cli_colors.js +0 -115
  129. package/src/CLI/cli_formatters.js +0 -94
  130. package/src/CLI/code_agent.js +0 -1667
  131. package/src/CLI/code_session_memory.js +0 -62
  132. package/src/CLI/gmail_auth.js +0 -210
  133. package/src/CLI/image_input.js +0 -90
  134. package/src/CLI/intent_detectors.js +0 -181
  135. package/src/CLI/interactive_chat.js +0 -658
  136. package/src/CLI/list_features.js +0 -64
  137. package/src/CLI/onboarding.js +0 -416
  138. package/src/CLI/repo_summarizer.js +0 -282
  139. package/src/CLI/semantic_code_search.js +0 -312
  140. package/src/CLI/skill_manager.js +0 -41
  141. package/src/CLI/slash_command_handler.js +0 -418
  142. package/src/CLI/symbol_indexer.js +0 -231
  143. package/src/CLI/updater.js +0 -230
  144. package/src/CLI/workspace_manager.js +0 -90
  145. package/src/Channels/brave_search_bridge.js +0 -35
  146. package/src/Channels/discord_bridge.js +0 -66
  147. package/src/Channels/google_search_bridge.js +0 -38
  148. package/src/Channels/line_bridge.js +0 -60
  149. package/src/Channels/slack_bridge.js +0 -48
  150. package/src/Channels/telegram_bridge.js +0 -41
  151. package/src/Channels/whatsapp_bridge.js +0 -57
  152. package/src/Command_Parser/parser.js +0 -45
  153. package/src/Plugins/dev_tools.js +0 -41
  154. package/src/Plugins/discord.js +0 -20
  155. package/src/Plugins/docker.js +0 -47
  156. package/src/Plugins/gmail.js +0 -251
  157. package/src/Plugins/google_calendar.js +0 -252
  158. package/src/Plugins/mcp_manager.js +0 -95
  159. package/src/Plugins/notion.js +0 -256
  160. package/src/Plugins/obsidian.js +0 -54
  161. package/src/Plugins/plugin_manager.js +0 -81
  162. package/src/Plugins/spotify.js +0 -173
  163. package/src/Plugins/system_metrics.js +0 -31
  164. package/src/Plugins/system_monitor.js +0 -72
  165. package/src/System/action_executor.js +0 -178
  166. package/src/System/bridge_manager.js +0 -76
  167. package/src/System/chat_history_manager.js +0 -83
  168. package/src/System/config_manager.js +0 -194
  169. package/src/System/custom_workflows.js +0 -163
  170. package/src/System/daemon_manager.js +0 -67
  171. package/src/System/google_tts_urls.js +0 -51
  172. package/src/System/granular_automation.js +0 -157
  173. package/src/System/ipc_handlers.js +0 -332
  174. package/src/System/notifications.js +0 -23
  175. package/src/System/optional_require.js +0 -23
  176. package/src/System/picture_store.js +0 -109
  177. package/src/System/proactive_loop.js +0 -153
  178. package/src/System/safety_manager.js +0 -273
  179. package/src/System/sandbox_runner.js +0 -182
  180. package/src/System/screen_capture.js +0 -175
  181. package/src/System/smart_context.js +0 -227
  182. package/src/System/system_automation.js +0 -162
  183. package/src/System/system_events.js +0 -79
  184. package/src/System/system_info.js +0 -125
  185. package/src/System/task_manager.js +0 -222
  186. package/src/System/tool_registry.js +0 -293
  187. package/src/System/window_manager.js +0 -220
  188. package/src/UI/floating.css +0 -80
  189. package/src/UI/floating.html +0 -17
  190. package/src/UI/floating.js +0 -67
  191. package/src/UI/live2d_manager.js +0 -600
  192. package/src/UI/preload-floating.js +0 -7
  193. package/src/UI/preload-spotlight.js +0 -11
  194. package/src/UI/preload-widget.js +0 -5
  195. package/src/UI/proactive-glow.html +0 -42
  196. package/src/UI/renderer.js +0 -2127
  197. package/src/UI/screenPicker.html +0 -214
  198. package/src/UI/screenPicker.js +0 -262
  199. package/src/UI/settings.html +0 -577
  200. package/src/UI/settings.js +0 -770
  201. package/src/UI/spotlight.html +0 -23
  202. package/src/UI/spotlight.js +0 -185
  203. package/src/UI/widget.html +0 -29
  204. package/src/UI/widget.js +0 -10
  205. /package/{models → src/renderer/public/models}/Shiroko_Model/Shiroko/Shiroko_Core/72d86db84cfa9730b894c241fd24c0db.png +0 -0
  206. /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//345/233/264/350/243/231.exp3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/apron.exp3.json} +0 -0
  207. /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//347/214/253/345/222/252/346/273/244/351/225/234.exp3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/catfilter.exp3.json} +0 -0
  208. /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//347/202/271/344/270/200/344/270/213.exp3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/click.exp3.json} +0 -0
  209. /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//345/221/206/347/214/253.exp3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/dazed.exp3.json} +0 -0
  210. /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//345/221/206/347/214/253/347/234/274/347/217/240/346/221/207/346/231/203.exp3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/dazedeyes.exp3.json} +0 -0
  211. /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//347/234/274/351/225/234.exp3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/glasses.exp3.json} +0 -0
  212. /package/{models → src/renderer/public/models}/Shiroko_Model/Shiroko/Shiroko_Core/items_pinned_to_model.json +0 -0
  213. /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//346/213/277/347/254/224.exp3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/pen.exp3.json} +0 -0
  214. /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//346/213/215/347/205/247.exp3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/photo.exp3.json} +0 -0
  215. /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.4096/texture_00.png" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.4096/texture_00.png} +0 -0
  216. /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.4096/texture_01.png" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.4096/texture_01.png} +0 -0
  217. /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.4096/texture_02.png" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.4096/texture_02.png} +0 -0
  218. /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.4096/texture_03.png" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.4096/texture_03.png} +0 -0
  219. /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.cdi3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.cdi3.json} +0 -0
  220. /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.moc3" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.moc3} +0 -0
  221. /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.physics3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.physics3.json} +0 -0
  222. /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.vtube.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.vtube.json} +0 -0
@@ -1,770 +0,0 @@
1
- const DEFAULT_CONFIG = {
2
- theme: 'dark',
3
- accentColor: '#8b5cf6',
4
- systemTextColor: '#f8fafc',
5
- customBgStart: '#0f172a',
6
- customBgEnd: '#1e1b4b',
7
- customPanelBg: '#1e293b',
8
- apiKey: '',
9
- geminiModel: 'gemini-2.5-flash',
10
- language: 'th-TH',
11
- assistantMode: 'chat',
12
- proactiveInterval: 60,
13
- proactiveCooldown: 120,
14
- glassBlur: 'blur(16px)',
15
- fontFamily: "'Outfit', sans-serif",
16
- fontSize: '15px',
17
- aiProvider: 'gemini',
18
- ollamaModel: 'llama3:latest',
19
- enableVoiceReply: true,
20
- enableCustomWorkflows: true,
21
- enableAgentCollaboration: true,
22
- ttsProvider: 'google',
23
- ttsVolume: 1.0,
24
- ttsSpeed: 1.0,
25
- ttsPitch: 1.0,
26
- pluginSpotifyEnabled: true,
27
- pluginCalendarEnabled: false,
28
- pluginGmailEnabled: false,
29
- pluginNotionEnabled: false,
30
- pluginDiscordEnabled: false,
31
- showDesktopWidget: true,
32
- mcpServers: {},
33
- openaiModel: 'gpt-4o',
34
- anthropicModel: 'claude-3-5-sonnet-latest',
35
- hfModel: 'meta-llama/Meta-Llama-3-8B-Instruct',
36
- localApiBaseUrl: '',
37
- localModelName: 'local-model',
38
- ollamaHost: ''
39
- };
40
-
41
- let currentConfig = { ...DEFAULT_CONFIG };
42
-
43
- // Load settings from main process
44
- async function loadSettings() {
45
- const config = await window.settingsApi.getSettings();
46
- currentConfig = { ...DEFAULT_CONFIG, ...config };
47
- applyConfig(currentConfig);
48
- }
49
-
50
- function applyConfig(config) {
51
- // Apply theme
52
- document.documentElement.setAttribute('data-theme', config.theme);
53
-
54
- if (config.theme === 'custom') {
55
- document.getElementById('custom-theme-controls').style.display = 'block';
56
- applyCustomThemeStyles(config);
57
- } else {
58
- document.getElementById('custom-theme-controls').style.display = 'none';
59
- // Reset dynamic style variables if not custom
60
- [
61
- '--bg-gradient',
62
- '--panel-bg',
63
- '--sidebar-bg',
64
- '--chrome-bg',
65
- '--surface-bg',
66
- '--surface-strong',
67
- '--input-bg'
68
- ].forEach(name => document.documentElement.style.removeProperty(name));
69
- }
70
-
71
- // Apply accent color
72
- document.documentElement.style.setProperty('--accent', config.accentColor);
73
- document.documentElement.style.setProperty('--accent-hover', lightenColor(config.accentColor, 20));
74
-
75
- // Apply API key
76
- document.getElementById('api-key-input').value = config.apiKey || '';
77
-
78
- const anthropicInput = document.getElementById('anthropic-api-key-input');
79
- if (anthropicInput) anthropicInput.value = config.anthropicApiKey || '';
80
-
81
- const openaiInput = document.getElementById('openai-api-key-input');
82
- if (openaiInput) openaiInput.value = config.openaiApiKey || '';
83
-
84
- const hfInput = document.getElementById('hf-api-key');
85
- if (hfInput) hfInput.value = config.hfApiKey || '';
86
-
87
- const ollamaHostInput = document.getElementById('ollama-host-input');
88
- if (ollamaHostInput) ollamaHostInput.value = config.ollamaHost || '';
89
-
90
- // Apply Gemini model
91
- applyModelSelection(config.geminiModel);
92
-
93
- // Apply AI Provider
94
- const providerSelect = document.getElementById('ai-provider-select');
95
- if (providerSelect) {
96
- providerSelect.value = config.aiProvider || 'gemini';
97
- toggleProviderOptions(providerSelect.value);
98
- }
99
-
100
- const ollamaInput = document.getElementById('ollama-model-input');
101
- if (ollamaInput) {
102
- ollamaInput.value = config.ollamaModel || 'llama3:latest';
103
- }
104
-
105
- applyModelSelectionGeneric('openai-model-select', 'openai-model-custom-row', 'openai-model-custom', config.openaiModel || 'gpt-4o');
106
- applyModelSelectionGeneric('anthropic-model-select', 'anthropic-model-custom-row', 'anthropic-model-custom', config.anthropicModel || 'claude-3-5-sonnet-latest');
107
-
108
- const hfModelInput = document.getElementById('hf-model-name');
109
- if (hfModelInput) {
110
- hfModelInput.value = config.hfModel || 'meta-llama/Meta-Llama-3-8B-Instruct';
111
- }
112
-
113
- const localApiBaseUrlInput = document.getElementById('local-api-base-url');
114
- if (localApiBaseUrlInput) {
115
- localApiBaseUrlInput.value = config.localApiBaseUrl || '';
116
- }
117
-
118
- const localModelNameInput = document.getElementById('local-model-name');
119
- if (localModelNameInput) {
120
- localModelNameInput.value = config.localModelName || 'local-model';
121
- }
122
-
123
- const voiceReplyToggle = document.getElementById('enable-voice-reply');
124
- if (voiceReplyToggle) {
125
- voiceReplyToggle.checked = config.enableVoiceReply !== false;
126
- }
127
-
128
- const ttsProviderSelect = document.getElementById('tts-provider-select');
129
- if (ttsProviderSelect) ttsProviderSelect.value = config.ttsProvider || 'google';
130
-
131
- const ttsVolume = document.getElementById('tts-volume');
132
- if (ttsVolume) {
133
- ttsVolume.value = config.ttsVolume !== undefined ? config.ttsVolume : 1.0;
134
- document.getElementById('tts-volume-val').textContent = `${Math.round(ttsVolume.value * 100)}%`;
135
- }
136
-
137
- const ttsSpeed = document.getElementById('tts-speed');
138
- if (ttsSpeed) {
139
- ttsSpeed.value = config.ttsSpeed !== undefined ? config.ttsSpeed : 1.0;
140
- document.getElementById('tts-speed-val').textContent = `${parseFloat(ttsSpeed.value).toFixed(1)}x`;
141
- }
142
-
143
- const ttsPitch = document.getElementById('tts-pitch');
144
- if (ttsPitch) {
145
- ttsPitch.value = config.ttsPitch !== undefined ? config.ttsPitch : 1.0;
146
- document.getElementById('tts-pitch-val').textContent = parseFloat(ttsPitch.value).toFixed(1);
147
- }
148
-
149
- const enableWorkflowsToggle = document.getElementById('enable-custom-workflows');
150
- if (enableWorkflowsToggle) {
151
- enableWorkflowsToggle.checked = config.enableCustomWorkflows !== false;
152
- }
153
-
154
- const enableAgentCollaborationToggle = document.getElementById('enable-agent-collaboration');
155
- if (enableAgentCollaborationToggle) {
156
- enableAgentCollaborationToggle.checked = config.enableAgentCollaboration !== false;
157
- }
158
-
159
- // Plugins logic
160
- updatePluginButton('spotify', config.pluginSpotifyEnabled);
161
- updatePluginButton('calendar', config.pluginCalendarEnabled);
162
- updatePluginButton('gmail', config.pluginGmailEnabled);
163
- updatePluginButton('notion', config.pluginNotionEnabled);
164
- updatePluginButton('discord', config.pluginDiscordEnabled);
165
-
166
- // Apply Automation Browser
167
- if (config.automationBrowser) {
168
- document.getElementById('automation-browser-select').value = config.automationBrowser;
169
- }
170
-
171
- const showWidgetToggle = document.getElementById('show-desktop-widget');
172
- if (showWidgetToggle) {
173
- showWidgetToggle.checked = config.showDesktopWidget !== false;
174
- }
175
-
176
- // Apply UI Customizations
177
- document.getElementById('glass-blur-select').value = config.glassBlur || 'blur(16px)';
178
- document.documentElement.style.setProperty('--glass-blur', config.glassBlur || 'blur(16px)');
179
-
180
- document.getElementById('font-family-select').value = config.fontFamily || "'Outfit', sans-serif";
181
- document.body.style.fontFamily = config.fontFamily || "'Outfit', sans-serif";
182
-
183
- document.getElementById('font-size-select').value = config.fontSize || '15px';
184
- document.documentElement.style.fontSize = config.fontSize || '15px';
185
-
186
- // Update active theme card
187
- document.querySelectorAll('.theme-card').forEach(card => {
188
- card.classList.toggle('active', card.dataset.theme === config.theme);
189
- });
190
-
191
- // Update active color dot
192
- document.querySelectorAll('.color-dot').forEach(dot => {
193
- dot.classList.toggle('active', dot.dataset.color === config.accentColor);
194
- });
195
-
196
- // Update color picker
197
- document.getElementById('custom-color').value = config.accentColor;
198
-
199
- const defaultTextColor = config.theme === 'light' ? '#0f172a' : DEFAULT_CONFIG.systemTextColor;
200
- const textColor = (!config.systemTextColor || (config.theme === 'light' && config.systemTextColor === DEFAULT_CONFIG.systemTextColor))
201
- ? defaultTextColor
202
- : config.systemTextColor;
203
- document.getElementById('system-text-color').value = textColor;
204
- document.documentElement.style.setProperty('--text-main', textColor);
205
-
206
- // Update custom color pickers
207
- document.getElementById('custom-bg-start').value = config.customBgStart || '#0f172a';
208
- document.getElementById('custom-bg-end').value = config.customBgEnd || '#1e1b4b';
209
- document.getElementById('custom-panel-bg').value = config.customPanelBg || '#1e293b';
210
- updateCustomPreviewBox(config);
211
-
212
- // Apply proactive settings
213
- const interval = config.proactiveInterval || 60;
214
- const cooldown = config.proactiveCooldown || 120;
215
- document.getElementById('proactive-interval').value = interval;
216
- document.getElementById('proactive-cooldown').value = cooldown;
217
- updateIntervalDisplay(interval);
218
- updateCooldownDisplay(cooldown);
219
-
220
- // MCP Servers
221
- renderMcpServers();
222
- }
223
-
224
- function lightenColor(hex, amount) {
225
- const num = parseInt(hex.replace('#', ''), 16);
226
- const r = Math.min(255, (num >> 16) + amount);
227
- const g = Math.min(255, ((num >> 8) & 0x00FF) + amount);
228
- const b = Math.min(255, (num & 0x0000FF) + amount);
229
- return `#${((r << 16) | (g << 8) | b).toString(16).padStart(6, '0')}`;
230
- }
231
-
232
- function applyModelSelection(model) {
233
- applyModelSelectionGeneric('gemini-model-select', 'gemini-model-custom-row', 'gemini-model-custom', model);
234
- }
235
-
236
- function applyModelSelectionGeneric(selectId, customRowId, customInputId, model) {
237
- const select = document.getElementById(selectId);
238
- const customRow = document.getElementById(customRowId);
239
- const customInput = document.getElementById(customInputId);
240
- if (!select || !customRow || !customInput) return;
241
-
242
- const normalized = (model || '').trim();
243
- const optionValues = Array.from(select.options).map(opt => opt.value);
244
-
245
- if (normalized && optionValues.includes(normalized)) {
246
- select.value = normalized;
247
- customRow.style.display = 'none';
248
- customInput.value = '';
249
- } else {
250
- select.value = 'custom';
251
- customRow.style.display = 'block';
252
- customInput.value = normalized;
253
- }
254
- }
255
-
256
- function getSelectedModel() {
257
- return getSelectedModelGeneric('gemini-model-select', 'gemini-model-custom', DEFAULT_CONFIG.geminiModel);
258
- }
259
-
260
- function getSelectedModelGeneric(selectId, customInputId, defaultModel) {
261
- const select = document.getElementById(selectId);
262
- const customInput = document.getElementById(customInputId);
263
- if (!select || !customInput) return defaultModel;
264
- if (select.value === 'custom') {
265
- const custom = (customInput.value || '').trim();
266
- return custom || defaultModel;
267
- }
268
- return select.value;
269
- }
270
-
271
- // --- Event Listeners ---
272
-
273
- // Close button
274
- // Close button
275
- const closeBtn = document.getElementById('close-btn');
276
- if (closeBtn) {
277
- closeBtn.addEventListener('click', () => {
278
- window.settingsApi.closeSettings();
279
- });
280
- }
281
-
282
- // Toggle API key visibility
283
- const toggleKey = document.getElementById('toggle-key');
284
- if (toggleKey) {
285
- toggleKey.addEventListener('click', () => {
286
- const input = document.getElementById('api-key-input');
287
- input.type = input.type === 'password' ? 'text' : 'password';
288
- });
289
- }
290
-
291
- async function saveApiKeyOnly() {
292
- const input = document.getElementById('api-key-input');
293
- const status = document.getElementById('api-save-status');
294
- const btn = document.getElementById('save-api-key');
295
- const apiKey = input ? input.value.trim() : '';
296
-
297
- try {
298
- const baseConfig = await window.settingsApi.getSettings();
299
- const nextConfig = { ...baseConfig, apiKey };
300
- await window.settingsApi.saveSettings(nextConfig);
301
- currentConfig.apiKey = apiKey;
302
-
303
- if (btn) btn.textContent = 'Saved!';
304
- if (status) status.textContent = 'API key saved';
305
- setTimeout(() => {
306
- if (btn) btn.textContent = 'Save API Key';
307
- if (status) status.textContent = '';
308
- }, 1500);
309
- } catch (err) {
310
- console.error('Failed to save API key:', err);
311
- if (status) status.textContent = 'Save failed';
312
- setTimeout(() => { if (status) status.textContent = ''; }, 1500);
313
- }
314
- }
315
-
316
- const saveApiKey = document.getElementById('save-api-key');
317
- if (saveApiKey) saveApiKey.addEventListener('click', saveApiKeyOnly);
318
-
319
- const apiKeyInput = document.getElementById('api-key-input');
320
- if (apiKeyInput) {
321
- apiKeyInput.addEventListener('keydown', (e) => {
322
- if (e.key === 'Enter') {
323
- e.preventDefault();
324
- saveApiKeyOnly();
325
- }
326
- });
327
- }
328
-
329
- // Gemini model select
330
- document.getElementById('gemini-model-select').addEventListener('change', (e) => {
331
- const customRow = document.getElementById('gemini-model-custom-row');
332
- if (e.target.value === 'custom') {
333
- customRow.style.display = 'block';
334
- currentConfig.geminiModel = (document.getElementById('gemini-model-custom').value || '').trim();
335
- } else {
336
- customRow.style.display = 'none';
337
- currentConfig.geminiModel = e.target.value;
338
- }
339
- });
340
-
341
- document.getElementById('gemini-model-custom').addEventListener('input', (e) => {
342
- currentConfig.geminiModel = e.target.value.trim();
343
- });
344
-
345
- // OpenAI model select
346
- document.getElementById('openai-model-select').addEventListener('change', (e) => {
347
- const customRow = document.getElementById('openai-model-custom-row');
348
- if (e.target.value === 'custom') {
349
- customRow.style.display = 'block';
350
- currentConfig.openaiModel = (document.getElementById('openai-model-custom').value || '').trim();
351
- } else {
352
- customRow.style.display = 'none';
353
- currentConfig.openaiModel = e.target.value;
354
- }
355
- });
356
-
357
- document.getElementById('openai-model-custom').addEventListener('input', (e) => {
358
- currentConfig.openaiModel = e.target.value.trim();
359
- });
360
-
361
- // Anthropic model select
362
- document.getElementById('anthropic-model-select').addEventListener('change', (e) => {
363
- const customRow = document.getElementById('anthropic-model-custom-row');
364
- if (e.target.value === 'custom') {
365
- customRow.style.display = 'block';
366
- currentConfig.anthropicModel = (document.getElementById('anthropic-model-custom').value || '').trim();
367
- } else {
368
- customRow.style.display = 'none';
369
- currentConfig.anthropicModel = e.target.value;
370
- }
371
- });
372
-
373
- document.getElementById('anthropic-model-custom').addEventListener('input', (e) => {
374
- currentConfig.anthropicModel = e.target.value.trim();
375
- });
376
-
377
- // AI Provider toggle (No-op since all sections stay visible)
378
- function toggleProviderOptions(provider) {
379
- // No-op
380
- }
381
-
382
- document.getElementById('ai-provider-select').addEventListener('change', (e) => {
383
- currentConfig.aiProvider = e.target.value;
384
- });
385
-
386
- document.getElementById('ollama-model-input').addEventListener('input', (e) => {
387
- currentConfig.ollamaModel = e.target.value.trim();
388
- });
389
-
390
- // AI Studio link
391
- const aiStudioLink = document.getElementById('ai-studio-link');
392
- if (aiStudioLink) {
393
- aiStudioLink.addEventListener('click', () => {
394
- window.settingsApi.openExternal('https://aistudio.google.com/');
395
- });
396
- }
397
-
398
- // Theme cards
399
- document.querySelectorAll('.theme-card').forEach(card => {
400
- card.addEventListener('click', () => {
401
- currentConfig.theme = card.dataset.theme;
402
- applyConfig(currentConfig);
403
- });
404
- });
405
-
406
- // Color presets
407
- document.querySelectorAll('.color-dot').forEach(dot => {
408
- dot.addEventListener('click', () => {
409
- currentConfig.accentColor = dot.dataset.color;
410
- applyConfig(currentConfig);
411
- document.getElementById('custom-color').value = dot.dataset.color;
412
- });
413
- });
414
-
415
- // Custom color picker
416
- document.getElementById('custom-color').addEventListener('input', (e) => {
417
- currentConfig.accentColor = e.target.value;
418
- document.documentElement.style.setProperty('--accent', e.target.value);
419
- document.documentElement.style.setProperty('--accent-hover', lightenColor(e.target.value, 20));
420
- // Deselect presets
421
- document.querySelectorAll('.color-dot').forEach(dot => dot.classList.remove('active'));
422
- });
423
-
424
- // System text color picker
425
- document.getElementById('system-text-color').addEventListener('input', (e) => {
426
- currentConfig.systemTextColor = e.target.value;
427
- document.documentElement.style.setProperty('--text-main', e.target.value);
428
- });
429
-
430
- // Custom Theme color pickers
431
- function applyCustomThemeStyles(cfg) {
432
- const gradient = `linear-gradient(135deg, ${cfg.customBgStart} 0%, ${cfg.customBgEnd} 100%)`;
433
- document.documentElement.style.setProperty('--bg-gradient', gradient);
434
-
435
- // Convert hex to rgba for panel bg to keep transparency
436
- const panelRgb = hexToRgb(cfg.customPanelBg);
437
- document.documentElement.style.setProperty('--panel-bg', `rgba(${panelRgb.r}, ${panelRgb.g}, ${panelRgb.b}, 0.75)`);
438
- document.documentElement.style.setProperty('--sidebar-bg', `rgba(${panelRgb.r}, ${panelRgb.g}, ${panelRgb.b}, 0.82)`);
439
- document.documentElement.style.setProperty('--chrome-bg', `rgba(${panelRgb.r}, ${panelRgb.g}, ${panelRgb.b}, 0.78)`);
440
- document.documentElement.style.setProperty('--surface-bg', `rgba(${panelRgb.r}, ${panelRgb.g}, ${panelRgb.b}, 0.42)`);
441
- document.documentElement.style.setProperty('--surface-strong', `rgba(${panelRgb.r}, ${panelRgb.g}, ${panelRgb.b}, 0.62)`);
442
- document.documentElement.style.setProperty('--input-bg', `rgba(${panelRgb.r}, ${panelRgb.g}, ${panelRgb.b}, 0.58)`);
443
- updateCustomPreviewBox(cfg);
444
- }
445
-
446
- function updateCustomPreviewBox(cfg) {
447
- const box = document.getElementById('custom-theme-preview-box');
448
- if (box) {
449
- box.style.background = `linear-gradient(135deg, ${cfg.customBgStart} 0%, ${cfg.customBgEnd} 100%)`;
450
- }
451
- }
452
-
453
- function hexToRgb(hex) {
454
- const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
455
- return result ? {
456
- r: parseInt(result[1], 16),
457
- g: parseInt(result[2], 16),
458
- b: parseInt(result[3], 16)
459
- } : { r: 30, g: 41, b: 59 };
460
- }
461
-
462
- document.getElementById('custom-bg-start').addEventListener('input', (e) => {
463
- currentConfig.customBgStart = e.target.value;
464
- if (currentConfig.theme === 'custom') applyCustomThemeStyles(currentConfig);
465
- });
466
- document.getElementById('custom-bg-end').addEventListener('input', (e) => {
467
- currentConfig.customBgEnd = e.target.value;
468
- if (currentConfig.theme === 'custom') applyCustomThemeStyles(currentConfig);
469
- });
470
- document.getElementById('custom-panel-bg').addEventListener('input', (e) => {
471
- currentConfig.customPanelBg = e.target.value;
472
- if (currentConfig.theme === 'custom') applyCustomThemeStyles(currentConfig);
473
- });
474
-
475
- document.getElementById('glass-blur-select').addEventListener('change', (e) => {
476
- currentConfig.glassBlur = e.target.value;
477
- document.documentElement.style.setProperty('--glass-blur', e.target.value);
478
- });
479
-
480
- document.getElementById('font-family-select').addEventListener('change', (e) => {
481
- currentConfig.fontFamily = e.target.value;
482
- document.body.style.fontFamily = e.target.value;
483
- });
484
-
485
- document.getElementById('font-size-select').addEventListener('change', (e) => {
486
- currentConfig.fontSize = e.target.value;
487
- document.documentElement.style.fontSize = e.target.value;
488
- });
489
-
490
- // Proactive sliders
491
- function formatSeconds(s) {
492
- if (s < 60) return `${s} sec`;
493
- const m = s / 60;
494
- return Number.isInteger(m) ? `${m} min` : `${m.toFixed(1)} min`;
495
- }
496
-
497
- function updateIntervalDisplay(val) {
498
- document.getElementById('proactive-interval-display').textContent = formatSeconds(Number(val));
499
- }
500
-
501
- function updateCooldownDisplay(val) {
502
- document.getElementById('proactive-cooldown-display').textContent = formatSeconds(Number(val));
503
- }
504
-
505
- document.getElementById('proactive-interval').addEventListener('input', (e) => {
506
- updateIntervalDisplay(e.target.value);
507
- });
508
-
509
- document.getElementById('proactive-cooldown').addEventListener('input', (e) => {
510
- updateCooldownDisplay(e.target.value);
511
- });
512
-
513
- // TTS slider UI updates
514
- if (document.getElementById('tts-volume')) {
515
- document.getElementById('tts-volume').addEventListener('input', (e) => {
516
- document.getElementById('tts-volume-val').textContent = `${Math.round(e.target.value * 100)}%`;
517
- });
518
- }
519
- if (document.getElementById('tts-speed')) {
520
- document.getElementById('tts-speed').addEventListener('input', (e) => {
521
- document.getElementById('tts-speed-val').textContent = `${parseFloat(e.target.value).toFixed(1)}x`;
522
- });
523
- }
524
- if (document.getElementById('tts-pitch')) {
525
- document.getElementById('tts-pitch').addEventListener('input', (e) => {
526
- document.getElementById('tts-pitch-val').textContent = parseFloat(e.target.value).toFixed(1);
527
- });
528
- }
529
-
530
- // Save
531
- document.getElementById('save-btn').addEventListener('click', async () => {
532
- currentConfig.apiKey = document.getElementById('api-key-input').value.trim();
533
-
534
- const anthropicInput = document.getElementById('anthropic-api-key-input');
535
- if (anthropicInput) currentConfig.anthropicApiKey = anthropicInput.value.trim();
536
-
537
- const openaiInput = document.getElementById('openai-api-key-input');
538
- if (openaiInput) currentConfig.openaiApiKey = openaiInput.value.trim();
539
-
540
- const hfInput = document.getElementById('hf-api-key');
541
- if (hfInput) currentConfig.hfApiKey = hfInput.value.trim();
542
-
543
- const ollamaHostInput = document.getElementById('ollama-host-input');
544
- if (ollamaHostInput) currentConfig.ollamaHost = ollamaHostInput.value.trim();
545
-
546
- currentConfig.geminiModel = getSelectedModel();
547
- currentConfig.aiProvider = document.getElementById('ai-provider-select').value;
548
- currentConfig.ollamaModel = document.getElementById('ollama-model-input').value.trim();
549
-
550
- currentConfig.openaiModel = getSelectedModelGeneric('openai-model-select', 'openai-model-custom', DEFAULT_CONFIG.openaiModel || 'gpt-4o');
551
- currentConfig.anthropicModel = getSelectedModelGeneric('anthropic-model-select', 'anthropic-model-custom', DEFAULT_CONFIG.anthropicModel || 'claude-3-5-sonnet-latest');
552
-
553
- const hfModelInput = document.getElementById('hf-model-name');
554
- if (hfModelInput) currentConfig.hfModel = hfModelInput.value.trim();
555
-
556
- const localApiBaseUrlInput = document.getElementById('local-api-base-url');
557
- if (localApiBaseUrlInput) currentConfig.localApiBaseUrl = localApiBaseUrlInput.value.trim();
558
-
559
- const localModelNameInput = document.getElementById('local-model-name');
560
- if (localModelNameInput) currentConfig.localModelName = localModelNameInput.value.trim();
561
-
562
- const voiceReplyToggle = document.getElementById('enable-voice-reply');
563
- if (voiceReplyToggle) {
564
- currentConfig.enableVoiceReply = voiceReplyToggle.checked;
565
- }
566
-
567
- const ttsProviderSelect = document.getElementById('tts-provider-select');
568
- if (ttsProviderSelect) currentConfig.ttsProvider = ttsProviderSelect.value;
569
-
570
- if (document.getElementById('tts-volume')) currentConfig.ttsVolume = parseFloat(document.getElementById('tts-volume').value);
571
- if (document.getElementById('tts-speed')) currentConfig.ttsSpeed = parseFloat(document.getElementById('tts-speed').value);
572
- if (document.getElementById('tts-pitch')) currentConfig.ttsPitch = parseFloat(document.getElementById('tts-pitch').value);
573
-
574
- const enableWorkflowsToggle = document.getElementById('enable-custom-workflows');
575
- if (enableWorkflowsToggle) {
576
- currentConfig.enableCustomWorkflows = enableWorkflowsToggle.checked;
577
- }
578
-
579
- const enableAgentCollaborationToggle = document.getElementById('enable-agent-collaboration');
580
- if (enableAgentCollaborationToggle) {
581
- currentConfig.enableAgentCollaboration = enableAgentCollaborationToggle.checked;
582
- }
583
-
584
- const showWidgetToggle = document.getElementById('show-desktop-widget');
585
- if (showWidgetToggle) {
586
- currentConfig.showDesktopWidget = showWidgetToggle.checked;
587
- }
588
-
589
- currentConfig.automationBrowser = document.getElementById('automation-browser-select').value;
590
- currentConfig.proactiveInterval = Number(document.getElementById('proactive-interval').value);
591
- currentConfig.proactiveCooldown = Number(document.getElementById('proactive-cooldown').value);
592
- currentConfig.systemTextColor = document.getElementById('system-text-color').value;
593
- currentConfig.glassBlur = document.getElementById('glass-blur-select').value;
594
- currentConfig.fontFamily = document.getElementById('font-family-select').value;
595
- currentConfig.fontSize = document.getElementById('font-size-select').value;
596
-
597
- currentConfig.customBgStart = document.getElementById('custom-bg-start').value;
598
- currentConfig.customBgEnd = document.getElementById('custom-bg-end').value;
599
- currentConfig.customPanelBg = document.getElementById('custom-panel-bg').value;
600
-
601
- // Ensure mcpServers is part of the saved config
602
- if (!currentConfig.mcpServers) currentConfig.mcpServers = {};
603
-
604
- console.log('[Settings] Saving config with MCP servers:', Object.keys(currentConfig.mcpServers).length);
605
- await window.settingsApi.saveSettings(currentConfig);
606
- const btn = document.getElementById('save-btn');
607
- btn.textContent = '✅ Saved!';
608
- setTimeout(() => { btn.textContent = 'Save Settings'; }, 1500);
609
- });
610
-
611
- // --- MCP Management Functions ---
612
- function renderMcpServers() {
613
- console.log('[Settings] Rendering MCP Servers UI...');
614
- const list = document.getElementById('mcp-server-list');
615
- if (!list) {
616
- console.warn('[Settings] MCP list element not found in DOM.');
617
- return;
618
- }
619
- list.innerHTML = '';
620
-
621
- const servers = currentConfig.mcpServers || {};
622
- const entries = Object.entries(servers);
623
- console.log(`[Settings] Found ${entries.length} servers in currentConfig.`);
624
-
625
- if (entries.length === 0) {
626
- list.innerHTML = '<p class="mcp-empty">No MCP servers connected.</p>';
627
- return;
628
- }
629
-
630
- for (const [name, cfg] of entries) {
631
- const item = document.createElement('div');
632
- item.className = 'mcp-item';
633
-
634
- item.innerHTML = `
635
- <div class="mcp-info">
636
- <div class="mcp-name">🌐 ${name}</div>
637
- <div class="mcp-command">${cfg.command} ${(cfg.args || []).join(' ')}</div>
638
- </div>
639
- <button class="btn-danger btn-small" onclick="removeMcpServer('${name}')">Remove</button>
640
- `;
641
- list.appendChild(item);
642
- }
643
- }
644
-
645
- window.removeMcpServer = function(name) {
646
- if (confirm(`Remove MCP server "${name}"?`)) {
647
- delete currentConfig.mcpServers[name];
648
- renderMcpServers();
649
- }
650
- };
651
-
652
- document.getElementById('btn-add-mcp').addEventListener('click', () => {
653
- const nameInput = document.getElementById('mcp-new-name');
654
- const cmdInput = document.getElementById('mcp-new-command');
655
- const argsInput = document.getElementById('mcp-new-args');
656
- const envInput = document.getElementById('mcp-new-env');
657
-
658
- const name = nameInput.value.trim();
659
- const command = cmdInput.value.trim();
660
- const argsStr = argsInput.value.trim();
661
- const envStr = envInput.value.trim();
662
-
663
- if (!name || !command) {
664
- alert('Name and Command are required!');
665
- return;
666
- }
667
-
668
- // Basic args split (by space, but respecting some quotes if possible - simple for now)
669
- const args = argsStr ? argsStr.split(/\s+/) : [];
670
-
671
- let env = {};
672
- if (envStr) {
673
- try {
674
- env = JSON.parse(envStr);
675
- } catch (e) {
676
- alert('Invalid JSON in Environment Variables field!');
677
- return;
678
- }
679
- }
680
-
681
- if (!currentConfig.mcpServers) currentConfig.mcpServers = {};
682
- currentConfig.mcpServers[name] = { command, args, env };
683
-
684
- // Clear inputs
685
- nameInput.value = '';
686
- cmdInput.value = '';
687
- argsInput.value = '';
688
- envInput.value = '';
689
-
690
- renderMcpServers();
691
- });
692
-
693
- // Custom Workflows functionality
694
- const openWorkflowsBtn = document.getElementById('open-workflows-btn');
695
- const reloadWorkflowsBtn = document.getElementById('reload-workflows-btn');
696
- if (openWorkflowsBtn) {
697
- openWorkflowsBtn.addEventListener('click', () => {
698
- window.settingsApi.openCustomWorkflows();
699
- });
700
- }
701
- if (reloadWorkflowsBtn) {
702
- reloadWorkflowsBtn.addEventListener('click', async () => {
703
- await window.settingsApi.reloadCustomWorkflows();
704
- const originalText = reloadWorkflowsBtn.textContent;
705
- reloadWorkflowsBtn.textContent = '✅ Reloaded!';
706
- setTimeout(() => { reloadWorkflowsBtn.textContent = originalText; }, 1500);
707
- });
708
- }
709
-
710
- // Quit App
711
- document.getElementById('quit-btn').addEventListener('click', () => {
712
- if (confirm('Are you sure you want to quit Mint?')) {
713
- window.settingsApi.quitApp();
714
- }
715
- });
716
-
717
- // Reset to default
718
- document.getElementById('reset-btn').addEventListener('click', () => {
719
- currentConfig = { ...DEFAULT_CONFIG };
720
- applyConfig(currentConfig);
721
- });
722
-
723
- function updatePluginButton(pluginName, isEnabled) {
724
- const btn = document.getElementById(`btn-plugin-${pluginName}`);
725
- if (!btn) return;
726
-
727
- if (isEnabled) {
728
- btn.textContent = 'Disconnect';
729
- btn.classList.remove('btn-connect');
730
- btn.classList.add('btn-disconnect');
731
- } else {
732
- btn.textContent = 'Connect';
733
- btn.classList.add('btn-connect');
734
- btn.classList.remove('btn-disconnect');
735
- }
736
- }
737
-
738
- // Bind plugin buttons
739
- ['spotify', 'calendar', 'gmail', 'notion', 'discord'].forEach(plugin => {
740
- const btn = document.getElementById(`btn-plugin-${plugin}`);
741
- if (btn) {
742
- btn.addEventListener('click', () => {
743
- const key = `plugin${plugin.charAt(0).toUpperCase() + plugin.slice(1)}Enabled`;
744
- currentConfig[key] = !currentConfig[key];
745
- updatePluginButton(plugin, currentConfig[key]);
746
- });
747
- }
748
- });
749
-
750
- // Init
751
- // Sidebar Tab Navigation
752
- document.querySelectorAll('.tab-btn').forEach(btn => {
753
- btn.addEventListener('click', () => {
754
- const target = btn.dataset.target;
755
- // Deactivate all
756
- document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
757
- document.querySelectorAll('.tab-pane').forEach(p => p.classList.remove('active'));
758
- // Activate selected
759
- btn.classList.add('active');
760
- const pane = document.getElementById(target);
761
- if (pane) pane.classList.add('active');
762
-
763
- // Re-render MCP list if switching to plugins tab
764
- if (target === 'sect-plugins') {
765
- renderMcpServers();
766
- }
767
- });
768
- });
769
-
770
- window.addEventListener('DOMContentLoaded', loadSettings);