kiku-agent 1.3.1 → 1.3.3

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 (232) hide show
  1. package/README.md +69 -12
  2. package/package.json +5 -12
  3. package/server/agent/agentCore.js +319 -46
  4. package/server/agent/appPaths.js +31 -0
  5. package/server/agent/audioPlayer.js +339 -12
  6. package/server/agent/autoContext.js +193 -0
  7. package/server/agent/catalogEntityResolver.js +170 -28
  8. package/server/agent/clarifyingQuestions.js +137 -35
  9. package/server/agent/cli.js +177 -48
  10. package/server/agent/cloudAdapters.js +116 -0
  11. package/server/agent/commandRegistry.js +409 -80
  12. package/server/agent/commands.js +1056 -125
  13. package/server/agent/config.js +1088 -690
  14. package/server/agent/contextCompactor.js +213 -21
  15. package/server/agent/cpuMetrics.js +199 -0
  16. package/server/agent/engineService.js +591 -0
  17. package/server/agent/eval/AGENTS.md +228 -0
  18. package/server/agent/eval/analyze.py +684 -0
  19. package/server/agent/eval/gates.json +15 -0
  20. package/server/agent/eval/modules/analysis/compare.js +198 -0
  21. package/server/agent/eval/modules/analysis/gates.js +72 -0
  22. package/server/agent/eval/modules/analysis/judge.js +70 -0
  23. package/server/agent/eval/modules/core/cli.js +453 -0
  24. package/server/agent/eval/modules/core/config.js +60 -0
  25. package/server/agent/eval/modules/core/store.js +236 -0
  26. package/server/agent/eval/modules/evaluation/cases.js +689 -0
  27. package/server/agent/eval/modules/evaluation/runner.js +288 -0
  28. package/server/agent/eval/modules/evaluation/scoring.js +363 -0
  29. package/server/agent/eval/modules/evaluation/worker.js +122 -0
  30. package/server/agent/eval/modules/reporting/benchmark.js +265 -0
  31. package/server/agent/eval/modules/reporting/benchmarkPng.js +487 -0
  32. package/server/agent/eval/modules/reporting/dashboard.js +1406 -0
  33. package/server/agent/eval/modules/server/evalApi.js +1099 -0
  34. package/server/agent/eval/modules/ui/evalUi.js +4799 -0
  35. package/server/agent/eval/modules/utils/smokes.js +119 -0
  36. package/server/agent/eventBus.js +1 -0
  37. package/server/agent/ink/main.jsx +196 -191
  38. package/server/agent/jobManager.js +11 -1
  39. package/server/agent/lanDiscovery.js +721 -23
  40. package/server/agent/llmClient.js +317 -71
  41. package/server/agent/lmStudioWakeup.js +517 -65
  42. package/server/agent/locationService.js +797 -0
  43. package/server/agent/mcpQuizData.js +509 -0
  44. package/server/agent/memory/contextAllocator.js +19 -7
  45. package/server/agent/memory.js +3 -1
  46. package/server/agent/modelCompatibility.js +352 -0
  47. package/server/agent/modelDefaults.js +1 -0
  48. package/server/agent/modelManager.js +46 -2
  49. package/server/agent/newsWatch.js +9 -3
  50. package/server/agent/processManager.js +229 -0
  51. package/server/agent/prompts.js +174 -8
  52. package/server/agent/routingInterceptor.js +9 -1
  53. package/server/agent/sanitizer.js +41 -6
  54. package/server/agent/searchQueryPlanner.js +202 -0
  55. package/server/agent/session.js +59 -4
  56. package/server/agent/tests/agentBubbleSystem.test.js +65 -0
  57. package/server/agent/tests/agentFollowUps.test.js +253 -0
  58. package/server/agent/tests/agentMusicControl.test.js +245 -0
  59. package/server/agent/tests/apiRouter.test.js +108 -0
  60. package/server/agent/tests/architectureFixes.test.js +81 -0
  61. package/server/agent/tests/architectureRefactoring.test.js +194 -0
  62. package/server/agent/tests/autoContext.test.js +176 -0
  63. package/server/agent/tests/autoResearch.test.js +64 -0
  64. package/server/agent/tests/bilibiliEmbed.test.js +296 -0
  65. package/server/agent/tests/catalogSync.test.js +130 -0
  66. package/server/agent/tests/chatHardening.test.js +121 -0
  67. package/server/agent/tests/chineseWebSearchEscalation.test.js +62 -0
  68. package/server/agent/tests/citations.test.js +180 -0
  69. package/server/agent/tests/clarificationAnalytics.test.js +219 -0
  70. package/server/agent/tests/clarifyingQuestions.test.js +627 -0
  71. package/server/agent/tests/cliAutomation.test.js +158 -0
  72. package/server/agent/tests/cloudProviders.test.js +322 -0
  73. package/server/agent/tests/commandInput.test.js +24 -0
  74. package/server/agent/tests/commands.test.js +506 -0
  75. package/server/agent/tests/contextIntelligence.test.js +209 -0
  76. package/server/agent/tests/conversationSafety.test.js +53 -0
  77. package/server/agent/tests/cpuMetrics.test.js +101 -0
  78. package/server/agent/tests/decisionAndSearchEnhancements.test.js +167 -0
  79. package/server/agent/tests/dramaAnswerQuality.test.js +73 -0
  80. package/server/agent/tests/dynamicCatalogIngestion.test.js +285 -0
  81. package/server/agent/tests/dynamicRoutingAndSearch.test.js +92 -0
  82. package/server/agent/tests/edgeCasesScenarios.test.js +131 -0
  83. package/server/agent/tests/engineService.test.js +436 -0
  84. package/server/agent/tests/engineUnload.test.js +94 -0
  85. package/server/agent/tests/entertainmentMetrics.test.js +126 -0
  86. package/server/agent/tests/envBootstrap.test.js +87 -0
  87. package/server/agent/tests/envCommand.test.js +284 -0
  88. package/server/agent/tests/errorHandling.test.js +80 -0
  89. package/server/agent/tests/errors.test.js +13 -0
  90. package/server/agent/tests/evalAnalyze.test.js +54 -0
  91. package/server/agent/tests/evalCommand.test.js +54 -0
  92. package/server/agent/tests/evalCorpus.test.js +126 -0
  93. package/server/agent/tests/evalHarness.test.js +62 -0
  94. package/server/agent/tests/evalJudgeContext.test.js +38 -0
  95. package/server/agent/tests/evalMetrics.test.js +320 -0
  96. package/server/agent/tests/evalStore.test.js +190 -0
  97. package/server/agent/tests/evalStudio.test.js +179 -0
  98. package/server/agent/tests/feedbackLearning.test.js +186 -0
  99. package/server/agent/tests/fetchApi.test.js +99 -0
  100. package/server/agent/tests/firstRun.test.js +44 -0
  101. package/server/agent/tests/gemma4eOptimization.test.js +95 -0
  102. package/server/agent/tests/hardwareTiers.test.js +206 -0
  103. package/server/agent/tests/hybridWebSearch.test.js +194 -0
  104. package/server/agent/tests/judgeService.test.js +251 -0
  105. package/server/agent/tests/lanDiscovery.test.js +324 -0
  106. package/server/agent/tests/lanInterfaces.test.js +510 -0
  107. package/server/agent/tests/lmStudioWakeup.test.js +278 -0
  108. package/server/agent/tests/locationTool.test.js +278 -0
  109. package/server/agent/tests/mcpClient.test.js +201 -0
  110. package/server/agent/tests/memoryRoute.test.js +173 -0
  111. package/server/agent/tests/memoryUiNormalization.test.js +75 -0
  112. package/server/agent/tests/modelCompatibility.test.js +148 -0
  113. package/server/agent/tests/modelManager.test.js +141 -0
  114. package/server/agent/tests/multilingualScenarios.test.js +69 -0
  115. package/server/agent/tests/musicControlUiBridge.test.js +113 -0
  116. package/server/agent/tests/newCommands.test.js +347 -0
  117. package/server/agent/tests/newCommandsTui.test.js +141 -0
  118. package/server/agent/tests/newTools.test.js +113 -0
  119. package/server/agent/tests/newsIntelligence.test.js +178 -0
  120. package/server/agent/tests/nextGenArchitecture.test.js +101 -0
  121. package/server/agent/tests/offlineInput.test.js +217 -0
  122. package/server/agent/tests/openDomainPrompt.test.js +197 -0
  123. package/server/agent/tests/openDomainSearch.test.js +121 -0
  124. package/server/agent/tests/packagingGuard.test.js +57 -0
  125. package/server/agent/tests/presentation.test.js +61 -0
  126. package/server/agent/tests/processManager.test.js +144 -0
  127. package/server/agent/tests/providerPersistence.test.js +44 -0
  128. package/server/agent/tests/queryBenchmarks.test.js +83 -0
  129. package/server/agent/tests/queryDetails.test.js +126 -0
  130. package/server/agent/tests/quickActionsAndModals.test.js +180 -0
  131. package/server/agent/tests/realWorldValidation.test.js +391 -0
  132. package/server/agent/tests/resilienceAndConcurrency.test.js +117 -0
  133. package/server/agent/tests/runtimeWatchdog.test.js +32 -0
  134. package/server/agent/tests/sanitizer.test.js +37 -0
  135. package/server/agent/tests/scenariosData.js +378 -0
  136. package/server/agent/tests/schemaRouting.test.js +54 -0
  137. package/server/agent/tests/searchQueryPlanner.test.js +108 -0
  138. package/server/agent/tests/securityAuditRemediation.test.js +221 -0
  139. package/server/agent/tests/securityAuditRemediations2.test.js +154 -0
  140. package/server/agent/tests/securityHardening.test.js +146 -0
  141. package/server/agent/tests/securitySanitizer.test.js +38 -0
  142. package/server/agent/tests/sessionAndCopy.test.js +267 -0
  143. package/server/agent/tests/sidebarControls.test.js +135 -0
  144. package/server/agent/tests/statefulMemory.test.js +277 -0
  145. package/server/agent/tests/subagent.test.js +216 -0
  146. package/server/agent/tests/subagentProgress.test.js +109 -0
  147. package/server/agent/tests/subagentTextFallback.test.js +115 -0
  148. package/server/agent/tests/suggestions.test.js +199 -0
  149. package/server/agent/tests/suggestionsTui.test.js +251 -0
  150. package/server/agent/tests/telemetryAndProfiles.test.js +179 -0
  151. package/server/agent/tests/terminalImage.test.js +80 -0
  152. package/server/agent/tests/terminalMarkdown.test.js +166 -0
  153. package/server/agent/tests/terminalText.test.js +133 -0
  154. package/server/agent/tests/textProtocolLoop.test.js +197 -0
  155. package/server/agent/tests/textToolParsing.test.js +187 -0
  156. package/server/agent/tests/theme.test.js +26 -0
  157. package/server/agent/tests/toolRegistryParity.test.js +53 -0
  158. package/server/agent/tests/toolRoutingRegressions.test.js +160 -0
  159. package/server/agent/tests/tools.test.js +259 -0
  160. package/server/agent/tests/unifiedEndpoints.test.js +159 -0
  161. package/server/agent/tests/v110Features.test.js +262 -0
  162. package/server/agent/tests/versionBump.test.js +69 -0
  163. package/server/agent/tests/vramEstimator.test.js +595 -0
  164. package/server/agent/tests/webChatDocs.test.js +199 -0
  165. package/server/agent/tests/webChatInferenceControl.test.js +298 -0
  166. package/server/agent/tests/webChatInspection.test.js +551 -0
  167. package/server/agent/tests/webChatMcp.test.js +94 -0
  168. package/server/agent/tests/webChatMemory.test.js +112 -0
  169. package/server/agent/tests/webChatSecurity.test.js +169 -0
  170. package/server/agent/tests/webExtract.test.js +284 -0
  171. package/server/agent/tests/webSources.test.js +281 -0
  172. package/server/agent/textToolProtocol.js +173 -46
  173. package/server/agent/toolRouter.js +318 -44
  174. package/server/agent/tools.js +877 -96
  175. package/server/agent/ui.js +39 -34
  176. package/server/agent/vramService.js +35 -54
  177. package/server/agent/webSearch.js +441 -162
  178. package/server/agent/websearch/orchestrator.js +15 -5
  179. package/server/agent/websearch/resilience/cache.js +9 -2
  180. package/server/agent/websearch/security/ssrf.js +41 -10
  181. package/server/agent/youtubeAuth.js +5 -20
  182. package/server/apiRouter.js +5558 -4422
  183. package/server/eval/judgeRubrics.js +110 -0
  184. package/server/eval/judgeService.js +290 -0
  185. package/server/eval/runBenchmark.js +182 -0
  186. package/server/mcp/data/discography.js +2 -2
  187. package/server/mcp/examples/antigravity.example.json +17 -0
  188. package/server/mcp/examples/librechat.example.yaml +16 -0
  189. package/server/mcp/handler.js +8 -4
  190. package/server/mcp/security.js +220 -21
  191. package/server/mcp/server.js +2 -1
  192. package/server/mcp/tests/connection.test.js +162 -0
  193. package/server/mcp/tests/mcpKeyAuth.test.js +156 -0
  194. package/server/mcp/tools.js +7 -1
  195. package/server/supabase_migration_prefix.sql +102 -0
  196. package/server/supabase_schema.sql +63 -0
  197. package/server/web-chat/core/connection.js +179 -218
  198. package/server/web-chat/core/conversationContext.js +9 -2
  199. package/server/web-chat/core/directCatalogEngine.js +52 -28
  200. package/server/web-chat/core/dramaKnowledge.js +33 -22
  201. package/server/web-chat/core/followUpEngine.js +735 -81
  202. package/server/web-chat/core/futureEventGuard.js +5 -1
  203. package/server/web-chat/core/musicControlAction.js +70 -0
  204. package/server/web-chat/core/security.js +32 -21
  205. package/server/web-chat/core/toolInspector.js +6 -6
  206. package/server/web-chat/core/urlGuard.js +45 -0
  207. package/server/web-chat/router.js +204 -157
  208. package/server/web-chat/routes/chatRoute.js +885 -488
  209. package/server/web-chat/routes/engineRoute.js +270 -0
  210. package/server/web-chat/routes/exportRoute.js +1 -1
  211. package/server/web-chat/routes/lanDiscoveryRoute.js +17 -2
  212. package/server/web-chat/routes/lmStudioLoadRoute.js +172 -0
  213. package/server/web-chat/routes/mcpRoute.js +386 -0
  214. package/server/web-chat/routes/memoryRoute.js +253 -0
  215. package/server/web-chat/routes/providerRoute.js +49 -16
  216. package/server/web-chat/routes/staticRoute.js +306 -17
  217. package/server/web-chat/routes/statusRoute.js +194 -73
  218. package/server/web-chat/routes/suggestRoute.js +11 -3
  219. package/server/web-chat/routes/verifyRoute.js +26 -4
  220. package/server/web-chat/server.js +7 -6
  221. package/server/web-chat/ui/docsBuilder.js +3558 -0
  222. package/server/web-chat/ui/htmlBuilder.js +12 -0
  223. package/server/web-chat/ui/scripts/client.js +3401 -1302
  224. package/server/web-chat/ui/scripts/webchatI18n.js +155 -153
  225. package/server/web-chat/ui/settingsBuilder.js +7870 -0
  226. package/server/web-chat/ui/styles/lan-card.css +165 -0
  227. package/server/web-chat/ui/styles/main.css +4289 -447
  228. package/server/web-chat/ui/sw.js +64 -0
  229. package/server/web-chat/ui/templates/body.html +407 -281
  230. package/src/data/awardsData.js +146 -146
  231. package/src/data/musicVideoData.js +6 -4
  232. package/src/lib/vram/estimator.js +195 -19
