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
@@ -645,6 +645,9 @@ export function formatStatusBadge(statusType) {
645
645
  return `${C.cyberCyan}${C.bold}[◆ INFO]${C.reset}`;
646
646
  case 'mcp':
647
647
  return `${C.lavender}${C.bold}[● MCP]${C.reset}`;
648
+ case 'session':
649
+ case 'session_restored':
650
+ return `\x1b[48;2;236;72;153m\x1b[38;2;24;6;16m${C.bold} ✦ SESSION RESTORED ${C.reset}`;
648
651
  default:
649
652
  return `${C.slate}${C.bold}[${String(statusType).toUpperCase()}]${C.reset}`;
650
653
  }
@@ -753,6 +756,18 @@ export const STATUS_THEMES = Object.freeze({
753
756
  bodyBg: '\x1b[48;2;10;32;46m', bodyFg: '\x1b[38;2;186;230;253m',
754
757
  icon: '◆', defaultBadge: 'INFO',
755
758
  },
759
+ session: {
760
+ badgeBg: '\x1b[48;2;236;72;153m', badgeFg: '\x1b[38;2;24;6;16m',
761
+ headerBg: '\x1b[48;2;64;18;42m', headerFg: '\x1b[38;2;253;242;248m',
762
+ bodyBg: '\x1b[48;2;42;12;28m', bodyFg: '\x1b[38;2;251;207;232m',
763
+ icon: '✦', defaultBadge: 'SESSION RESTORED',
764
+ },
765
+ session_restored: {
766
+ badgeBg: '\x1b[48;2;236;72;153m', badgeFg: '\x1b[38;2;24;6;16m',
767
+ headerBg: '\x1b[48;2;64;18;42m', headerFg: '\x1b[38;2;253;242;248m',
768
+ bodyBg: '\x1b[48;2;42;12;28m', bodyFg: '\x1b[38;2;251;207;232m',
769
+ icon: '✦', defaultBadge: 'SESSION RESTORED',
770
+ },
756
771
  });
757
772
 
