kiku-agent 1.3.2 → 1.3.4
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.
- package/README.md +69 -12
- package/package.json +2 -1
- package/server/agent/agentCore.js +319 -46
- package/server/agent/appPaths.js +31 -0
- package/server/agent/audioPlayer.js +339 -12
- package/server/agent/autoContext.js +193 -0
- package/server/agent/catalogEntityResolver.js +170 -28
- package/server/agent/clarifyingQuestions.js +137 -35
- package/server/agent/cli.js +177 -48
- package/server/agent/cloudAdapters.js +116 -0
- package/server/agent/commandRegistry.js +409 -80
- package/server/agent/commands.js +1056 -125
- package/server/agent/config.js +1088 -690
- package/server/agent/contextCompactor.js +213 -21
- package/server/agent/cpuMetrics.js +199 -0
- package/server/agent/engineService.js +591 -0
- package/server/agent/eval/modules/evaluation/runner.js +4 -14
- package/server/agent/eval/modules/evaluation/scoring.js +15 -3
- package/server/agent/eval/modules/server/evalApi.js +5 -5
- package/server/agent/eval/modules/ui/evalUi.js +7 -4
- package/server/agent/eventBus.js +1 -0
- package/server/agent/ink/main.jsx +196 -191
- package/server/agent/jobManager.js +11 -1
- package/server/agent/lanDiscovery.js +721 -23
- package/server/agent/llmClient.js +317 -71
- package/server/agent/lmStudioWakeup.js +517 -65
- package/server/agent/locationService.js +797 -0
- package/server/agent/mcpQuizData.js +509 -0
- package/server/agent/memory/contextAllocator.js +19 -7
- package/server/agent/memory.js +3 -1
- package/server/agent/modelCompatibility.js +352 -0
- package/server/agent/modelDefaults.js +1 -0
- package/server/agent/modelManager.js +46 -2
- package/server/agent/newsWatch.js +9 -3
- package/server/agent/processManager.js +229 -0
- package/server/agent/prompts.js +174 -8
- package/server/agent/routingInterceptor.js +9 -1
- package/server/agent/sanitizer.js +41 -6
- package/server/agent/searchQueryPlanner.js +202 -0
- package/server/agent/session.js +59 -4
- package/server/agent/tests/agentFollowUps.test.js +128 -2
- package/server/agent/tests/agentMusicControl.test.js +245 -0
- package/server/agent/tests/apiRouter.test.js +1 -1
- package/server/agent/tests/autoContext.test.js +176 -0
- package/server/agent/tests/bilibiliEmbed.test.js +45 -0
- package/server/agent/tests/chatHardening.test.js +121 -0
- package/server/agent/tests/chineseWebSearchEscalation.test.js +62 -0
- package/server/agent/tests/clarifyingQuestions.test.js +33 -0
- package/server/agent/tests/cliAutomation.test.js +38 -1
- package/server/agent/tests/cloudProviders.test.js +91 -3
- package/server/agent/tests/commands.test.js +92 -3
- package/server/agent/tests/contextIntelligence.test.js +50 -3
- package/server/agent/tests/cpuMetrics.test.js +101 -0
- package/server/agent/tests/decisionAndSearchEnhancements.test.js +32 -0
- package/server/agent/tests/edgeCasesScenarios.test.js +82 -0
- package/server/agent/tests/engineService.test.js +436 -0
- package/server/agent/tests/engineUnload.test.js +94 -0
- package/server/agent/tests/envCommand.test.js +69 -0
- package/server/agent/tests/evalMetrics.test.js +8 -0
- package/server/agent/tests/fetchApi.test.js +99 -0
- package/server/agent/tests/hybridWebSearch.test.js +2 -0
- package/server/agent/tests/lanDiscovery.test.js +5 -0
- package/server/agent/tests/lanInterfaces.test.js +510 -0
- package/server/agent/tests/lmStudioWakeup.test.js +278 -0
- package/server/agent/tests/locationTool.test.js +278 -0
- package/server/agent/tests/memoryRoute.test.js +173 -0
- package/server/agent/tests/memoryUiNormalization.test.js +75 -0
- package/server/agent/tests/modelCompatibility.test.js +148 -0
- package/server/agent/tests/modelManager.test.js +32 -0
- package/server/agent/tests/musicControlUiBridge.test.js +113 -0
- package/server/agent/tests/nextGenArchitecture.test.js +4 -2
- package/server/agent/tests/openDomainPrompt.test.js +197 -0
- package/server/agent/tests/openDomainSearch.test.js +121 -0
- package/server/agent/tests/processManager.test.js +144 -0
- package/server/agent/tests/providerPersistence.test.js +10 -5
- package/server/agent/tests/quickActionsAndModals.test.js +180 -0
- package/server/agent/tests/searchQueryPlanner.test.js +108 -0
- package/server/agent/tests/securityAuditRemediation.test.js +16 -9
- package/server/agent/tests/securityAuditRemediations2.test.js +154 -0
- package/server/agent/tests/securityHardening.test.js +4 -4
- package/server/agent/tests/sessionAndCopy.test.js +39 -4
- package/server/agent/tests/sidebarControls.test.js +34 -0
- package/server/agent/tests/statefulMemory.test.js +8 -1
- package/server/agent/tests/textProtocolLoop.test.js +71 -0
- package/server/agent/tests/textToolParsing.test.js +48 -0
- package/server/agent/tests/toolRoutingRegressions.test.js +41 -0
- package/server/agent/tests/unifiedEndpoints.test.js +13 -6
- package/server/agent/tests/v110Features.test.js +1 -1
- package/server/agent/tests/vramEstimator.test.js +75 -0
- package/server/agent/tests/webChatDocs.test.js +199 -0
- package/server/agent/tests/webChatInferenceControl.test.js +298 -0
- package/server/agent/tests/webChatInspection.test.js +256 -5
- package/server/agent/tests/webChatMcp.test.js +94 -0
- package/server/agent/tests/webExtract.test.js +23 -0
- package/server/agent/tests/webSources.test.js +46 -12
- package/server/agent/textToolProtocol.js +173 -46
- package/server/agent/toolRouter.js +318 -44
- package/server/agent/tools.js +877 -96
- package/server/agent/ui.js +39 -34
- package/server/agent/vramService.js +35 -54
- package/server/agent/webSearch.js +441 -162
- package/server/agent/websearch/orchestrator.js +15 -5
- package/server/agent/websearch/resilience/cache.js +9 -2
- package/server/agent/websearch/security/ssrf.js +41 -10
- package/server/agent/youtubeAuth.js +5 -20
- package/server/apiRouter.js +5558 -4422
- package/server/mcp/data/discography.js +2 -2
- package/server/mcp/examples/antigravity.example.json +17 -0
- package/server/mcp/handler.js +8 -4
- package/server/mcp/security.js +220 -21
- package/server/mcp/server.js +2 -1
- package/server/mcp/tests/connection.test.js +14 -8
- package/server/mcp/tests/mcpKeyAuth.test.js +156 -0
- package/server/mcp/tools.js +7 -1
- package/server/supabase_migration_prefix.sql +102 -0
- package/server/supabase_schema.sql +18 -18
- package/server/web-chat/core/connection.js +179 -218
- package/server/web-chat/core/conversationContext.js +9 -2
- package/server/web-chat/core/directCatalogEngine.js +52 -28
- package/server/web-chat/core/dramaKnowledge.js +33 -22
- package/server/web-chat/core/followUpEngine.js +735 -81
- package/server/web-chat/core/futureEventGuard.js +5 -1
- package/server/web-chat/core/musicControlAction.js +70 -0
- package/server/web-chat/core/security.js +32 -21
- package/server/web-chat/core/toolInspector.js +6 -6
- package/server/web-chat/core/urlGuard.js +45 -0
- package/server/web-chat/router.js +204 -157
- package/server/web-chat/routes/chatRoute.js +885 -488
- package/server/web-chat/routes/engineRoute.js +270 -0
- package/server/web-chat/routes/exportRoute.js +1 -1
- package/server/web-chat/routes/lanDiscoveryRoute.js +17 -2
- package/server/web-chat/routes/lmStudioLoadRoute.js +172 -0
- package/server/web-chat/routes/mcpRoute.js +386 -0
- package/server/web-chat/routes/memoryRoute.js +253 -0
- package/server/web-chat/routes/providerRoute.js +49 -16
- package/server/web-chat/routes/staticRoute.js +306 -17
- package/server/web-chat/routes/statusRoute.js +194 -73
- package/server/web-chat/routes/suggestRoute.js +11 -3
- package/server/web-chat/routes/verifyRoute.js +26 -4
- package/server/web-chat/server.js +7 -6
- package/server/web-chat/ui/docsBuilder.js +3558 -0
- package/server/web-chat/ui/htmlBuilder.js +12 -0
- package/server/web-chat/ui/scripts/client.js +3401 -1302
- package/server/web-chat/ui/scripts/webchatI18n.js +155 -153
- package/server/web-chat/ui/settingsBuilder.js +7870 -0
- package/server/web-chat/ui/styles/lan-card.css +165 -0
- package/server/web-chat/ui/styles/main.css +4289 -447
- package/server/web-chat/ui/sw.js +64 -0
- package/server/web-chat/ui/templates/body.html +407 -281
- package/src/data/awardsData.js +146 -146
- package/src/data/musicVideoData.js +6 -4
- package/src/lib/vram/estimator.js +195 -19
package/server/agent/ui.js
CHANGED
|
@@ -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
|
|
1133
|
-
const
|
|
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 =
|
|
1147
|
-
` ${p}██╗ ██╗██╗██╗ ██╗██╗
|
|
1148
|
-
` ${r}█████═╝ ██║█████═╝ ██║
|
|
1149
|
-
` ${p}██║ ██║██║██║
|
|
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}██╗ ██╗██╗██╗ ██╗██╗ ██╗
|
|
1152
|
-
` ${p}██║ ██╔╝██║██║ ██╔╝██║ ██║
|
|
1153
|
-
` ${r}█████═╝ ██║█████═╝ ██║ ██║
|
|
1154
|
-
` ${r}██╔═██╗ ██║██╔═██╗ ██║ ██║
|
|
1155
|
-
` ${p}██║ ╚██╗██║██║ ╚██╗╚██████╔╝
|
|
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 + '◆', '
|
|
1173
|
-
padItem(c + '◆', 'Music &
|
|
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
|
-
|
|
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;
|