@@ -6,13 +6,13 @@
6
6
  <aside class="app-sidebar" id="app-sidebar" aria-label="KIKU AGENT navigation">
7
7
  <div class="sidebar-brand-row">
8
8
  <button type="button" class="sidebar-brand" onclick="createNewChatSession()" aria-label="KIKU AGENT — เริ่มแชทใหม่">
9
- <span class="brand-spark"><svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="currentColor"><path d="m12 3 2.8 5.7 6.2.9-4.5 4.4 1.1 6.2L12 17.3 6.4 20.2l1.1-6.2-4.5-4.4 6.2-.9z"/></svg></span>
9
+ <span class="brand-spark"><i class="bi bi-star-fill" aria-hidden="true" style="font-size:18px;"></i></span>
10
10
  <span class="brand-text">
11
11
  <strong class="brand-name-wrap">KIKU AGENT</strong>
12
12
  </span>
13
13
  </button>
14
14
  <button type="button" class="sidebar-icon-button sidebar-collapse-button" id="btn-sidebar-collapse" onclick="toggleAppSidebar()" title="ย่อ/ขยายแถบเมนู" aria-label="ย่อ/ขยายแถบเมนู" aria-expanded="true">
15
- <svg aria-hidden="true" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="4" y1="6" x2="20" y2="6"/><line x1="4" y1="12" x2="20" y2="12"/><line x1="4" y1="18" x2="20" y2="18"/></svg>
15
+ <i class="bi bi-list" aria-hidden="true" style="font-size:20px;"></i>
16
16
  </button>
17
17
  </div>
18
18
 
@@ -22,40 +22,45 @@
22
22
  <span data-sidebar-i18n="exploreHeading">Explore &amp; Features</span>
23
23
  </div>
24
24
  <button type="button" class="sidebar-nav-item" onclick="openSessionsModal()" title="ค้นหาประวัติการสนทนา">
25
- <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.4-3.4"/></svg>
25
+ <i class="bi bi-search" aria-hidden="true" style="font-size:18px;"></i>
26
26
  <span data-sidebar-i18n="search">Search Chat</span>
27
27
  </button>
28
28
  <button type="button" class="sidebar-nav-item" id="sidebar-music-button" onclick="openMusicModal()" title="คลังเพลงและ Jukebox">
29
- <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 18V5l12-2v13"/><circle cx="6" cy="18" r="3"/><circle cx="18" cy="16" r="3"/></svg>
29
+ <i class="bi bi-music-note-beamed" aria-hidden="true" style="font-size:18px;"></i>
30
30
  <span data-sidebar-i18n="music">Music Jukebox</span>
31
31
  </button>
32
32
  <button type="button" class="sidebar-nav-item" onclick="openQuizModal()" title="เกมทายปัญหาแฟนคลับ">
33
- <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M6 9H4.5a2.5 2.5 0 0 1 0-5H6"/><path d="M18 9h1.5a2.5 2.5 0 0 0 0-5H18"/><path d="M4 22h16"/><path d="M10 14.66V17c0 .55-.45 1-1 1H7.5a1.5 1.5 0 0 0 0 3h9a1.5 1.5 0 0 0 0-3H15c-.55 0-1-.45-1-1v-2.34"/><path d="M18 4H6v7a6 6 0 0 0 12 0V4Z"/></svg>
33
+ <i class="bi bi-trophy" aria-hidden="true" style="font-size:18px;"></i>
34
34
  <span data-sidebar-i18n="quiz">Fan Quiz Challenge</span>
35
35
  </button>
36
- <button type="button" class="sidebar-nav-item" onclick="renderTimelineModal()" title="ไทม์ไลน์เส้นทางอาชีพ">
37
- <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="20" x2="12" y2="4"/><polyline points="6 10 12 4 18 10"/><line x1="4" y1="20" x2="20" y2="20"/></svg>
36
+ <button type="button" class="sidebar-nav-item" onclick="openTimelineModal()" title="ไทม์ไลน์เส้นทางอาชีพ">
37
+ <i class="bi bi-clock-history" aria-hidden="true" style="font-size:18px;"></i>
38
38
  <span data-sidebar-i18n="timeline">Career Timeline</span>
39
39
  </button>
40
40
  <button type="button" class="sidebar-nav-item" onclick="toggleSuggestionsDrawer()" title="หัวข้อคำถามแนะนำ">
41
- <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="m12 3-1.912 5.813a2 2 0 0 1-1.275 1.275L3 12l5.813 1.912a2 2 0 0 1 1.275 1.275L12 21l1.912-5.813a2 2 0 0 1 1.275-1.275L21 12l-5.813-1.912a2 2 0 0 1-1.275-1.275L12 3Z"/></svg>
41
+ <i class="bi bi-stars" aria-hidden="true" style="font-size:18px;"></i>
42
42
  <span data-sidebar-i18n="prompts">Suggested Prompts</span>
43
43
  </button>
44
44
  <button type="button" class="sidebar-nav-item" onclick="toggleSavedPrompts()" title="พรอมต์ที่บันทึกไว้">
45
- <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z"/></svg>
45
+ <i class="bi bi-bookmark" aria-hidden="true" style="font-size:18px;"></i>
46
46
  <span data-sidebar-i18n="saved">Saved Prompts</span>
47
47
  </button>
48
48
  <button type="button" class="sidebar-nav-item" onclick="openSponsorsModal()" title="ผู้สนับสนุนโครงการ (Sponsors & Ads)">
49
- <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="8" r="7"/><polyline points="8.21 13.89 7 23 12 20 17 23 15.79 13.88"/></svg>
49
+ <i class="bi bi-award" aria-hidden="true" style="font-size:18px;"></i>
50
50
  <span data-sidebar-i18n="sponsors">Sponsors &amp; Ads</span>
51
51
  </button>
52
+ <button type="button" class="sidebar-nav-item" onclick="openMcpToolsModal()" title="สถานะ MCP Server และรายการ Tool ทั้งหมดในระบบ">
53
+ <i class="bi bi-cpu" aria-hidden="true" style="font-size:18px;"></i>
54
+ <span data-sidebar-i18n="mcpTools">MCP &amp; Tools</span>
55
+ <span class="mcp-count-pill" id="sidebar-mcp-count">68+</span>
56
+ </button>
52
57
  </nav>
53
58
 
54
59
  <section class="sidebar-section sidebar-history" aria-labelledby="history-section-title">
55
60
  <div class="sidebar-section-heading static">
56
61
  <span id="history-section-title" data-sidebar-i18n="history">Chats</span>
57
62
  <button type="button" onclick="openSessionsModal()" title="ดูประวัติทั้งหมด" aria-label="ดูประวัติทั้งหมด">
58
- <svg aria-hidden="true" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 8v4l3 2"/><circle cx="12" cy="12" r="9"/></svg>
63
+ <i class="bi bi-clock-history" aria-hidden="true" style="font-size:15px;"></i>
59
64
  </button>
60
65
  </div>
61
66
  <div class="sidebar-session-list" id="sidebar-session-list" aria-live="polite"></div>
@@ -70,15 +75,15 @@
70
75
  <section class="sidebar-section sidebar-sponsors" aria-label="ผู้สนับสนุนโครงการ">
71
76
  <div class="sidebar-section-heading static" style="display:flex; justify-content:space-between; align-items:center;">
72
77
  <span style="display:flex; align-items:center; gap:6px; font-weight:700; font-size:11px; letter-spacing:0.04em;">
73
- <span style="color:#f472b6;">📢</span>
78
+ <span style="color:#f472b6;">•</span>
74
79
  <span data-sidebar-i18n="sponsorsHeading">Sponsor Spotlight</span>
75
80
  </span>
76
81
  <div style="display:flex; gap:4px; align-items:center;">
77
82
  <button type="button" class="btn-sidebar-heading-action" onclick="cycleSidebarAd(event)" title="หมุนเวียนโฆษณา (Next Sponsor)" aria-label="หมุนเวียนโฆษณา">
78
- <svg aria-hidden="true" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21.5 2v6h-6M21.34 15.57a10 10 0 1 1-.57-8.38l5.67-5.67"/></svg>
83
+ <i class="bi bi-arrow-clockwise" aria-hidden="true" style="font-size:13px;"></i>
79
84
  </button>
80
85
  <button type="button" class="btn-sidebar-heading-action" onclick="openSponsorsModal(event)" title="ดูผู้สนับสนุนทั้งหมด" aria-label="ดูผู้สนับสนุนทั้งหมด">
81
- <svg aria-hidden="true" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg>
86
+ <i class="bi bi-box-arrow-up-right" aria-hidden="true" style="font-size:13px;"></i>
82
87
  </button>
83
88
  </div>
84
89
  </div>
@@ -92,28 +97,28 @@
92
97
  <span data-sidebar-i18n="controlsHeading">System Controls</span>
93
98
  </div>
94
99
  <button type="button" class="sidebar-nav-item" onclick="exportChat()" title="ส่งออกบทสนทนาเป็นไฟล์ Markdown">
95
- <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
100
+ <i class="bi bi-download" aria-hidden="true" style="font-size:18px;"></i>
96
101
  <span data-sidebar-i18n="export">Export Chat</span>
97
102
  </button>
98
103
  <button type="button" class="sidebar-nav-item" onclick="togglePetals()" title="เปิด/ปิด กลีบดอกซากุระ">
99
- <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M12 2a4 4 0 0 0-4 4c0 3 4 5 4 5s4-2 4-5a4 4 0 0 0-4-4Z"/><path d="M12 22a4 4 0 0 0 4-4c0-3-4-5-4-5s-4 2-4 5a4 4 0 0 0 4 4Z"/><path d="M2 12a4 4 0 0 0 4 4c3 0 5-4 5-4s-2-4-5-4a4 4 0 0 0-4 4Z"/><path d="M22 12a4 4 0 0 0-4-4c-3 0-5 4-5 4s2 4 5 4a4 4 0 0 0 4-4Z"/></svg>
104
+ <i class="bi bi-flower1" aria-hidden="true" style="font-size:18px;"></i>
100
105
  <span id="sidebar-petals-label" data-sidebar-i18n="petals">Sakura Petals</span>
101
106
  </button>
102
107
  <button type="button" class="sidebar-nav-item" onclick="toggleTheme()" title="สลับโหมด กลางวัน / กลางคืน">
103
- <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"/></svg>
108
+ <i class="bi bi-moon-stars" aria-hidden="true" style="font-size:18px;"></i>
104
109
  <span id="sidebar-theme-label" data-sidebar-i18n="theme">Theme Mode</span>
105
110
  </button>
106
111
  <button type="button" class="sidebar-nav-item" onclick="toggleSound()" title="เปิด/ปิด เสียงเอฟเฟกต์">
107
- <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/><path d="M15.54 8.46a5 5 0 0 1 0 7.07"/><path d="M19.07 4.93a10 10 0 0 1 0 14.14"/></svg>
112
+ <i class="bi bi-volume-up" aria-hidden="true" style="font-size:18px;"></i>
108
113
  <span id="sidebar-sound-label" data-sidebar-i18n="sound">Sound FX</span>
109
114
  </button>
110
115
  <button type="button" class="sidebar-nav-item" onclick="cycleLanguage()" title="เปลี่ยนภาษา (TH / 中文 / EN)">
111
- <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
116
+ <i class="bi bi-translate" aria-hidden="true" style="font-size:18px;"></i>
112
117
  <span id="sidebar-lang-label" data-sidebar-i18n="lang">Language (TH)</span>
113
118
  </button>