758
773
  export function formatRichCardLines({
@@ -1122,61 +1137,51 @@ export function getWelcomeHeroLines() {
1122
1137
  const r = C.roseGlow;
1123
1138
  const g = C.gold;
1124
1139
  const c = C.cyberCyan;
1125
- const l = C.lavender;
1126
- const e = C.emerald;
1127
1140
  const s = C.slate;
1128
1141
  const w = C.white;
1129
1142
  const b = C.bold;
1130
1143
  const d = C.dim;
1131
1144
  const rst = C.reset;
1132
- const boxWidth = Math.min(84, Math.max(50, getFullWidth() - 4));
1133
- const compact = getFullWidth() < 120;
1134
- const headerTitle = 'Suggested Topics & Queries';
1135
- const topDashCount = Math.max(2, boxWidth - getStringDisplayWidth(headerTitle) - 6);
1145
+ const fullWidth = getFullWidth();
1146
+ const boxWidth = Math.min(80, Math.max(48, fullWidth - 4));
1136
1147
  const innerWidth = boxWidth - 2;
1148
+ const headerTitle = 'Suggested Queries';
1149
+ const topDashCount = Math.max(2, boxWidth - getStringDisplayWidth(headerTitle) - 6);
1137
1150
 
1138
1151
  const padItem = (icon, tag, text) => {
1139
1152
  const tagWidth = 14;
1140
- const tagPadded = tag + ' '.repeat(Math.max(0, tagWidth - getStringDisplayWidth(tag)));
1141
1153
  const visualContent = 2 + 2 + tagWidth + 2 + getStringDisplayWidth(text);
1142
1154
  const pad = Math.max(0, innerWidth - visualContent);
1143
1155
  return ` ${s}│${rst} ${icon} ${tag}${rst}${' '.repeat(Math.max(0, tagWidth - getStringDisplayWidth(tag)))} ${w}${text}${rst}${' '.repeat(pad)}${s}│${rst}`;
1144
1156
  };
1145
1157
 
1146
- const heroLines = compact ? [
1147
- ` ${p}██╗ ██╗██╗██╗ ██╗██╗ ██╗ █████╗ ██╗${rst}`,
1148
- ` ${r}█████═╝ ██║█████═╝ ██║ ██║ ███████║██║${rst}`,
1149
- ` ${p}██║ ██║██║██║ ██║╚██████╔╝ ██║ ██║██║${rst}`,
1158
+ const heroLines = fullWidth < 78 ? [
1159
+ ` ${p}██╗ ██╗██╗██╗ ██╗██╗ ██╗${rst}`,
1160
+ ` ${r}█████═╝ ██║█████═╝ ██║ ██║${rst}`,
1161
+ ` ${p}██║ ██║██║██║ ██║╚██████╔╝${rst}`,
1162
+ ` ${r}◆ ${b}${w}KIKU AGENT${rst} ${s}•${rst} ${d}[Sakura]${rst}`,
1150
1163
  ] : [
1151
- ` ${p}██╗ ██╗██╗██╗ ██╗██╗ ██╗ █████╗ ██╗${rst}`,
1152
- ` ${p}██║ ██╔╝██║██║ ██╔╝██║ ██║ ██╔══██╗██║${rst}`,
1153
- ` ${r}█████═╝ ██║█████═╝ ██║ ██║ ███████║██║${rst}`,
1154
- ` ${r}██╔═██╗ ██║██╔═██╗ ██║ ██║ ██╔══██╗██║${rst}`,
1155
- ` ${p}██║ ╚██╗██║██║ ╚██╗╚██████╔╝ ██║ ██║██║${rst}`,
1156
- ` ${p}╚═╝ ╚═╝╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝${rst}`,
1157
- ];
1158
- const shortcutLines = compact ? [
1159
- ` ${s}Keys: ${b}${w}[Tab]${rst} ${s}Cmds • ${b}${w}[↑/↓]${rst} ${s}Hist • ${b}${w}[F1]${rst} ${s}Help • ${b}${w}[F2]${rst} ${s}Details${rst}`,
1160
- ` ${b}${w}[F3]${rst} ${s}Think • ${b}${w}[F4]${rst} ${s}Tools • ${b}${w}[F5]${rst} ${s}Copy • ${b}${w}[Ctrl+C]${rst} ${s}Exit${rst}`,
1161
- ] : [
1162
- ` ${s}Keys: ${b}${w}[Tab]${rst} ${s}Autocomplete • ${b}${w}[↑/↓]${rst} ${s}History • ${b}${w}[PgUp/PgDn]${rst} ${s}Scroll • ${b}${w}[Ctrl+C]${rst} ${s}Exit${rst}`,
1163
- ` ${s}F-Keys: ${b}${w}[F1]${rst} ${s}Help • ${b}${w}[F2]${rst} ${s}Details • ${b}${w}[F3]${rst} ${s}Thinking • ${b}${w}[F4]${rst} ${s}Tools • ${b}${w}[F5]${rst} ${s}Copy • ${b}${w}[F6]${rst} ${s}Gallery • ${b}${w}[F7]${rst} ${s}Theme${rst}`,
1164
- ` ${s}Ctrl: ${b}${w}[Ctrl+T]${rst} ${s}Toggle Think • ${b}${w}[Ctrl+R]${rst} ${s}Retry • ${b}${w}[Ctrl+S]${rst} ${s}Save • ${b}${w}[Ctrl+G]${rst} ${s}Gallery${rst}`,
1164
+ ` ${p}██╗ ██╗██╗██╗ ██╗██╗ ██╗ ${r}█████╗ ██████╗ ███████╗███╗ ██╗████████╗${rst}`,
1165
+ ` ${p}██║ ██╔╝██║██║ ██╔╝██║ ██║ ${r}██╔══██╗██╔════╝ ██╔════╝████╗ ██║╚══██╔══╝${rst}`,
1166
+ ` ${r}█████═╝ ██║█████═╝ ██║ ██║ ${r}███████║██║ ███╗█████╗ ██╔██╗ ██║ ██║ ${rst}`,
1167
+ ` ${r}██╔═██╗ ██║██╔═██╗ ██║ ██║ ${p}██╔══██║██║ ██║██╔══╝ ██║╚██╗██║ ██║ ${rst}`,
1168
+ ` ${p}██║ ╚██╗██║██║ ╚██╗╚██████╔╝ ${p}██║ ██║╚██████╔╝███████╗██║ ╚████║ ██║ ${rst}`,
1165
1169
  ];
1166
1170
 
1171
+ const subtitle = ` ${p}🌸 ${b}${w}Ju Jingyi (鞠婧祎) AI Concierge${rst} ${s}•${rst} ${d}Interactive Terminal Agent${rst}`;
1172
+
1173
+ const shortcutLine = fullWidth < 85
1174
+ ? ` ${s}Keys: ${b}${w}[Tab]${rst} ${s}Cmds • ${b}${w}[↑/↓]${rst} ${s}Hist • ${b}${w}[F1]${rst} ${s}Help • ${b}${w}[Ctrl+C]${rst} ${s}Exit${rst}`
1175
+ : ` ${s}Keys: ${b}${w}[Tab]${rst} ${s}Autocomplete • ${b}${w}[↑/↓]${rst} ${s}History • ${b}${w}[F1]${rst} ${s}Help • ${b}${w}[F3]${rst} ${s}Think • ${b}${w}[Ctrl+C]${rst} ${s}Exit${rst}`;
1176
+
1167
1177
  return [
1168
- ...(compact ? [] : ['']),
1169
1178
  ...heroLines,
1170
- '',
1179
+ subtitle,
1171
1180
  ` ${s}╭──${rst} ${b}${g}${headerTitle}${rst} ${s}${'─'.repeat(topDashCount)}╮${rst}`,
1172
- padItem(p + '◆', '2026 Works', '"What are Ju Jingyi\'s 2026 upcoming dramas?"'),
1173
- padItem(c + '◆', 'Music & OST', '"OSTs from In Blossom & Ruyi Pavilion, /play Ginkgo"'),
1174
- padItem(e + '◆', 'Endorsements', '"Versace Global Ambassador & fashion partnerships"'),
1175
- padItem(l + '◆', 'Tools / MCP', '"@search_works 2026, /mcp list, /stats, /help"'),
1181
+ padItem(p + '◆', 'Ju Jingyi Works', '"What are Ju Jingyi\'s 2026 upcoming dramas?"'),
1182
+ padItem(c + '◆', 'Music & Tools', '"OSTs from In Blossom, /play Ginkgo, @search_works"'),
1176
1183
  ` ${s}╰${'─'.repeat(innerWidth)}╯${rst}`,
1177
- '',
1178
- ...shortcutLines,
1179
- '',
1184
+ shortcutLine,
1180
1185
  ];
1181
1186
  }
1182
1187
 
@@ -13,6 +13,8 @@ import { getGpuMetrics } from './gpuMetrics.js';
13
13
  import { listInstalledGgufs, resolveModelConfig } from './modelConfig.js';
14
14
  import { classifyHardwareTier, calculateDynamicVramBudget, HARDWARE_TIERS } from './telemetry/hardwareTiers.js';
15
15
  import { techPowerUpClient } from './telemetry/techPowerUpClient.js';
16
+ import { probeLmStudioRuntime } from './lmStudioWakeup.js';
17
+ import { getCpuMetrics } from './cpuMetrics.js';
16
18
 
17
19
  function runProcessCapture(cmd, args, timeoutMs = 2500) {
18
20
  return new Promise((resolve) => {
@@ -154,12 +156,43 @@ export async function getHardwareTarget() {
154
156
 
155
157
 
156
158
  export async function buildHardwareReport() {
157
- const [target, probe] = await Promise.all([
159
+ const [target, probe, cpu] = await Promise.all([
158
160
  getHardwareTarget(),
159
161
  getGpuMetrics().catch(() => ({ available: false })),
162
+ getCpuMetrics().catch(() => null),
160
163
  ]);
164
+
165
+ const primaryGpu = probe.available && probe.gpus?.[0] ? probe.gpus[0] : null;
166
+ const gpuName = primaryGpu?.name || target.name || '';
167
+ const vramGb = primaryGpu?.totalMb ? primaryGpu.totalMb / 1024 : (target.totalBytes ? target.totalBytes / 1024 ** 3 : 0);
168
+
169
+ let gpuSpecs = null;
170
+ try {
171
+ gpuSpecs = techPowerUpClient.disambiguateGpu(gpuName, vramGb);
172
+ } catch {}
173
+
174
+ const gpu = primaryGpu ? {
175
+ name: gpuSpecs?.name || gpuName,
176
+ vendor: primaryGpu.vendor || target.vendor || 'Unknown',
177
+ vramTotalMb: primaryGpu.totalMb ?? null,
178
+ vramUsedMb: primaryGpu.usedMb ?? null,
179
+ vramFreeMb: primaryGpu.freeMb ?? null,
180
+ vramTotalGb: vramGb ? Number(vramGb.toFixed(1)) : null,
181
+ utilizationGpu: primaryGpu.utilizationGpu ?? null,
182
+ temperatureC: primaryGpu.temperatureC ?? null,
183
+ driverVersion: primaryGpu.driverVersion ?? null,
184
+ busWidth: gpuSpecs?.busBits ?? null,
185
+ bandwidthGbps: gpuSpecs?.bandwidthGbs ?? null,
186
+ memoryType: gpuSpecs?.memoryType ?? null,
187
+ architecture: gpuSpecs?.arch ?? null,
188
+ pcieGeneration: gpuSpecs?.pcie ?? null,
189
+ source: primaryGpu.source || target.source || 'gpu-probe',
190
+ } : null;
191
+
161
192
  return {
162
193
  available: Boolean(target.available),
194
+ gpu,
195
+ cpu,
163
196
  installedModels: listInstalledGgufs(),
164
197
  target: {
165
198
  vendor: target.vendor,
@@ -242,59 +275,7 @@ function pickFirst(...values) {
242
275
 
243
276
 
244
277
 
245
- const LMSTUDIO_PROBE_TTL_MS = 15_000;
246
- const lmStudioProbeCache = new Map();
247
-
248
- export async function probeLmStudioRuntime(baseUrl = 'http://127.0.0.1:1234/v1') {
249
- const key = String(baseUrl || 'http://127.0.0.1:1234/v1');
250
- const cached = lmStudioProbeCache.get(key);
251
- if (cached) {
252
- if (cached.inFlight) return cached.inFlight;
253
- if (Date.now() - cached.fetchedAt < LMSTUDIO_PROBE_TTL_MS) return cached.data;
254
- }
255
- const entry = { fetchedAt: Date.now(), data: null, inFlight: probeLmStudioRuntimeUncached(baseUrl) };
256
- lmStudioProbeCache.set(key, entry);
257
- try {
258
- const result = await entry.inFlight;
259
- entry.data = result;
260
- entry.fetchedAt = Date.now();
261
- return result;
262
- } catch (err) {
263
- lmStudioProbeCache.delete(key);
264
- throw err;
265
- } finally {
266
- entry.inFlight = null;
267
- }
268
- }
269
-
270
- async function probeLmStudioRuntimeUncached(baseUrl = 'http://127.0.0.1:1234/v1') {
271
- const result = { reachable: false, loadedModel: null, loadedModelType: null, loadedContextLength: null, quantization: null, pendingModel: null };
272
- try {
273
- const root = String(baseUrl || 'http://127.0.0.1:1234/v1').replace(/\/v1\/?$/, '');
274
- const res = await fetch(`${root}/api/v0/models`, { signal: AbortSignal.timeout(2500) });
275
- if (!res.ok) return result;
276
- const data = await res.json();
277
- const models = Array.isArray(data?.data) ? data.data : [];
278
- if (models.length === 0) return result;
279
- result.reachable = true;
280
- const loaded = models.find(m => m.state === 'loaded' && (m.type === 'llm' || m.type === 'vlm'))
281
- || models.find(m => m.state === 'loaded');
282
- if (loaded) {
283
- result.loadedModel = loaded.id || null;
284
- result.loadedModelType = loaded.type || null;
285
- result.loadedContextLength = loaded.loaded_context_length ?? loaded.max_context_length ?? null;
286
- result.quantization = loaded.quantization || null;
287
- return result;
288
- }
289
-
290
- const pending = models.find(m => m.state === 'loading' && (m.type === 'llm' || m.type === 'vlm'))
291
- || models.find(m => m.state === 'loading');
292
- if (pending) result.pendingModel = pending.id || null;
293
- return result;
294
- } catch {
295
- return result;
296
- }
297
- }
278
+ export { probeLmStudioRuntime } from './lmStudioWakeup.js';
298
279
 
299
280
  export async function computeVramEstimate(request = {}) {
300
281
  let modelName = request.modelName || request.model || request.model_id || null;