114
- <button type="button" class="sidebar-nav-item" id="btn-settings-toggle" onclick="openSettingsModal()" title="ตั้งค่าโมเดลและ AI Provider">
115
- <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
116
- <span id="sidebar-settings-label" data-sidebar-i18n="settings">AI Settings (Model)</span>
119
+ <button type="button" class="sidebar-nav-item" id="btn-settings-toggle" onclick="window.location.href='/settings'" title="ตั้งค่าโมเดลและ AI Provider เต็มรูปแบบ">
120
+ <i class="bi bi-gear" aria-hidden="true" style="font-size:18px;"></i>
121
+ <span id="sidebar-settings-label" data-sidebar-i18n="settings">AI Settings (/settings)</span>
117
122
  </button>
118
123
  </section>
119
124
  </div>
@@ -122,13 +127,13 @@
122
127
  <header class="workspace-toolbar">
123
128
  <div class="toolbar-leading">
124
129
  <button type="button" class="toolbar-sidebar-button" id="toolbar-sidebar-button" onclick="toggleAppSidebar()" title="เปิด/ปิดแถบเมนู (Sidebar)" aria-label="เปิดแถบเมนู" aria-expanded="false">
125
- <svg aria-hidden="true" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="4" y1="6" x2="20" y2="6"/><line x1="4" y1="12" x2="20" y2="12"/><line x1="4" y1="18" x2="20" y2="18"/></svg>
130
+ <i class="bi bi-list" aria-hidden="true" style="font-size:20px;"></i>
126
131
  </button>
127
132
  <span class="toolbar-title" style="font-weight: 700; font-size: 13px; color: var(--text);">KIKU AGENT</span>
128
133
  </div>
129
134
  <div class="toolbar-trailing" style="display: flex; align-items: center; gap: 8px;">
130
- <button type="button" class="toolbar-sidebar-button" id="btn-mobile-settings-toggle" onclick="openSettingsModal()" title="ตั้งค่าโมเดลและ AI Provider" aria-label="ตั้งค่าโมเดล">
131
- <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
135
+ <button type="button" class="toolbar-sidebar-button" id="btn-mobile-settings-toggle" onclick="window.location.href='/settings'" title="ตั้งค่าโมเดลและ AI Provider" aria-label="ตั้งค่าโมเดล">
136
+ <i class="bi bi-gear" aria-hidden="true" style="font-size:18px;"></i>
132
137
  </button>
133
138
  </div>
134
139
  </header>
@@ -138,14 +143,26 @@
138
143
  <div id="chat-container">
139
144
  <div class="welcome-hero" id="welcome-hero">
140
145
  <section class="hero-media" aria-label="แกลเลอรีภาพจวีจิ้งอี">
141
- <figure class="hero-media-frame hero-media-primary">
142
- <img src="/images/0040jbadgy1id6am4yxqfj61s82dn1kx02.jpg" alt="จวีจิ้งอีในลุคชุดสีครีม" width="690" height="903" fetchpriority="high" decoding="async">
146
+ <figure class="hero-media-frame hero-media-primary" data-hero-slot="primary" tabindex="0" role="region" aria-label="ภาพสล็อตหลัก">
147
+ <img id="hero-img-primary" src="/images/0040jbadgy1id6am4yxqfj61s82dn1kx02.jpg" alt="จวีจิ้งอีในลุคชุดสีครีม" width="690" height="903" fetchpriority="high" decoding="async">
148
+ <button type="button" class="hero-slot-action" onclick="openHeroGalleryPicker('primary')" title="เลือกภาพสล็อตหลัก" aria-label="เลือกภาพสล็อตหลัก">
149
+ <i class="bi bi-image" aria-hidden="true" style="font-size:13px;"></i>
150
+ <span>เปลี่ยนภาพ</span>
151
+ </button>
143
152
  </figure>
144
- <figure class="hero-media-frame hero-media-secondary">
145
- <img src="/images/008ET7Legy1ig9s8bab6sj30i20o7go1.jpg" alt="ภาพพอร์ตเทรตจวีจิ้งอีกลางแสงธรรมชาติ" width="650" height="871" decoding="async">
153
+ <figure class="hero-media-frame hero-media-secondary" data-hero-slot="secondary" tabindex="0" role="region" aria-label="ภาพสล็อตรอง">
154
+ <img id="hero-img-secondary" src="/images/008ET7Legy1ig9s8bab6sj30i20o7go1.jpg" alt="ภาพพอร์ตเทรตจวีจิ้งอีกลางแสงธรรมชาติ" width="650" height="871" decoding="async">
155
+ <button type="button" class="hero-slot-action" onclick="openHeroGalleryPicker('secondary')" title="เลือกภาพสล็อตรอง" aria-label="เลือกภาพสล็อตรอง">
156
+ <i class="bi bi-image" aria-hidden="true" style="font-size:13px;"></i>
157
+ <span>เปลี่ยนภาพ</span>
158
+ </button>
146
159
  </figure>
147
- <figure class="hero-media-frame hero-media-poster">
148
- <img src="/images/008ET7Legy1ig9s8cbxkzj30i20mxmzh.jpg" alt="โปสเตอร์ซีรีส์ In Blossom" width="1000" height="1778" decoding="async">
160
+ <figure class="hero-media-frame hero-media-poster" data-hero-slot="poster" tabindex="0" role="region" aria-label="ภาพสล็อตโปสเตอร์">
161
+ <img id="hero-img-poster" src="/images/008ET7Legy1ig9s8cbxkzj30i20mxmzh.jpg" alt="โปสเตอร์ซีรีส์ In Blossom" width="1000" height="1778" decoding="async">
162
+ <button type="button" class="hero-slot-action" onclick="openHeroGalleryPicker('poster')" title="เลือกภาพสล็อตโปสเตอร์" aria-label="เลือกภาพสล็อตโปสเตอร์">
163
+ <i class="bi bi-image" aria-hidden="true" style="font-size:13px;"></i>
164
+ <span>เปลี่ยนภาพ</span>
165
+ </button>
149
166
  </figure>
150
167
  <div class="hero-media-mark" aria-hidden="true">
151
168
  <strong>JU JINGYI</strong>
@@ -167,15 +184,15 @@
167
184
  <div class="suggestions-drawer" id="suggestions-drawer">
168
185
  <div class="suggestions-header-bar">
169
186
  <span class="suggestions-title">
170
- <svg aria-hidden="true" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg>
187
+ <i class="bi bi-star" aria-hidden="true" style="font-size:13px;"></i>
171
188
  <span id="suggestions-title-text">หัวข้อคำถามแนะนำ</span>
172
189
  </span>
173
190
  <span class="suggestions-header-actions">
174
191
  <button type="button" class="btn-ai-suggest" id="btn-ai-suggest" onclick="requestAiSuggestions()" title="ให้ KIKU AI สร้างคำถาม">
175
- <span id="btn-ai-suggest-label">✨ AI สร้างคำถาม</span>
192
+ <span id="btn-ai-suggest-label">• AI สร้างคำถาม</span>
176
193
  </button>
177
194
  <button type="button" class="btn-toggle-drawer" onclick="toggleSuggestionsDrawer()">
178
- <svg aria-hidden="true" width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
195
+ <i class="bi bi-x-lg" aria-hidden="true" style="font-size:11px;"></i>
179
196
  <span id="suggestions-close-label">ย่อเก็บ</span>
180
197
  </button>
181
198
  </span>
@@ -198,7 +215,7 @@
198
215
  <div class="mini-card-horizontal-main">
199
216
  <div class="mini-vinyl-art-wrap">
200
217
  <div class="mini-vinyl-art-disc" id="mini-vinyl-art-disc">
201
- <img id="mini-player-poster" class="mini-card-poster" src="https://img.youtube.com/vi/9AeErG03SZw/hqdefault.jpg" alt="Poster" onerror="this.onerror=null;this.src='https://img.youtube.com/vi/9AeErG03SZw/hqdefault.jpg';" />
218
+ <img id="mini-player-poster" class="mini-card-poster" src="https://img.youtube.com/vi/9AeErG03SZw/hqdefault.jpg" alt="Poster" width="50" height="50" loading="lazy" decoding="async" onerror="this.onerror=null;this.src='https://img.youtube.com/vi/9AeErG03SZw/hqdefault.jpg';" />
202
219
  <div class="mini-vinyl-center-pin"></div>
203
220
  </div>
204
221
  <div class="poster-glow-aura" id="mini-poster-glow"></div>
@@ -231,16 +248,16 @@
231
248
  </div>
232
249
  </div>
233
250
  <button type="button" class="mini-card-btn-icon" id="btn-mini-video-toggle" onclick="toggleMiniPlayerVideo()" title="สลับดูวิดีโอ MV">
234
- <svg aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect width="20" height="15" x="2" y="5" rx="2"/><polygon points="10 9 15 12.5 10 16 10 9"/></svg>
251
+ <i class="bi bi-camera-video" aria-hidden="true" style="font-size:14px;"></i>
235
252
  </button>
236
253
  <button type="button" class="mini-card-btn-icon" onclick="openMusicModal()" title="เปิดคลังเพลงทั้งหมด (46 บทเพลง)">
237
- <svg aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 18V5l12-2v13"/><circle cx="6" cy="18" r="3"/><circle cx="18" cy="16" r="3"/></svg>
254
+ <i class="bi bi-music-note-beamed" aria-hidden="true" style="font-size:14px;"></i>
238
255
  </button>
239
256
  <button type="button" class="mini-card-btn-icon" onclick="setMiniPlayerExpanded(false)" title="ย่อขนาด">
240
- <svg aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="5" y1="12" x2="19" y2="12"/></svg>
257
+ <i class="bi bi-dash-lg" aria-hidden="true" style="font-size:14px;"></i>
241
258
  </button>
242
259
  <button type="button" class="mini-card-btn-icon" onclick="closeMiniPlayer()" title="ปิดเครื่องเล่น">
243
- <svg aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
260
+ <i class="bi bi-x-lg" aria-hidden="true" style="font-size:14px;"></i>
244
261
  </button>
245
262
  </div>
246
263
  </div>
@@ -256,7 +273,7 @@
256
273
 
257
274
  <div class="mini-card-controls-row">
258
275
  <button type="button" class="btn-mini-ctl" id="btn-mini-shuffle" onclick="toggleMiniPlayerShuffle()" title="สลับโหมดสุ่มเพลง">
259
- <svg aria-hidden="true" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="16 3 21 3 21 8"/><line x1="4" y1="20" x2="21" y2="3"/><polyline points="21 16 21 21 16 21"/><line x1="15" y1="15" x2="21" y2="21"/><line x1="4" y1="4" x2="9" y2="9"/></svg>
276
+ <i class="bi bi-shuffle" aria-hidden="true" style="font-size:15px;"></i>
260
277
  </button>
261
278
  <button type="button" class="btn-mini-ctl" onclick="prevMiniPlayerTrack()" title="เพลงก่อนหน้า">
262
279
  <svg aria-hidden="true" width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><polygon points="19 20 9 12 19 4 19 20"/><line x1="5" y1="19" x2="5" y2="5" stroke="currentColor" stroke-width="2"/></svg>
@@ -269,7 +286,7 @@
269
286
  <svg aria-hidden="true" width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><polygon points="5 4 15 12 5 20 5 4"/><line x1="19" y1="5" x2="19" y2="19" stroke="currentColor" stroke-width="2"/></svg>
270
287
  </button>
271
288
  <button type="button" class="btn-mini-ctl" id="btn-mini-repeat" onclick="toggleMiniPlayerRepeat()" title="โหมดวนซ้ำ">
272
- <svg aria-hidden="true" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg>
289
+ <i class="bi bi-repeat" aria-hidden="true" style="font-size:15px;"></i>
273
290
  </button>
274
291
  </div>
275
292
  </div>
@@ -281,7 +298,7 @@
281
298
  <circle class="mini-disc-progress-bg" cx="36" cy="36" r="34"></circle>
282
299
  <circle class="mini-disc-progress-val" id="mini-disc-progress-circle" cx="36" cy="36" r="34"></circle>
283
300
  </svg>
284
- <img id="mini-disc-thumb" class="mini-disc-thumb" src="https://img.youtube.com/vi/9AeErG03SZw/hqdefault.jpg" alt="Disc" onerror="this.onerror=null;this.src='https://img.youtube.com/vi/9AeErG03SZw/hqdefault.jpg';" />
301
+ <img id="mini-disc-thumb" class="mini-disc-thumb" src="https://img.youtube.com/vi/9AeErG03SZw/hqdefault.jpg" alt="Disc" width="32" height="32" loading="lazy" decoding="async" onerror="this.onerror=null;this.src='https://img.youtube.com/vi/9AeErG03SZw/hqdefault.jpg';" />
285
302
  <div class="mini-disc-overlay">
286
303
  <span id="mini-disc-icon"><svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="currentColor"><polygon points="6 3 20 12 6 21 6 3"/></svg></span>
287
304
  </div>
@@ -291,7 +308,7 @@
291
308
  <span class="mini-disc-pill-hint">กำลังเล่นเพลง • คลิกเพื่อขยาย</span>
292
309
  </div>
293
310
  <div class="mini-disc-expand-icon">
294
- <svg aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><polyline points="15 3 21 3 21 9"/><polyline points="9 21 3 21 3 15"/><line x1="21" y1="3" x2="14" y2="10"/><line x1="3" y1="21" x2="10" y2="14"/></svg>
311
+ <i class="bi bi-arrows-angle-expand" aria-hidden="true" style="font-size:14px;"></i>
295
312
  </div>
296
313
  </button>
297
314
  </aside>
@@ -307,7 +324,7 @@
307
324
  <div class="voice-live-orb" title="ไมโครโฟนทำงานอยู่">
308
325
  <span class="voice-orb-ring ring-1"></span>
309
326
  <span class="voice-orb-core">
310
- <svg aria-hidden="true" width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4"><path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" y1="19" x2="12" y2="23"/><line x1="8" y1="23" x2="16" y2="23"/></svg>
327
+ <i class="bi bi-mic" aria-hidden="true" style="font-size:11px;"></i>
311
328
  </span>
312
329
  </div>
313
330
  <span class="voice-live-title">กำลังฟัง...</span>
@@ -328,7 +345,7 @@
328
345
  </div>
329
346
  <div class="voice-hud-actions">
330
347
  <button type="button" class="btn-voice-mini btn-voice-discard" onclick="cancelSpeechRecognition()" title="ยกเลิกการบันทึกเสียง">
331
- <svg aria-hidden="true" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
348
+ <i class="bi bi-x-lg" aria-hidden="true" style="font-size:12px;"></i>
332
349
  <span>ยกเลิก</span>
333
350
  </button>
334
351
  <button type="button" class="btn-voice-mini btn-voice-send" id="btn-voice-send" onclick="sendVoiceQueryDirectly()" title="ส่งคำถามนี้ไปยัง AI ทันที">
@@ -355,24 +372,29 @@
355
372
  </span>
356
373
  </button>
357
374
  <div class="quick-action-menu" id="quick-action-menu" role="menu" aria-label="เครื่องมือด่วน">
358
- <button type="button" role="menuitem" onclick="handleImageUpload(); closeQuickActions()"><span class="quick-item-icon" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48"/></svg></span><span>แนบรูปภาพ / ไฟล์</span></button>
359
- <button type="button" role="menuitem" onclick="toggleSpeechRecognition(); closeQuickActions()"><span class="quick-item-icon" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" y1="19" x2="12" y2="22"/></svg></span><span>สั่งงานด้วยเสียง</span></button>
360
- <button type="button" role="menuitem" onclick="openQuizModal(); closeQuickActions()"><span class="quick-item-icon" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 9H4.5a2.5 2.5 0 0 1 0-5H6"/><path d="M18 9h1.5a2.5 2.5 0 0 0 0-5H18"/><path d="M4 22h16"/><path d="M10 14.66V17c0 .55-.47.98-.97 1.21C7.85 18.75 7 20.24 7 22"/><path d="M14 14.66V17c0 .55.47.98.97 1.21C16.15 18.75 17 20.24 17 22"/><path d="M18 2H6v7a6 6 0 0 0 12 0V2Z"/></svg></span><span>Fan Quiz Challenge</span></button>
361
- <button type="button" role="menuitem" onclick="openMusicModal(); closeQuickActions()"><span class="quick-item-icon" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 18V5l12-2v13"/><circle cx="6" cy="18" r="3"/><circle cx="18" cy="16" r="3"/></svg></span><span>คลังเพลง Jukebox</span></button>
362
- <button type="button" role="menuitem" onclick="openSettingsModal(); closeQuickActions()"><span class="quick-item-icon" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h10M18 7h2M4 17h2M10 17h10M14 4v6M7 14v6"/></svg></span><span>ตั้งค่าโมเดล AI (Model Settings)</span></button>
375
+ <button type="button" role="menuitem" onclick="handleImageUpload(); closeQuickActions()"><span class="quick-item-icon" aria-hidden="true"><i class="bi bi-paperclip" aria-hidden="true" style="font-size:16px;"></i></span><span>แนบรูปภาพ / ไฟล์</span></button>
376
+ <button type="button" role="menuitem" onclick="toggleSpeechRecognition(); closeQuickActions()"><span class="quick-item-icon" aria-hidden="true"><i class="bi bi-mic" aria-hidden="true" style="font-size:16px;"></i></span><span>สั่งงานด้วยเสียง</span></button>
377
+ <hr style="border:none; border-top:1px solid rgba(255,255,255,0.06); margin:4px 0;">
378
+ <button type="button" role="menuitem" onclick="openResearchModal(); closeQuickActions()"><span class="quick-item-icon" aria-hidden="true"><i class="bi bi-search-heart" aria-hidden="true" style="font-size:16px;"></i></span><span>🔍 วิจัยเชิงลึก (Deep Research)</span></button>
379
+ <button type="button" role="menuitem" onclick="openVerifyModal(); closeQuickActions()"><span class="quick-item-icon" aria-hidden="true"><i class="bi bi-shield-check" aria-hidden="true" style="font-size:16px;"></i></span><span>⚖️ ตรวจสอบข้อเท็จจริง (Verify)</span></button>
380
+ <button type="button" role="menuitem" onclick="openTimelineModal(); closeQuickActions()"><span class="quick-item-icon" aria-hidden="true"><i class="bi bi-clock-history" aria-hidden="true" style="font-size:16px;"></i></span><span>📅 ไทม์ไลน์อาชีพ (Timeline)</span></button>
381
+ <hr style="border:none; border-top:1px solid rgba(255,255,255,0.06); margin:4px 0;">
382
+ <button type="button" role="menuitem" onclick="openQuizModal(); closeQuickActions()"><span class="quick-item-icon" aria-hidden="true"><i class="bi bi-trophy" aria-hidden="true" style="font-size:16px;"></i></span><span>Fan Quiz Challenge</span></button>
383
+ <button type="button" role="menuitem" onclick="openMusicFromQuickActions()"><span class="quick-item-icon" aria-hidden="true"><i class="bi bi-music-note-beamed" aria-hidden="true" style="font-size:16px;"></i></span><span>คลังเพลง Jukebox</span></button>
384
+ <button type="button" role="menuitem" onclick="window.location.href='/settings'; closeQuickActions()"><span class="quick-item-icon" aria-hidden="true"><i class="bi bi-sliders" aria-hidden="true" style="font-size:16px;"></i></span><span>ตั้งค่าโมเดล AI (/settings)</span></button>
363
385
  </div>
364
386
 
365
387
  <button type="button" id="btn-attach" class="btn-input-tool" title="แนบรูปภาพ" onclick="handleImageUpload()">
366
- <svg aria-hidden="true" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48"/></svg>
388
+ <i class="bi bi-paperclip" aria-hidden="true" style="font-size:17px;"></i>
367
389
  </button>
368
390
  <button type="button" id="btn-mic" class="btn-input-tool btn-mic" title="สั่งงานด้วยเสียง" onclick="toggleSpeechRecognition()">
369
- <svg aria-hidden="true" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" y1="19" x2="12" y2="22"/></svg>
391
+ <i class="bi bi-mic" aria-hidden="true" style="font-size:17px;"></i>
370
392
  </button>
371
393
 
372
394
  <!-- Active Model Status Chip -->
373
- <button type="button" id="input-model-chip" class="input-model-chip" onclick="openSettingsModal()" title="คลิกเพื่อเปลี่ยนโมเดล AI หรือตั้งค่า">
395
+ <button type="button" id="input-model-chip" class="input-model-chip" onclick="window.location.href='/settings'" title="คลิกเพื่อเปลี่ยนโมเดล AI หรือตั้งค่า (/settings)">
374
396
  <span class="model-chip-dot" id="input-model-chip-dot" aria-hidden="true"></span>
375
- <span id="input-model-chip-icon" class="model-chip-icon">🌸</span>
397
+ <span id="input-model-chip-icon" class="model-chip-icon">•</span>
376
398
  <span id="input-model-chip-label" class="model-chip-label">Gemma 4 E4B</span>
377
399
  </button>
378
400
  </div>
@@ -380,22 +402,129 @@
380
402
  <div class="input-actions-right">
381
403
  <button type="button" id="btn-stop" class="btn-stop" title="หยุดสร้างคำตอบ" onclick="stopGeneration()" aria-label="หยุดการสร้างคำตอบ">
382
404
  <span class="btn-stop-icon">
383
- <svg aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><rect x="4" y="4" width="16" height="16" rx="3"/></svg>
405
+ <i class="bi bi-stop-fill" aria-hidden="true" style="font-size:14px;"></i>
384
406
  </span>
385
407
  </button>
386
408
  <button type="button" id="btn-send" class="btn-send btn-send-muted" title="ส่งข้อความ (Enter)" onclick="submitQuery()" aria-label="ส่งข้อความ">
387
409
  <span class="btn-send-icon">
388
- <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.3" stroke-linecap="round" stroke-linejoin="round"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>
410
+ <i class="bi bi-send" aria-hidden="true" style="font-size:18px;"></i>
389
411
  </span>
390
412
  </button>
391
413
  </div>
392
414
  </div>
393
415
  </div>
394
416
 
395
- <p class="input-disclaimer" id="input-disclaimer">🌸 Kiku Official Fan AI Assistant • ข้อมูลอาจมีความคลาดเคลื่อน โปรดอ้างอิงจากข้อมูลอย่างเป็นทางการ</p>
417
+ <p class="input-disclaimer" id="input-disclaimer">• Kiku Official Fan AI Assistant • ข้อมูลอาจมีความคลาดเคลื่อน โปรดอ้างอิงจากข้อมูลอย่างเป็นทางการ</p>
396
418
  </div>
397
419
  </main>
398
420
 
421
+ <!-- Timeline Modal -->
422
+ <div class="modal-backdrop" id="timeline-modal" role="dialog" aria-modal="true" tabindex="-1" onclick="if(event.target===this) closeTimelineModal()" onkeydown="if(event.key==='Escape') closeTimelineModal()">
423
+ <div class="modal-dialog timeline-modal-dialog">
424
+ <div class="timeline-header">
425
+ <h3>
426
+ <span style="font-size:20px;">📅</span>
427
+ <span>ไทม์ไลน์อาชีพ — จวีจิ้งอี (Career Timeline)</span>
428
+ </h3>
429
+ <div style="display:flex; gap:8px; align-items:center;">
430
+ <select id="timeline-era-filter" class="timeline-era-select" onchange="filterTimeline(this.value)">
431
+ <option value="all">ทุกยุค (All Eras)</option>
432
+ <option value="snh48">SNH48 Era</option>
433
+ <option value="solo">Solo Artist</option>
434
+ </select>
435
+ <button type="button" class="btn-close-drawer" onclick="closeTimelineModal()" title="ปิด">
436
+ <span style="font-size:16px; font-weight:700; line-height:1;">✕</span>
437
+ </button>
438
+ </div>
439
+ </div>
440
+ <div class="timeline-body" id="timeline-body">
441
+ <div class="timeline-loading">
442
+ <div class="timeline-spinner"></div>
443
+ <p>กำลังโหลดข้อมูลไทม์ไลน์...</p>
444
+ </div>
445
+ </div>
446
+ </div>
447
+ </div>
448
+
449
+ <!-- Deep Research Modal -->
450
+ <div class="modal-backdrop" id="research-modal" role="dialog" aria-modal="true" tabindex="-1" onclick="if(event.target===this) closeResearchModal()" onkeydown="if(event.key==='Escape') closeResearchModal()">
451
+ <div class="modal-dialog" style="max-width: 580px;">
452
+ <div class="modal-header">
453
+ <h3 style="display:flex; align-items:center; gap:8px;">
454
+ <span style="font-size:20px;">🔍</span>
455
+ <span>วิจัยเชิงลึก (Deep Research Engine)</span>
456
+ </h3>
457
+ <button type="button" class="btn-close-drawer" onclick="closeResearchModal()" title="ปิด">
458
+ <i class="bi bi-x-lg" aria-hidden="true" style="font-size:18px;"></i>
459
+ </button>
460
+ </div>
461
+ <div class="modal-body" style="padding: 20px 22px; display:flex; flex-direction:column; gap:16px;">
462
+ <div style="font-size: 13px; color: var(--text-muted); line-height: 1.6;">
463
+ ระบบจะระดม <strong>3 Subagent Workers</strong> ทำงานคู่ขนานกันเพื่อสำรวจคลังผลงานอย่างละเอียด ค้นหาข่าวสารและกระแสจากสื่อภายนอก พร้อมตรวจสอบข้อเท็จจริงเพื่อสร้างรายงานวิเคราะห์เชิงลึก
464
+ </div>
465
+ <div>
466
+ <label for="research-modal-input" style="display:block; font-size:12.5px; font-weight:600; margin-bottom:6px; color:var(--text);">หัวข้อหรือคำถามที่ต้องการวิจัย:</label>
467
+ <textarea id="research-modal-input" class="form-control" rows="3" style="width:100%; resize:vertical; padding:10px 14px; border-radius:12px; font-size:13.5px;" placeholder="เช่น: วิเคราะห์พัฒนาการด้านการแสดงและบทบาทเด่นของจวีจิ้งอีตั้งแต่เดบิวต์จนถึงปัจจุบัน..."></textarea>
468
+ </div>
469
+ <div>
470
+ <div style="font-size:12px; font-weight:600; color:var(--text-dim); margin-bottom:8px;">💡 หัวข้อแนะนำสำหรับการวิจัย:</div>
471
+ <div style="display:flex; flex-wrap:wrap; gap:6px;">
472
+ <button type="button" class="btn-action" style="font-size:12px; padding:4px 10px;" onclick="setResearchTopic('วิเคราะห์พัฒนาการด้านการแสดงและบทบาทเด่นของจวีจิ้งอี')">🎭 พัฒนาการด้านการแสดง</button>
473
+ <button type="button" class="btn-action" style="font-size:12px; padding:4px 10px;" onclick="setResearchTopic('รางวัลและเกียรติยศทั้งหมดที่จวีจิ้งอีได้รับในระดับประเทศและสากล')">🏆 รางวัลและเกียรติยศ</button>
474
+ <button type="button" class="btn-action" style="font-size:12px; padding:4px 10px;" onclick="setResearchTopic('บทบาทหยางไฉ่เวยและซ่างกวนจื่อในซีรีส์ฮวาเจียนเลิ่ง (In Blossom)')">🌸 เจาะลึก In Blossom</button>
475
+ <button type="button" class="btn-action" style="font-size:12px; padding:4px 10px;" onclick="setResearchTopic('ผลงานเพลง ซิงเกิลเดี่ยว และเพลงประกอบซีรีส์เด่นทั้งหมด')">🎵 ผลงานเพลงและ OST</button>
476
+ </div>
477
+ </div>
478
+ <div style="display:flex; justify-content:flex-end; gap:8px; margin-top:6px;">
479
+ <button type="button" class="btn-action" onclick="closeResearchModal()">ยกเลิก</button>
480
+ <button type="button" class="btn-action" style="background:var(--primary); color:#fff; border-color:var(--primary); font-weight:600;" onclick="submitResearchFromModal()">
481
+ <i class="bi bi-search" aria-hidden="true" style="font-size:13px; margin-right:4px;"></i>
482
+ <span>เริ่มการวิจัย (3 Workers)</span>
483
+ </button>
484
+ </div>
485
+ </div>
486
+ </div>
487
+ </div>
488
+
489
+ <!-- Verify Claim Modal -->
490
+ <div class="modal-backdrop" id="verify-modal" role="dialog" aria-modal="true" tabindex="-1" onclick="if(event.target===this) closeVerifyModal()" onkeydown="if(event.key==='Escape') closeVerifyModal()">
491
+ <div class="modal-dialog" style="max-width: 580px;">
492
+ <div class="modal-header">
493
+ <h3 style="display:flex; align-items:center; gap:8px;">
494
+ <span style="font-size:20px;">⚖️</span>
495
+ <span>ตรวจสอบข้อเท็จจริง (Fact-Check &amp; Verify)</span>
496
+ </h3>
497
+ <button type="button" class="btn-close-drawer" onclick="closeVerifyModal()" title="ปิด">
498
+ <i class="bi bi-x-lg" aria-hidden="true" style="font-size:18px;"></i>
499
+ </button>
500
+ </div>
501
+ <div class="modal-body" style="padding: 20px 22px; display:flex; flex-direction:column; gap:16px;">
502
+ <div style="font-size: 13px; color: var(--text-muted); line-height: 1.6;">
503
+ ระบบจะตรวจสอบข้ออ้างหรือข่าวลือข้าม <strong>3 แหล่งข้อมูล</strong> (แคตตาล็อกทางการ, ข่าวและสื่อโซเชียล, ตัววิเคราะห์ข้อขัดแย้ง) เพื่อสรุปคำตัดสิน (VERIFIED / FALSE / CONFLICTING / UNVERIFIED)
504
+ </div>
505
+ <div>
506
+ <label for="verify-modal-input" style="display:block; font-size:12.5px; font-weight:600; margin-bottom:6px; color:var(--text);">ข้ออ้างหรือข่าวลือที่ต้องการตรวจสอบ:</label>
507
+ <textarea id="verify-modal-input" class="form-control" rows="3" style="width:100%; resize:vertical; padding:10px 14px; border-radius:12px; font-size:13.5px;" placeholder="เช่น: จวีจิ้งอีเป็น Brand Ambassador ของเครื่องประดับ FRED Paris จริงหรือไม่..."></textarea>
508
+ </div>
509
+ <div>
510
+ <div style="font-size:12px; font-weight:600; color:var(--text-dim); margin-bottom:8px;">💡 ตัวอย่างข้ออ้างที่พบบ่อย:</div>
511
+ <div style="display:flex; flex-wrap:wrap; gap:6px;">
512
+ <button type="button" class="btn-action" style="font-size:12px; padding:4px 10px;" onclick="setVerifyClaim('จวีจิ้งอีเป็น Brand Ambassador ของ FRED Paris ในปี 2024-2026 จริงหรือไม่')">💎 แอมบาสเดอร์ FRED Paris</button>
513
+ <button type="button" class="btn-action" style="font-size:12px; padding:4px 10px;" onclick="setVerifyClaim('เพลง 0.2s เป็นซิงเกิลวันเกิดที่ปล่อยเมื่อวันที่ 18 มิถุนายน 2024')">🎂 เพลง 0.2s ปล่อยวันเกิด 2024</button>
514
+ <button type="button" class="btn-action" style="font-size:12px; padding:4px 10px;" onclick="setVerifyClaim('จวีจิ้งอีเคยเป็นพรีเซนเตอร์ของแบรนด์ TuTuCare และ Lafang')">🐰 แบรนด์ TuTuCare &amp; Lafang</button>
515
+ </div>
516
+ </div>
517
+ <div style="display:flex; justify-content:flex-end; gap:8px; margin-top:6px;">
518
+ <button type="button" class="btn-action" onclick="closeVerifyModal()">ยกเลิก</button>
519
+ <button type="button" class="btn-action" style="background:var(--primary); color:#fff; border-color:var(--primary); font-weight:600;" onclick="submitVerifyFromModal()">
520
+ <i class="bi bi-shield-check" aria-hidden="true" style="font-size:14px; margin-right:4px;"></i>
521
+ <span>ตรวจสอบข้อเท็จจริง</span>
522
+ </button>
523
+ </div>
524
+ </div>
525
+ </div>
526
+ </div>
527
+
399
528
  <div class="modal-backdrop" id="music-modal" role="dialog" aria-modal="true" tabindex="-1" onclick="if(event.target===this) closeMusicModal()" onkeydown="if(event.key==='Escape') closeMusicModal()">
400
529
  <div class="modal-dialog jukebox-modal-dialog">
401
530
  <div class="jukebox-header">
@@ -418,7 +547,7 @@
418
547
  <div class="jukebox-toolbar">
419
548
  <div class="jukebox-search-box">
420
549
  <span class="search-icon">
421
- <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.4-3.4"/></svg>
550
+ <i class="bi bi-search" aria-hidden="true" style="font-size:18px;"></i>
422
551
  </span>
423
552
  <input type="text" id="music-search-input" placeholder="ค้นหาชื่อเพลง, ซีรีส์, หรือปีที่ปล่อย (เช่น In Blossom, 2026, 叹云兮, Everyday)..." oninput="filterJukeboxList(); if(typeof toggleMusicSearchClear==='function') toggleMusicSearchClear(this);" />
424
553
  <button type="button" class="jukebox-search-clear" id="music-search-clear" onclick="clearMusicSearch()" title="ล้างการค้นหา">✕</button>
@@ -446,7 +575,7 @@
446
575
  Ju Jingyi Trivia Quiz Challenge
447
576
  </h3>
448
577
  <button type="button" class="btn-close-drawer" onclick="closeQuizModal()">
449
- <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
578
+ <i class="bi bi-x-lg" aria-hidden="true" style="font-size:18px;"></i>
450
579
  </button>
451
580
  </div>
452
581
  <div class="modal-body" id="quiz-modal-body">
@@ -459,17 +588,17 @@
459
588
  <div class="modal-dialog" style="max-width: 660px;">
460
589
  <div class="modal-header">
461
590
  <h3>
462
- <svg aria-hidden="true" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.4-3.4"/></svg>
591
+ <i class="bi bi-search" aria-hidden="true" style="font-size:20px;"></i>
463
592
  <span>ค้นหาประวัติการสนทนา (Search Chat History)</span>
464
593
  </h3>
465
594
  <button type="button" class="btn-close-drawer" onclick="closeSessionsModal()">
466
- <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
595
+ <i class="bi bi-x-lg" aria-hidden="true" style="font-size:18px;"></i>
467
596
  </button>
468
597
  </div>
469
598
  <div class="modal-body" style="padding: 18px 22px;">
470
599
  <div class="search-modal-box" style="margin-bottom: 14px; position: relative;">
471
600
  <input type="text" id="sessions-search-input" class="form-control" style="width: 100%; padding-left: 38px; padding-right: 14px; border-radius: 12px; height: 42px; font-size: 13.5px;" placeholder="ค้นหาตามชื่อแชท หรือข้อความในบทสนทนา (เช่น In Blossom, Versace, 2026)..." oninput="filterSessions(this.value)">
472
- <svg aria-hidden="true" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="position: absolute; left: 12px; top: 13px; color: var(--text-dim); pointer-events: none;"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.4-3.4"/></svg>
601
+ <i class="bi bi-search" aria-hidden="true" style="font-size:16px;position: absolute; left: 12px; top: 13px; color: var(--text-dim); pointer-events: none;"></i>
473
602
  </div>
474
603
 
475
604
  <div class="sessions-toolbar" style="display: flex; gap: 8px; margin-bottom: 14px; flex-wrap: wrap;">
@@ -478,11 +607,11 @@
478
607
  <span>สร้างแชทใหม่</span>
479
608
  </button>
480
609
  <button type="button" class="btn-action" style="justify-content:center;" onclick="exportChat()">
481
- <svg aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
610
+ <i class="bi bi-download" aria-hidden="true" style="font-size:14px;"></i>
482
611
  <span>ส่งออกประวัติ</span>
483
612
  </button>
484
613
  <button type="button" class="btn-action" style="justify-content:center; color: #ef4444;" onclick="clearAllChatSessions()">
485
- <svg aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 6h18"/><path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"/><path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"/></svg>
614
+ <i class="bi bi-trash3" aria-hidden="true" style="font-size:14px;"></i>
486
615
  <span>ล้างทั้งหมด</span>
487
616
  </button>
488
617
  </div>
@@ -497,21 +626,21 @@
497
626
  <div class="modal-dialog" style="max-width: 720px;">
498
627
  <div class="modal-header">
499
628
  <h3>
500
- <svg aria-hidden="true" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z"/></svg>
629
+ <i class="bi bi-bookmark" aria-hidden="true" style="font-size:20px;"></i>
501
630
  <span>คลังพรอมต์ &amp; บุ๊กมาร์ก (Saved Prompts &amp; Bookmarks)</span>
502
631
  </h3>
503
632
  <button type="button" class="btn-close-drawer" onclick="closeSavedPromptsModal()">
504
- <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
633
+ <i class="bi bi-x-lg" aria-hidden="true" style="font-size:18px;"></i>
505
634
  </button>
506
635
  </div>
507
636
  <div class="modal-body" style="padding: 18px 22px;">
508
637
  <div class="modal-tabs">
509
638
  <button type="button" id="tab-btn-prompts" class="modal-tab-btn active" onclick="switchSavedPromptsTab('prompts')">
510
- <svg aria-hidden="true" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z"/></svg>
639
+ <i class="bi bi-bookmark" aria-hidden="true" style="font-size:15px;"></i>
511
640
  <span>คลังพรอมต์แม่แบบ (Prompt Library)</span>
512
641
  </button>
513
642
  <button type="button" id="tab-btn-bookmarks" class="modal-tab-btn" onclick="switchSavedPromptsTab('bookmarks')">
514
- <svg aria-hidden="true" width="15" height="15" viewBox="0 0 24 24" fill="currentColor"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg>
643
+ <i class="bi bi-star" aria-hidden="true" style="font-size:15px;"></i>
515
644
  <span>คำตอบที่ปักหมุดไว้ (Bookmarked Answers)</span>
516
645
  </button>
517
646
  </div>
@@ -520,7 +649,7 @@
520
649
  <div style="display: flex; gap: 8px; margin-bottom: 12px;">
521
650
  <div style="flex: 1; position: relative;">
522
651
  <input type="text" id="prompts-search-input" class="form-control" style="width: 100%; padding-left: 36px; border-radius: 10px; height: 38px; font-size: 13px;" placeholder="ค้นหาตามชื่อพรอมต์ หรือคีย์เวิร์ด..." oninput="filterSavedPrompts(this.value)">
523
- <svg aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="position: absolute; left: 11px; top: 12px; color: var(--text-dim); pointer-events: none;"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.4-3.4"/></svg>
652
+ <i class="bi bi-search" aria-hidden="true" style="font-size:14px;position: absolute; left: 11px; top: 12px; color: var(--text-dim); pointer-events: none;"></i>
524
653
  </div>
525
654
  <button type="button" class="btn-action" onclick="openCreatePromptModal()" style="background: rgba(255,117,140,0.18); border-color: var(--primary); color: var(--primary);">
526
655
  <span>สร้างพรอมต์</span>
@@ -533,7 +662,7 @@
533
662
  <div id="tab-content-bookmarks" style="display: none;">
534
663
  <div style="margin-bottom: 12px; position: relative;">
535
664
  <input type="text" id="bookmarks-search-input" class="form-control" style="width: 100%; padding-left: 36px; border-radius: 10px; height: 38px; font-size: 13px;" placeholder="ค้นหาข้อความที่ปักหมุดไว้..." oninput="filterBookmarks(this.value)">
536
- <svg aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="position: absolute; left: 11px; top: 12px; color: var(--text-dim); pointer-events: none;"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.4-3.4"/></svg>
665
+ <i class="bi bi-search" aria-hidden="true" style="font-size:14px;position: absolute; left: 11px; top: 12px; color: var(--text-dim); pointer-events: none;"></i>
537
666
  </div>
538
667
  <div id="bookmarks-list" style="display: flex; flex-direction: column; gap: 10px; max-height: 46vh; overflow-y: auto;">
539
668
  </div>
@@ -546,10 +675,10 @@
546
675
  <div class="modal-dialog" style="max-width: 520px;">
547
676
  <div class="modal-header">
548
677
  <h3>
549
- <span>➕ บันทึกพรอมต์ใหม่ (Create Saved Prompt)</span>
678
+ <span>+ บันทึกพรอมต์ใหม่ (Create Saved Prompt)</span>
550
679
  </h3>
551
680
  <button type="button" class="btn-close-drawer" onclick="closeCreatePromptModal()">
552
- <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
681
+ <i class="bi bi-x-lg" aria-hidden="true" style="font-size:18px;"></i>
553
682
  </button>
554
683
  </div>
555
684
  <div class="modal-body" style="padding: 18px 20px;">
@@ -573,7 +702,7 @@
573
702
  <textarea id="new-prompt-text" class="form-control" rows="4" style="width: 100%; resize: vertical;" placeholder="พิมพ์ข้อความคำสั่งที่ต้องการให้ AI ตอบ..."></textarea>
574
703
  </div>
575
704
  <button type="button" class="btn-action" style="margin-top: 8px; justify-content: center; background: var(--primary); color: #fff; border: none; padding: 10px;" onclick="saveNewCustomPrompt()">
576
- <span>💾 บันทึกพรอมต์</span>
705
+ <span>• บันทึกพรอมต์</span>
577
706
  </button>
578
707
  </div>
579
708
  </div>
@@ -584,7 +713,7 @@
584
713
  <div class="command-palette-backdrop" id="command-palette-modal" onclick="handleCommandPaletteBackdrop(event)" onkeydown="if(event.key==='Escape') closeCommandPalette()" style="display:none;" role="dialog" aria-modal="true" aria-label="Command Palette" tabindex="-1">
585
714
  <div class="command-palette-box">
586
715
  <div class="command-palette-header">
587
- <svg aria-hidden="true" class="command-palette-search-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.4-3.4"/></svg>
716
+ <i class="bi bi-search command-palette-search-icon" aria-hidden="true" style="font-size:20px;"></i>
588
717
  <input type="text" id="command-palette-input" placeholder="ค้นหาฟีเจอร์, คำสั่งลัด, เพลง, หรือเครื่องมือ AI... (ESC เพื่อปิด)" oninput="filterCommandPalette(this.value)" onkeydown="handleCommandPaletteKeyDown(event)" autocomplete="off" />
589
718
  <kbd class="palette-kbd">ESC</kbd>
590
719
  </div>
@@ -602,19 +731,19 @@
602
731
  <div class="share-card-dialog">
603
732
  <div class="modal-header">
604
733
  <div class="modal-title-wrap">
605
- <span class="modal-spark">🌸</span>
734
+ <span class="modal-spark"><i class="bi bi-stars" aria-hidden="true"></i></span>
606
735
  <h3>สร้างการ์ดแชร์บทสนทนา (Share Card)</h3>
607
736
  </div>
608
- <button type="button" class="btn-close-drawer" onclick="closeShareCardModal()" aria-label="ปิด"><svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></button>
737
+ <button type="button" class="btn-close-drawer" onclick="closeShareCardModal()" aria-label="ปิด"><i class="bi bi-x-lg" aria-hidden="true" style="font-size:18px;"></i></button>
609
738
  </div>
610
739
  <div class="share-card-preview-area" id="share-card-canvas-container"></div>
611
740
  <div class="share-card-actions">
612
741
  <button type="button" class="btn-share-download" onclick="downloadShareCardImage(this)">
613
- <svg aria-hidden="true" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
742
+ <i class="bi bi-download" aria-hidden="true" style="font-size:16px;"></i>
614
743
  <span>ดาวน์โหลดรูปภาพ (PNG)</span>
615
744
  </button>
616
745
  <button type="button" class="btn-share-copy" onclick="copyShareCardToClipboard(this)">
617
- <svg aria-hidden="true" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>
746
+ <i class="bi bi-copy" aria-hidden="true" style="font-size:16px;"></i>
618
747
  <span>คัดลอกข้อความ</span>
619
748
  </button>
620
749
  </div>
@@ -626,10 +755,10 @@
626
755
  <div class="share-card-dialog" style="max-width:640px;">
627
756
  <div class="modal-header">
628
757
  <div class="modal-title-wrap">
629
- <span class="modal-spark">🌸</span>
758
+ <span class="modal-spark"><i class="bi bi-stars" aria-hidden="true"></i></span>
630
759
  <h3>สร้างการ์ดคำคม (Quote Card)</h3>
631
760
  </div>
632
- <button type="button" class="btn-close-drawer" onclick="closeQuoteCardModal()" aria-label="ปิด"><svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></button>
761
+ <button type="button" class="btn-close-drawer" onclick="closeQuoteCardModal()" aria-label="ปิด"><i class="bi bi-x-lg" aria-hidden="true" style="font-size:18px;"></i></button>
633
762
  </div>
634
763
  <div class="modal-body" style="padding:16px 20px; display:flex; flex-direction:column; align-items:center; gap:14px;">
635
764
  <canvas id="quote-canvas" width="600" height="340" style="max-width:100%; height:auto; border-radius:18px; box-shadow:0 12px 32px rgba(0,0,0,0.4); border:1px solid rgba(255,117,140,0.3);"></canvas>
@@ -643,11 +772,11 @@
643
772
  </div>
644
773
  <div class="share-card-actions">
645
774
  <button type="button" class="btn-share-download" id="btn-quote-download" onclick="downloadQuoteCard(this)">
646
- <svg aria-hidden="true" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
775
+ <i class="bi bi-download" aria-hidden="true" style="font-size:16px;"></i>
647
776
  <span>ดาวน์โหลดรูปภาพ (PNG)</span>
648
777
  </button>
649
778
  <button type="button" class="btn-share-copy" id="btn-quote-copy" onclick="copyQuoteCardImage(this)">
650
- <svg aria-hidden="true" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>
779
+ <i class="bi bi-copy" aria-hidden="true" style="font-size:16px;"></i>
651
780
  <span>คัดลอกรูปภาพ</span>
652
781
  </button>
653
782
  </div>
@@ -659,10 +788,10 @@
659
788
  <div class="modal-dialog" style="max-width:760px; max-height:85vh; overflow-y:auto;">
660
789
  <div class="modal-header">
661
790
  <div class="modal-title-wrap">
662
- <span class="modal-spark">⚔️</span>
791
+ <span class="modal-spark"><i class="bi bi-stars" aria-hidden="true"></i></span>
663
792
  <h3>เปรียบเทียบผลงานซีรีส์ &amp; เพลง (Comparison Matrix)</h3>
664
793
  </div>
665
- <button type="button" class="btn-close-drawer" onclick="closeCompareModal()" aria-label="ปิด"><svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></button>
794
+ <button type="button" class="btn-close-drawer" onclick="closeCompareModal()" aria-label="ปิด"><i class="bi bi-x-lg" aria-hidden="true" style="font-size:18px;"></i></button>
666
795
  </div>
667
796
  <div class="modal-body" id="compare-modal-body"></div>
668
797
  </div>
@@ -673,250 +802,247 @@
673
802
  <div class="modal-dialog sponsors-modal-dialog">
674
803
  <div class="modal-header">
675
804
  <div class="modal-title-wrap">
676
- <span class="modal-spark">📢</span>
805
+ <span class="modal-spark"><i class="bi bi-stars" aria-hidden="true"></i></span>
677
806
  <div>
678
807
  <h3 style="margin:0; font-size:16px; font-weight:700;">SPONSOR SPOTLIGHT</h3>
679
808
  <p style="margin:2px 0 0; font-size:12px; color:var(--text-muted);">ผู้สนับสนุนโครงการและระบบนิเวศ Kiku Agent (Matching CLI /ads)</p>
680
809
  </div>
681
810
  </div>
682
- <button type="button" class="btn-close-drawer" onclick="closeSponsorsModal()" aria-label="ปิด"><svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></button>
811
+ <button type="button" class="btn-close-drawer" onclick="closeSponsorsModal()" aria-label="ปิด"><i class="bi bi-x-lg" aria-hidden="true" style="font-size:18px;"></i></button>
683
812
  </div>
684
813
  <div class="modal-body sponsors-modal-body" id="sponsors-modal-body">
685
814
  <!-- Dynamically rendered by renderSponsorsModal() -->
686
815
  </div>
687
816
  <div class="modal-footer sponsors-modal-footer">
688
- <span>🌸 สนับสนุนการพัฒนา Open-Source AI Agent Ecosystem</span>
817
+ <span>• สนับสนุนการพัฒนา Open-Source AI Agent Ecosystem</span>
689
818
  <button type="button" class="btn-msg-action" onclick="closeSponsorsModal()" style="padding:6px 14px; border-radius:8px;">ปิด</button>
690
819
  </div>
691
820
  </div>
692
821
  </div>
693
822
 
694
- <!-- AI Engine & Model Configuration Modal Popup -->
695
- <div class="modal-backdrop" id="settings-modal" onclick="if(event.target===this) closeSettingsModal()" onkeydown="if(event.key==='Escape') closeSettingsModal()" style="display:none;" role="dialog" aria-modal="true" aria-label="AI Engine & Model Configuration" tabindex="-1">
696
- <div class="modal-dialog settings-modal-dialog">
697
- <div class="modal-header settings-modal-header">
698
- <div class="modal-title-wrap settings-heading-block">
699
- <span class="settings-kicker">Inference control</span>
700
- <h3 class="settings-modal-title">AI Engine &amp; Model Configuration</h3>
701
- <p class="settings-modal-desc">กำหนดเส้นทางโมเดล การตอบสนอง และทรัพยากรของเครื่องในที่เดียว</p>
702
- </div>
703
- <div class="settings-modal-header-actions">
704
- <button type="button" class="settings-status-pill" id="settings-status-pill" title="คลิกเพื่อซิงก์ตาม CLI / Server" onclick="resetToCliProvider()">
705
- <span class="settings-status-mark" aria-hidden="true"></span>
706
- <span id="settings-provider-badge">Auto (CLI Sync)</span>
707
- </button>
708
- <button type="button" class="btn-close-drawer settings-close-button" onclick="closeSettingsModal()" aria-label="ปิดหน้าต่าง"><svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 6 6 18M6 6l12 12"/></svg></button>
709
- </div>
710
- </div>
711
-
712
- <div class="modal-body settings-modal-body">
713
- <!-- Card 1: AI Provider & Model -->
714
- <div class="settings-glass-panel">
715
- <div class="settings-panel-header">
716
- <svg aria-hidden="true" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2v20M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"/></svg>
717
- <span>ผู้ให้บริการและโมเดล (AI Provider &amp; Model)</span>
718
- </div>
719
- <div class="settings-panel-content">
720
- <div class="form-group">
721
- <label for="cfg-provider" id="lbl-cfg-provider">AI Provider</label>
722
- <div class="form-control-wrap">
723
- <select id="cfg-provider" class="form-control" onchange="onProviderChange()">
724
- <option value="auto">ตาม CLI / Server (Auto Sync)</option>
725
- <option value="lmstudio">LM Studio (Local gemma-4-e4b / Qwen)</option>
726
- <option value="vllm">vLLM (Local / WSL - Port 8000)</option>
727
- <option value="custom">Custom / LAN Server (Ollama, llama.cpp, gateway)</option>
728
- <option value="gemini">Google Gemini (Gemini 3.7 Flash / Pro)</option>
729
- <option value="openai">OpenAI (GPT-4o / o1 / o3)</option>
730
- <option value="groq">Groq (Llama 3.3 70B Fast)</option>
731
- <option value="deepseek">DeepSeek AI (V3 / R1)</option>
732
- <option value="openrouter">OpenRouter (Unified Gateway)</option>
733
- </select>
734
- </div>
823
+ <div class="modal-backdrop" id="gallery-picker-modal" role="dialog" aria-modal="true" aria-label="เลือกภาพแกลเลอรี" tabindex="-1" onclick="if(event.target===this) closeHeroGalleryPicker()" onkeydown="if(event.key==='Escape') closeHeroGalleryPicker()" style="display:none;">
824
+ <div class="modal-dialog gallery-picker-dialog">
825
+ <div class="modal-header">
826
+ <div class="modal-title-wrap">
827
+ <span class="modal-spark"><i class="bi bi-stars" aria-hidden="true"></i></span>
828
+ <div>
829
+ <h3 id="gallery-picker-title">VISUAL ARCHIVE GALLERY</h3>
830
+ <p id="gallery-picker-desc">เลือกภาพเพื่อใส่ในตำแหน่ง: <strong id="gallery-picker-target-slot">สล็อตหลัก (Primary)</strong> หรือลากรูปไปวางที่กรอบภาพได้โดยตรง</p>
831
+ </div>
832
+ </div>
833
+ <button type="button" class="btn-close-drawer" onclick="closeHeroGalleryPicker()" aria-label="ปิด">
834
+ <i class="bi bi-x-lg" aria-hidden="true" style="font-size:18px;"></i>
835
+ </button>
836
+ </div>
837
+ <div class="gallery-picker-controls">
838
+ <div class="gallery-picker-categories" id="gallery-picker-categories">
839
+ <button type="button" class="gallery-picker-cat-btn active" data-category="all" onclick="filterGalleryPickerCategory('all')">ทั้งหมด</button>
840
+ <button type="button" class="gallery-picker-cat-btn" data-category="weibo-update" onclick="filterGalleryPickerCategory('weibo-update')">อัปเดต Weibo</button>
841
+ <button type="button" class="gallery-picker-cat-btn" data-category="drama-poster" onclick="filterGalleryPickerCategory('drama-poster')">ซีรีส์ &amp; ละคร</button>
842
+ <button type="button" class="gallery-picker-cat-btn" data-category="commercial-brand" onclick="filterGalleryPickerCategory('commercial-brand')">แบรนด์ &amp; พรีเซนเตอร์</button>
843
+ <button type="button" class="gallery-picker-cat-btn" data-category="fashion-magazine" onclick="filterGalleryPickerCategory('fashion-magazine')">แฟชั่น &amp; นิตยสาร</button>
844
+ <button type="button" class="gallery-picker-cat-btn" data-category="stage-concert" onclick="filterGalleryPickerCategory('stage-concert')">สเตจ &amp; คอนเสิร์ต</button>
845
+ <button type="button" class="gallery-picker-cat-btn" data-category="red-carpet" onclick="filterGalleryPickerCategory('red-carpet')">พรมแดง &amp; กาล่า</button>
846
+ <button type="button" class="gallery-picker-cat-btn" data-category="hanfu-aesthetic" onclick="filterGalleryPickerCategory('hanfu-aesthetic')">ชุดจีนโบราณ &amp; กู่เฟิง</button>
847
+ </div>
848
+ <div class="gallery-picker-search-bar">
849
+ <input type="text" id="gallery-picker-search" placeholder="ค้นหาภาพตามชื่อผลงาน ลุค หรือแบรนด์..." aria-label="ค้นหาภาพแกลเลอรี" oninput="handleGallerySearchInput(this.value)">
850
+ </div>
851
+ </div>
852
+ <div class="modal-body gallery-picker-body" id="gallery-picker-body">
853
+ <div class="gallery-picker-grid" id="gallery-picker-grid" role="list"></div>
854
+ </div>
855
+ <div class="modal-footer gallery-picker-footer">
856
+ <div class="gallery-picker-footer-tip">
857
+ <span>[Notice] คลิกที่รูปภาพเพื่อเลือกใส่สล็อต หรือลากรูปไปวางที่กรอบภาพหน้าแรก</span>
858
+ </div>
859
+ <div class="gallery-picker-footer-actions">
860
+ <button type="button" class="btn-msg-action" onclick="resetHeroImages()" title="รีเซ็ตภาพเป็นค่าเริ่มต้น">รีเซ็ตภาพเริ่มต้น</button>
861
+ <button type="button" class="btn-msg-action" onclick="closeHeroGalleryPicker()">ปิด</button>
862
+ </div>
863
+ </div>
864
+ </div>
865
+ </div>
866
+
867
+ <!-- MCP Server & Tools Hub Modal -->
868
+ <div class="modal-backdrop" id="mcp-tools-modal" onclick="if(event.target===this)closeMcpToolsModal()" onkeydown="if(event.key==='Escape')closeMcpToolsModal()" style="display:none;" role="dialog" aria-modal="true" aria-label="MCP Server and Tools Catalog" tabindex="-1">
869
+ <div class="modal-dialog mcp-modal-dialog">
870
+ <div class="modal-header mcp-modal-header">
871
+ <div class="modal-title-wrap">
872
+ <span class="modal-spark mcp-modal-spark"><i class="bi bi-cpu" aria-hidden="true"></i></span>
873
+ <div>
874
+ <div style="display:flex; align-items:center; gap:8px; flex-wrap:wrap;">
875
+ <h3 style="margin:0; font-size:16px; font-weight:700;">MCP SERVER &amp; TOOLS ECOSYSTEM</h3>
876
+ <span class="mcp-status-badge mcp-online" id="mcp-server-live-indicator">
877
+ <span class="mcp-dot-pulse"></span> ONLINE
878
+ </span>
735
879
  </div>
736
- <div class="form-group">
737
- <label for="cfg-model" id="lbl-cfg-model">Model Name / ID</label>
738
- <div class="form-control-wrap">
739
- <input type="text" id="cfg-model" class="form-control" placeholder="google/gemma-4-e4b" value="google/gemma-4-e4b" onchange="autoSaveSettings()">
740
- </div>
880
+ <p style="margin:2px 0 0; font-size:12px; color:var(--text-muted);">Model Context Protocol 2025-11-25 • Streamable HTTP • System Tools Catalog</p>
881
+ </div>
882
+ </div>
883
+ <button type="button" class="btn-close-drawer" onclick="closeMcpToolsModal()" aria-label="ปิด"><i class="bi bi-x-lg" aria-hidden="true" style="font-size:18px;"></i></button>
884
+ </div>
885
+
886
+ <!-- Modal Tab Navigation -->
887
+ <div class="mcp-modal-tabs">
888
+ <button type="button" class="mcp-tab-btn active" id="mcp-tab-btn-status" data-mcp-tab="status" onclick="switchMcpModalTab('status')">
889
+ <i class="bi bi-activity"></i> Overview &amp; Status
890
+ </button>
891
+ <button type="button" class="mcp-tab-btn" id="mcp-tab-btn-tools" data-mcp-tab="tools" onclick="switchMcpModalTab('tools')">
892
+ <i class="bi bi-tools"></i> Tools Catalog (<span id="mcp-modal-tools-count">...</span>)
893
+ </button>
894
+ <button type="button" class="mcp-tab-btn" id="mcp-tab-btn-config" data-mcp-tab="config" onclick="switchMcpModalTab('config')">
895
+ <i class="bi bi-code-slash"></i> Client Configs (10 ค่าย AI &amp; IDEs)
896
+ </button>
897
+ </div>
898
+
899
+ <!-- Modal Body Panes -->
900
+ <div class="modal-body mcp-modal-body" id="mcp-modal-body">
901
+ <!-- Tab 1: Status & Overview -->
902
+ <div class="mcp-tab-pane active" id="mcp-pane-status">
903
+ <!-- Status Grid -->
904
+ <div class="mcp-status-grid">
905
+ <div class="mcp-stat-card">
906
+ <div class="mcp-stat-label">MCP Server Endpoint</div>
907
+ <div class="mcp-stat-value code-font" id="mcp-stat-endpoint">/mcp</div>
908
+ <div class="mcp-stat-desc">Streamable HTTP (POST /mcp)</div>
741
909
  </div>
742
- <div class="form-group">
743
- <label for="cfg-baseurl" id="lbl-cfg-baseurl">API Base URL</label>
744
- <div class="form-control-wrap">
745
- <input type="text" id="cfg-baseurl" class="form-control" placeholder="http://127.0.0.1:8000/v1" onchange="autoSaveSettings()">
746
- </div>
747
- <small class="form-hint" id="cfg-baseurl-help">LM Studio: :1234, vLLM: :8000 หรือ URL สำหรับ WSL/Network</small>
910
+ <div class="mcp-stat-card">
911
+ <div class="mcp-stat-label">Protocol Version</div>
912
+ <div class="mcp-stat-value" id="mcp-stat-protocol">2025-11-25</div>
913
+ <div class="mcp-stat-desc">Model Context Protocol (Compat 2024-11-05)</div>
748
914
  </div>
749
- <div class="form-group lan-scan-group">
750
- <label for="lan-scan-results" id="lbl-lan-scan">LAN Discovery — ค้นหา LM Server ในเครือข่าย</label>
751
- <div class="lan-scan-row">
752
- <button type="button" id="btn-lan-scan" class="btn-sync-cli" onclick="scanLanEndpoints()" title="สแกนหา LM Studio / vLLM / Ollama ในเครือข่ายและแสดงรายชื่อโมเดล">
753
- <svg aria-hidden="true" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="2"/><path d="M16.24 7.76a6 6 0 0 1 0 8.49m-8.48-.01a6 6 0 0 1 0-8.49m11.31-2.82a10 10 0 0 1 0 14.14m-14.14 0a10 10 0 0 1 0-14.14"/></svg>
754
- <span id="lan-scan-label">Scan LAN</span>
755
- </button>
756
- <small class="form-hint lan-scan-status" id="lan-scan-status"></small>
757
- </div>
758
- <input type="text" id="lan-scan-targets" class="form-control lan-scan-targets" placeholder="ระบุวงเอง (เว้นว่าง = อัตโนมัติ) เช่น 192.168.0.0/24, 10.0.0.1-10.0.0.50" onkeydown="if(event.key==='Enter'){event.preventDefault();scanLanEndpoints();}">
759
- <small class="form-hint">รองรับ CIDR (192.168.0.0/24), ช่วง IP (10.0.0.1-10.0.0.50), IP เดี่ยว — คั่นด้วยเครื่องหมายจุลภาค</small>
760
- <div id="lan-scan-results" class="lan-scan-results" hidden></div>
915
+ <div class="mcp-stat-card">
916
+ <div class="mcp-stat-label">System Tools Ready</div>
917
+ <div class="mcp-stat-value highlight-purple" id="mcp-stat-tools">68+</div>
918
+ <div class="mcp-stat-desc">Callable by Web Chat &amp; External Agents</div>
761
919
  </div>
762
- <div class="settings-quick-sync-row">
763
- <button type="button" class="btn-sync-cli" onclick="resetToCliProvider()" title="รีเซ็ตกลับไปใช้โมเดลตามที่ CLI / Server กำหนด">
764
- <svg aria-hidden="true" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 11a8.1 8.1 0 0 0-15.5-2M4 4v5h5M4 13a8.1 8.1 0 0 0 15.5 2M20 20v-5h-5"/></svg>
765
- <span>Use CLI defaults</span>
766
- </button>
920
+ <div class="mcp-stat-card">
921
+ <div class="mcp-stat-label">External MCP Bridge</div>
922
+ <div class="mcp-stat-value" id="mcp-stat-clients">Active</div>
923
+ <div class="mcp-stat-desc">Web Chat can invoke MCP tools</div>
767
924
  </div>
768
925
  </div>
769
- </div>
770
926
 
771
- <!-- Card 2: Security & Inference Parameters -->
772
- <div class="settings-glass-panel">
773
- <div class="settings-panel-header">
774
- <svg aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
775
- <span>ความปลอดภัยและพารามิเตอร์ (Security &amp; Inference)</span>
776
- </div>
777
- <div class="settings-panel-content">
778
- <div class="form-group" id="group-cfg-apikey">
779
- <label for="cfg-apikey" id="lbl-cfg-apikey">Cloud API Key</label>
780
- <form class="form-control-wrap with-toggle" autocomplete="off" onsubmit="return false;" style="margin:0;">
781
- <input type="text" id="cfg-apikey-username" name="username" autocomplete="username" value="kiku-cloud-user" hidden readonly tabindex="-1" aria-hidden="true" style="display:none;">
782
- <input type="password" id="cfg-apikey" name="kiku-cloud-apikey" class="form-control" placeholder="ระบุ API Key (เว้นว่างหากใช้ตาม CLI / Local)" autocomplete="new-password" spellcheck="false" autocapitalize="off" onchange="autoSaveSettings()">
783
- <button type="button" id="btn-toggle-apikey-vis" class="btn-input-icon" onclick="toggleApiKeyVisibility()" title="แสดง/ซ่อน API Key">
784
- <svg aria-hidden="true" id="eye-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
785
- </button>
786
- </form>
787
- <div id="cfg-apikey-help" class="form-help-text">เก็บไว้ในหน่วยความจำของเบราว์เซอร์สำหรับเซสชันนี้เท่านั้น</div>
927
+ <!-- Live Endpoint Banner -->
928
+ <div class="mcp-endpoint-banner">
929
+ <div class="mcp-endpoint-info">
930
+ <span class="mcp-method-badge">POST</span>
931
+ <code class="mcp-url-code" id="mcp-full-url-display">http://localhost:3002/mcp</code>
788
932
  </div>
789
-
790
- <div class="form-group">
791
- <label for="cfg-thinking" id="lbl-cfg-thinking">Thinking Mode</label>
792
- <div class="form-control-wrap">
793
- <select id="cfg-thinking" class="form-control" onchange="autoSaveSettings()">
794
- <option value="show">แสดงทั้งหมด (Deep Thinking)</option>
795
- <option value="collapse">ย่อเริ่มต้น (Auto Collapse)</option>
796
- <option value="hide">ซ่อนทั้งหมด (Direct Answer)</option>
797
- </select>
798
- </div>
933
+ <div class="mcp-endpoint-actions">
934
+ <button type="button" class="btn-copy-sm" onclick="copyMcpUrl(this)">
935
+ <i class="bi bi-clipboard"></i> Copy URL
936
+ </button>
937
+ <button type="button" class="btn-copy-sm" onclick="testMcpServerHealth(this)">
938
+ <i class="bi bi-shield-check"></i> Test Ping
939
+ </button>
799
940
  </div>
941
+ </div>
800
942
 
801
- <div class="form-group">
802
- <div class="label-with-badge">
803
- <label for="cfg-temperature" id="lbl-cfg-temp">Creativity (Temp)</label>
804
- <span class="temp-badge" id="temp-val">0.7</span>
805
- </div>
806
- <div class="form-control-wrap slider-wrap">
807
- <input type="range" id="cfg-temperature" min="0" max="1" step="0.05" value="0.7" class="form-slider" oninput="onTemperatureInput(this)">
808
- </div>
809
- </div>
943
+ <!-- Features summary -->
944
+ <div class="mcp-features-box">
945
+ <h4 style="margin:0 0 8px; font-size:13px; font-weight:700; color:var(--text);">✨ ความสามารถของระบบ Kiku MCP &amp; Web Chat</h4>
946
+ <ul class="mcp-features-list">
947
+ <li><strong>Two-Way MCP Support:</strong> Kiku ให้บริการเป็น <em>MCP Server</em> สำหรับ Claude Desktop/Cursor และในขณะเดียวกัน Web Chatbot ก็ทำหน้าที่เป็น <em>MCP Client</em> ที่สามารถเรียกใช้ Tools ภายนอกได้</li>
948
+ <li><strong>Zero-Key Autonomous Tools:</strong> มีเครื่องมือค้นหาเว็บ (DuckDuckGo, SearXNG, Jina), ถอดรหัสชาร์เซ็ตไทย-จีน, วิเคราะห์ข่าว, ค้นหารูปภาพ, คลังผลงานจวีจิ้งอีครบถ้วน</li>
949
+ <li><strong>Streamable HTTP Protocol:</strong> รองรับการสตรีมคำขอและผลลัพธ์ผ่าน HTTP JSON-RPC ตามมาตรฐาน MCP ล่าสุด 2025-11-25 พร้อม Backward Compatibility ถึง 2024-11-05 และระบบความปลอดภัย Loopback/Admin</li>
950
+ </ul>
810
951
  </div>
811
952
  </div>
812
953
 
813
- <!-- Card 3: Model Memory Footprint Calculator (Predictive VRAM Analyzer) -->
814
- <div class="settings-glass-panel settings-vram-panel">
815
- <div class="settings-panel-header">
816
- <svg aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 8V4H8"/><rect width="16" height="12" x="4" y="8" rx="2"/><path d="M2 14h2"/><path d="M20 14h2"/><path d="M15 13v-2"/><path d="M9 13v-2"/></svg>
817
- <span>โมเดลและหน่วยความจำ (Model Memory Footprint Calculator)</span>
818
- </div>
819
- <div class="settings-panel-content" id="vram-calc">
820
- <div id="vram-cloud-notice" class="vram-cloud-notice" style="display:none;">
821
- <div class="vram-cloud-text">
822
- <strong>โหมดแชท Cloud (<span id="vram-cloud-prov-name">Gemini</span>):</strong>
823
- <span>ประมวลผลบนเซิร์ฟเวอร์ผู้ให้บริการ ไม่ใช้ VRAM ของการ์ดจอในเครื่อง | ตารางคำนวณด้านล่างใช้สำหรับจำลอง/ประเมินโมเดล Local</span>
824
- </div>
954
+ <!-- Tab 2: Tools Catalog -->
955
+ <div class="mcp-tab-pane" id="mcp-pane-tools" style="display:none;">
956
+ <!-- Tools Filter Bar -->
957
+ <div class="mcp-tools-filter-bar">
958
+ <div class="mcp-cat-pills" id="mcp-category-pills">
959
+ <button type="button" class="mcp-cat-pill active" data-cat="ALL" onclick="filterMcpToolsCategory('ALL')">All (<span id="mcp-cat-count-all">0</span>)</button>
960
+ <button type="button" class="mcp-cat-pill" data-cat="CATALOG" onclick="filterMcpToolsCategory('CATALOG')">Catalog (<span id="mcp-cat-count-catalog">0</span>)</button>
961
+ <button type="button" class="mcp-cat-pill" data-cat="MEDIA" onclick="filterMcpToolsCategory('MEDIA')">Media (<span id="mcp-cat-count-media">0</span>)</button>
962
+ <button type="button" class="mcp-cat-pill" data-cat="RESEARCH" onclick="filterMcpToolsCategory('RESEARCH')">Search &amp; News (<span id="mcp-cat-count-research">0</span>)</button>
963
+ <button type="button" class="mcp-cat-pill" data-cat="SYSTEM" onclick="filterMcpToolsCategory('SYSTEM')">System (<span id="mcp-cat-count-system">0</span>)</button>
964
+ <button type="button" class="mcp-cat-pill" data-cat="MCP" onclick="filterMcpToolsCategory('MCP')">MCP (<span id="mcp-cat-count-mcp">0</span>)</button>
825
965
  </div>
826
- <div class="form-group">
827
- <label for="vram-model">โมเดลเป้าหมายสำหรับคำนวณ (Target Model)</label>
828
- <div class="form-control-wrap">
829
- <select id="vram-model" class="form-control" onchange="onVramModelChange()">
830
- <option value="auto" selected>Auto: active local model</option>
831
- </select>
832
- </div>
833
- <div id="vram-model-custom-wrap" style="display:none; margin-top: 8px;">
834
- <input type="text" id="vram-model-custom" class="form-control" placeholder="พิมพ์ชื่อโมเดล HuggingFace หรือ path ไฟล์ .gguf" oninput="scheduleVramEstimate()">
835
- </div>
836
- <div id="vram-model-note" class="form-help-text">เลือกโมเดล Local / Preset ที่ต้องการประเมิน VRAM</div>
966
+ <div class="mcp-search-wrap">
967
+ <i class="bi bi-search"></i>
968
+ <input type="text" id="mcp-tools-search" placeholder="ค้นหาชื่อ Tool หรือฟังก์ชัน..." oninput="onMcpToolsSearchInput(this.value)">
837
969
  </div>
838
- <div class="form-group">
839
- <label for="vram-hardware">Hardware Target</label>
840
- <div class="form-control-wrap">
841
- <select id="vram-hardware" class="form-control" onchange="updateVramEstimate()">
842
- <option value="auto">Auto-detect hardware</option>
843
- </select>
844
- </div>
845
- <div id="vram-hardware-note" class="form-help-text">กำลังตรวจจับ GPU…</div>
970
+ </div>
971
+
972
+ <!-- Tools Grid -->
973
+ <div class="mcp-tools-grid" id="mcp-tools-grid">
974
+ <div style="text-align:center; padding:30px; color:var(--text-muted);">กำลังโหลดรายการเครื่องมือ...</div>
975
+ </div>
976
+ </div>
977
+
978
+ <!-- Tab 3: Client Configs (All 10 Platforms) -->
979
+ <div class="mcp-tab-pane" id="mcp-pane-config" style="display:none;">
980
+ <!-- Selector & Controls Bar -->
981
+ <div class="mcp-client-selector-wrap">
982
+ <div class="mcp-client-chips" id="mcp-client-chips">
983
+ <!-- Dynamically populated chips -->
846
984
  </div>
847
- <div class="form-group">
848
- <div class="label-with-badge">
849
- <label for="vram-ctx">Context Length</label>
850
- <div class="vram-ctx-badge-group" style="display: inline-flex; align-items: center; gap: 6px;">
851
- <button type="button" id="btn-vram-ctx-auto" class="btn-sync-inline" onclick="resetVramCtxToAuto()" style="display: none;" title="รีเซ็ตกลับเป็นโหมด Auto">
852
- <svg aria-hidden="true" width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M20 11a8.1 8.1 0 0 0-15.5-2M4 4v5h5M4 13a8.1 8.1 0 0 0 15.5 2M20 20v-5h-5"/></svg>
853
- <span>Auto</span>
985
+
986
+ <div class="mcp-transport-toggle-bar">
987
+ <div style="display:flex; align-items:center; gap:8px;">
988
+ <span style="font-size:12px; font-weight:700; color:var(--text);"><i class="bi bi-hdd-network"></i> โหมดเชื่อมต่อ:</span>
989
+ <div class="mcp-mode-pills">
990
+ <button type="button" class="mcp-mode-btn active" id="mcp-mode-btn-http" onclick="setMcpConfigTransport('http')">
991
+ <i class="bi bi-lightning-charge"></i> Streamable HTTP (แนะนำ)
992
+ </button>
993
+ <button type="button" class="mcp-mode-btn" id="mcp-mode-btn-stdio" onclick="setMcpConfigTransport('stdio')">
994
+ <i class="bi bi-terminal"></i> Local Stdio (npx)
854
995
  </button>
855
- <span class="temp-badge" id="vram-ctx-val">Auto (16,384)</span>
856
996
  </div>
857
997
  </div>
858
- <div class="form-control-wrap slider-wrap">
859
- <input type="range" id="vram-ctx" min="1024" max="131072" step="1024" value="16384" class="form-slider" oninput="onVramCtxInput(this)">
860
- </div>
998
+ <span class="mcp-path-badge" id="mcp-config-active-file"><i class="bi bi-file-earmark-code"></i> claude_desktop_config.json</span>
861
999
  </div>
862
- <div class="vram-calc-grid">
863
- <div class="form-group">
864
- <label for="vram-quant">Quantization</label>
865
- <div class="form-control-wrap">
866
- <select id="vram-quant" class="form-control" onchange="updateVramEstimate()">
867
- <option value="fp16">FP16 / BF16 (16.0 bpw)</option>
868
- <option value="q8_0">Q8_0 / INT8 (8.0 bpw)</option>
869
- <option value="q6_k">Q6_K (6.56 bpw)</option>
870
- <option value="q5_k_m">Q5_K_M (5.5 bpw)</option>
871
- <option value="q4_k_m" selected>Q4_K_M (4.5 bpw)</option>
872
- <option value="q4_0">Q4_0 / Q4_K_S (4.2 bpw)</option>
873
- <option value="q3_k_m">Q3_K_M (3.4 bpw)</option>
874
- <option value="q2_k">Q2_K (2.6 bpw)</option>
875
- </select>
1000
+ </div>
1001
+
1002
+ <!-- Active Client Detail Box -->
1003
+ <div class="mcp-config-section" id="mcp-active-config-section">
1004
+ <div class="mcp-config-header">
1005
+ <div>
1006
+ <div style="display:flex; align-items:center; gap:8px;">
1007
+ <h4 style="margin:0; font-size:15px; font-weight:700;" id="mcp-config-client-name">Claude Desktop Configuration</h4>
1008
+ <span class="mcp-method-badge" id="mcp-config-client-badge">Streamable HTTP</span>
876
1009
  </div>
1010
+ <p style="margin:4px 0 0; font-size:12px; color:var(--text-muted);" id="mcp-config-client-desc">ใส่คอนฟิกนี้ในไฟล์ <code>claude_desktop_config.json</code> ของคุณ</p>
877
1011
  </div>
878
- <div class="form-group">
879
- <label for="vram-cache">Cache Precision</label>
880
- <div class="form-control-wrap">
881
- <select id="vram-cache" class="form-control" onchange="updateVramEstimate()">
882
- <option value="16" selected>FP16 (16-bit)</option>
883
- <option value="8">Q8_0 (8-bit)</option>
884
- </select>
885
- </div>
1012
+ <div style="display:flex; gap:8px;">
1013
+ <button type="button" class="btn-copy-sm" id="btn-copy-active-mcp" onclick="copyActiveMcpSnippet(this)">
1014
+ <i class="bi bi-clipboard"></i> Copy Config
1015
+ </button>
886
1016
  </div>
887
1017
  </div>
888
- <div class="vram-breakdown" id="vram-breakdown">
889
- <div class="vram-row"><span>Model Weights</span><b id="vram-weights">—</b></div>
890
- <div class="vram-row"><span>KV Cache Memory</span><b id="vram-kv">—</b></div>
891
- <div class="vram-row"><span>Static Overhead</span><b id="vram-overhead">—</b></div>
892
- <div class="vram-row vram-total"><span>Total VRAM Required</span><b id="vram-total">—</b></div>
1018
+ <div id="mcp-cli-command-box" style="display:none; margin-bottom:10px; padding:9px 14px; border-radius:8px; background:rgba(56,189,248,0.08); border:1px solid rgba(56,189,248,0.25); font-size:12px; font-family:'JetBrains Mono', monospace; display:flex; justify-content:space-between; align-items:center;">
1019
+ <code id="mcp-cli-command-text" style="color:var(--accent-cyan); word-break:break-all;">claude mcp add kiku ...</code>
1020
+ <button type="button" class="btn-copy-sm" onclick="copyMcpCliCmd(this)" style="padding:2px 8px; font-size:11px; margin-left:8px;">Copy CLI</button>
893
1021
  </div>
894
- <div class="vram-gauge-wrap">
895
- <div class="vram-gauge"><div class="vram-gauge-fill" id="vram-gauge-fill" style="width:0%"></div></div>
896
- <div class="vram-gauge-meta">
897
- <span id="vram-gauge-pct">—</span>
898
- <span class="vram-status-pill vram-zone-unknown" id="vram-status-pill">UNVERIFIED</span>
899
- </div>
1022
+ <pre class="mcp-code-block"><code id="mcp-code-active-preview">...</code></pre>
1023
+ </div>
1024
+
1025
+ <!-- All 10 Supported Clients Quick Grid -->
1026
+ <div style="margin-top:18px;">
1027
+ <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:10px;">
1028
+ <h4 style="margin:0; font-size:13px; font-weight:700; color:var(--text);"><i class="bi bi-grid-3x3-gap"></i> รองรับครบทั้ง 10 ค่าย AI &amp; IDEs ในโปรเจกต์นี้</h4>
1029
+ <span style="font-size:11.5px; color:var(--text-muted);">คลิก 'ดู' เพื่อเปลี่ยนค่าย หรือคลิก Copy ได้ทันที</span>
1030
+ </div>
1031
+ <div class="mcp-clients-grid" id="mcp-all-clients-grid">
1032
+ <!-- Dynamically populated cards for all 10 clients -->
900
1033
  </div>
901
- <div id="vram-remediation" class="form-help-text vram-remediation"></div>
902
- <label class="vram-override-row" id="vram-override-row" style="display:none;">
903
- <input type="checkbox" id="vram-override" onchange="onVramOverrideChange()">
904
- <span>Allow CPU offloading. This avoids an out-of-memory stop but adds substantial latency.</span>
905
- </label>
906
1034
  </div>
907
1035
  </div>
908
1036
  </div>
909
1037
 
910
- <div class="modal-footer settings-modal-footer">
911
- <div class="settings-modal-footer-hint">
912
- <span>Changes apply immediately and save automatically.</span>
913
- </div>
914
- <div style="display: flex; gap: 8px;">
915
- <button type="button" class="btn-primary-pill" id="settings-done-btn" onclick="closeSettingsModal()" style="min-width: 120px; justify-content: center;">
916
- <span>Close configuration</span>
917
- </button>
1038
+ <div class="modal-footer mcp-modal-footer">
1039
+ <div style="font-size:11.5px; color:var(--text-muted);">
1040
+ <span class="mcp-dot-pulse-sm"></span> Endpoint: <code style="color:var(--primary); font-family:monospace;">/mcp</code> • รองรับการเชื่อมต่อแบบไร้กุญแจ (Zero-Key)
918
1041
  </div>
1042
+ <button type="button" class="btn-msg-action" onclick="closeMcpToolsModal()" style="padding:6px 16px; border-radius:8px;">ปิด</button>
919
1043
  </div>
920
1044
  </div>
921
1045
  </div>
922
1046
 
1047
+
1048
+