@fugood/buttress-server 2.25.0-beta.9 → 2.25.0
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 +338 -19
- package/config/sample.toml +9 -0
- package/lib/autodiscover/index.d.ts +20 -0
- package/lib/autodiscover/sign.d.ts +10 -0
- package/lib/autodiscover/types.d.ts +32 -0
- package/lib/autodiscover/udp.d.ts +22 -0
- package/lib/cli.d.ts +3 -0
- package/lib/index.d.ts +29 -0
- package/lib/index.mjs +1282 -63
- package/lib/package.d.ts +7 -0
- package/lib/routes/anthropic-messages.d.ts +55 -0
- package/lib/routes/file.d.ts +10 -0
- package/lib/routes/index.d.ts +5 -0
- package/lib/routes/info.check.d.ts +1 -0
- package/lib/routes/info.d.ts +4 -0
- package/lib/routes/llm-shared.d.ts +54 -0
- package/lib/routes/openai-compat.d.ts +17 -0
- package/lib/routes/status.d.ts +4 -0
- package/lib/services/common.d.ts +29 -0
- package/lib/services/create-llm-service.d.ts +24 -0
- package/lib/services/ggml-llm.d.ts +5 -0
- package/lib/services/ggml-stt.d.ts +26 -0
- package/lib/services/index.d.ts +39 -0
- package/lib/services/mlx-llm.d.ts +5 -0
- package/lib/services/onnx-stt.d.ts +77 -0
- package/lib/services/onnx-tts.d.ts +48 -0
- package/lib/types.d.ts +158 -0
- package/lib/utils/SessionFileManager.d.ts +16 -0
- package/lib/utils/buttressAuth.d.ts +25 -0
- package/lib/utils/config.d.ts +21 -0
- package/lib/utils/httpAuthGuard.d.ts +1 -0
- package/lib/utils/net.d.ts +6 -0
- package/lib/utils/router.d.ts +2 -0
- package/lib/utils/serialize.d.ts +2 -0
- package/lib/utils/serverCaps.d.ts +4 -0
- package/lib/utils/sessionGuard.d.ts +33 -0
- package/lib/utils/test-caps.d.ts +61 -0
- package/lib/utils/workspaceState.d.ts +21 -0
- package/package.json +10 -8
- package/public/status.html +162 -1
- package/lib/chunk-C8PTHxhX.mjs +0 -2
- package/lib/index.d.mts +0 -370
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Session } from '../types';
|
|
2
|
+
type AnyRecord = Record<string, unknown>;
|
|
3
|
+
/**
|
|
4
|
+
* Extract a session id from the `X-Buttress-Sess-Id` request header.
|
|
5
|
+
* Query-param fallback is intentionally not supported: session ids would
|
|
6
|
+
* otherwise show up in proxy access logs and browser history, and there is
|
|
7
|
+
* no transport in our supported clients that can't set custom headers.
|
|
8
|
+
*/
|
|
9
|
+
export declare const extractSessionIdFromRequest: (headers: Record<string, string | undefined> | undefined) => string | null;
|
|
10
|
+
/**
|
|
11
|
+
* Elysia `beforeHandle` guard for HTTP routes that operate on a buttress
|
|
12
|
+
* session (file upload/download). Verifies:
|
|
13
|
+
*
|
|
14
|
+
* 1. A session id is supplied via the `X-Buttress-Sess-Id` header.
|
|
15
|
+
* 2. The session exists in the in-memory map (i.e. `init` has been issued
|
|
16
|
+
* over WS for this client).
|
|
17
|
+
* 3. When the server is bound to a workspace, the request's access token
|
|
18
|
+
* identity matches the identity recorded on the session — preventing
|
|
19
|
+
* one device in a workspace from acting on another device's session.
|
|
20
|
+
*
|
|
21
|
+
* Handlers can re-extract the resolved session via `resolveGuardedSession`.
|
|
22
|
+
*/
|
|
23
|
+
export declare const buttressSessionGuard: any;
|
|
24
|
+
/**
|
|
25
|
+
* Re-resolve the session that `buttressSessionGuard` validated. Returns null
|
|
26
|
+
* only if called outside the guard's protection (programming error). Handlers
|
|
27
|
+
* should treat null as 500 / unreachable.
|
|
28
|
+
*/
|
|
29
|
+
export declare const resolveGuardedSession: (store: AnyRecord, headers: Record<string, string | undefined>) => {
|
|
30
|
+
sessionId: string;
|
|
31
|
+
session: Session;
|
|
32
|
+
} | null;
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Display model capabilities in a Markdown table format
|
|
3
|
+
* @param {Object} options - Display options
|
|
4
|
+
* @param {Array<string>} options.modelIds - Array of model repository IDs
|
|
5
|
+
* @param {Object|null} options.defaultConfig - Default configuration from TOML
|
|
6
|
+
* @returns {Promise<void>}
|
|
7
|
+
*/
|
|
8
|
+
export declare function showModelsTable({ modelIds, defaultConfig, }?: {
|
|
9
|
+
modelIds?: string[];
|
|
10
|
+
defaultConfig?: any;
|
|
11
|
+
}): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Test ggml-llm capabilities for a backend type with optional model configuration
|
|
14
|
+
* @param {Object} options - Test options
|
|
15
|
+
* @param {string|null} options.modelId - Model repository ID
|
|
16
|
+
* @param {Object|null} options.defaultConfig - Default configuration from TOML
|
|
17
|
+
* @returns {Promise<void>}
|
|
18
|
+
*/
|
|
19
|
+
export declare function testGgmlLlmCapabilities({ modelId, defaultConfig, }?: {
|
|
20
|
+
modelId?: string | null;
|
|
21
|
+
defaultConfig?: any;
|
|
22
|
+
}): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Display STT model capabilities in a Markdown table format
|
|
25
|
+
* @param {Object} options - Display options
|
|
26
|
+
* @param {Array<string>} options.modelIds - Array of model IDs (format: repo_id:filename)
|
|
27
|
+
* @param {Object|null} options.defaultConfig - Default configuration from TOML
|
|
28
|
+
* @returns {Promise<void>}
|
|
29
|
+
*/
|
|
30
|
+
export declare function showSttModelsTable({ modelIds, defaultConfig, }?: {
|
|
31
|
+
modelIds?: string[];
|
|
32
|
+
defaultConfig?: any;
|
|
33
|
+
}): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Test ggml-stt capabilities for a backend type with optional model configuration
|
|
36
|
+
* @param {Object} options - Test options
|
|
37
|
+
* @param {string|null} options.modelId - Model ID (format: repo_id:filename)
|
|
38
|
+
* @param {Object|null} options.defaultConfig - Default configuration from TOML
|
|
39
|
+
* @returns {Promise<void>}
|
|
40
|
+
*/
|
|
41
|
+
/**
|
|
42
|
+
* Display MLX model capabilities in a Markdown table format.
|
|
43
|
+
*
|
|
44
|
+
* MLX getCapabilities is a platform/python check (no per-model GGUF metadata),
|
|
45
|
+
* so the table shows hardware fit based on unified memory and model repo IDs.
|
|
46
|
+
*/
|
|
47
|
+
export declare function showMlxModelsTable({ modelIds, defaultConfig, }?: {
|
|
48
|
+
modelIds?: string[];
|
|
49
|
+
defaultConfig?: any;
|
|
50
|
+
}): Promise<void>;
|
|
51
|
+
/**
|
|
52
|
+
* Test MLX LLM capabilities for a single model with detailed output
|
|
53
|
+
*/
|
|
54
|
+
export declare function testMlxLlmCapabilities({ modelId, defaultConfig, }?: {
|
|
55
|
+
modelId?: string | null;
|
|
56
|
+
defaultConfig?: any;
|
|
57
|
+
}): Promise<void>;
|
|
58
|
+
export declare function testGgmlSttCapabilities({ modelId, defaultConfig, }?: {
|
|
59
|
+
modelId?: string | null;
|
|
60
|
+
defaultConfig?: any;
|
|
61
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface WorkspaceBinding {
|
|
2
|
+
id: string;
|
|
3
|
+
name?: string;
|
|
4
|
+
serverId: string;
|
|
5
|
+
issuerPublicKey: string;
|
|
6
|
+
kid: string;
|
|
7
|
+
boundAt: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ServerKeyPair {
|
|
10
|
+
publicKeySpki: string;
|
|
11
|
+
privateKeyPkcs8: string;
|
|
12
|
+
kid: string;
|
|
13
|
+
}
|
|
14
|
+
export interface WorkspaceState {
|
|
15
|
+
workspace: WorkspaceBinding | null;
|
|
16
|
+
serverKeyPair: ServerKeyPair | null;
|
|
17
|
+
}
|
|
18
|
+
export declare const resolveStateDir: () => string;
|
|
19
|
+
export declare const resolveStatePath: () => string;
|
|
20
|
+
export declare const loadWorkspaceState: () => WorkspaceState;
|
|
21
|
+
export declare const saveWorkspaceState: (state: WorkspaceState) => Promise<void>;
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fugood/buttress-server",
|
|
3
|
-
"version": "2.25.0
|
|
3
|
+
"version": "2.25.0",
|
|
4
4
|
"main": "lib/index.mjs",
|
|
5
|
-
"types": "lib/index.d.
|
|
5
|
+
"types": "lib/index.d.ts",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
8
8
|
"bricks-buttress": "./bin/bricks-buttress"
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
],
|
|
16
16
|
"scripts": {
|
|
17
17
|
"typecheck": "tsc --noEmit",
|
|
18
|
-
"build": "tsdown -c rolldown.config.js",
|
|
18
|
+
"build": "tsdown -c rolldown.config.js --config-loader native && tsc --noCheck --emitDeclarationOnly",
|
|
19
19
|
"prepublish": "bun run build",
|
|
20
20
|
"dev": "bun src/index.ts",
|
|
21
21
|
"start": "bun lib/index.mjs",
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@elysiajs/cors": "^1.1.1",
|
|
32
32
|
"@elysiajs/node": "^1.4.2",
|
|
33
|
-
"@fugood/llama.node": "
|
|
34
|
-
"@fugood/whisper.node": "^1.
|
|
33
|
+
"@fugood/llama.node": "1.7.11",
|
|
34
|
+
"@fugood/whisper.node": "^1.1.1",
|
|
35
35
|
"@huggingface/gguf": "^0.3.2",
|
|
36
36
|
"@iarna/toml": "^3.0.0",
|
|
37
37
|
"bytes": "^3.1.0",
|
|
@@ -39,11 +39,13 @@
|
|
|
39
39
|
"jose": "^5.9.6",
|
|
40
40
|
"ms": "^2.1.1",
|
|
41
41
|
"node-machine-id": "^1.1.12",
|
|
42
|
+
"onnxruntime-node": "1.24.3",
|
|
43
|
+
"sharp": "^0.34.1",
|
|
42
44
|
"zod": "^3.25.76"
|
|
43
45
|
},
|
|
44
46
|
"devDependencies": {
|
|
45
|
-
"tsdown": "^0.
|
|
46
|
-
"typescript": "^
|
|
47
|
+
"tsdown": "^0.22.4",
|
|
48
|
+
"typescript": "^7.0.2"
|
|
47
49
|
},
|
|
48
|
-
"gitHead": "
|
|
50
|
+
"gitHead": "a2690b315c7043b65d71f21609b65358cd50d9a4"
|
|
49
51
|
}
|
package/public/status.html
CHANGED
|
@@ -539,6 +539,48 @@
|
|
|
539
539
|
</div>
|
|
540
540
|
</div>
|
|
541
541
|
</div>
|
|
542
|
+
|
|
543
|
+
<!-- ONNX-STT Status (hidden unless active) -->
|
|
544
|
+
<div class="card" id="onnxSttCard" style="display:none">
|
|
545
|
+
<div class="card-header">
|
|
546
|
+
<span class="card-title">ONNX-STT Status</span>
|
|
547
|
+
<span class="badge badge-info" id="onnxSttGeneratorCount">0 generators</span>
|
|
548
|
+
</div>
|
|
549
|
+
<div id="onnxSttGenerators"></div>
|
|
550
|
+
<div class="section">
|
|
551
|
+
<div class="section-title collapsible" onclick="toggleSection(this)">Model Load History</div>
|
|
552
|
+
<div class="collapsible-content" id="onnxSttModelHistory">
|
|
553
|
+
<div class="empty-state">No model load history</div>
|
|
554
|
+
</div>
|
|
555
|
+
</div>
|
|
556
|
+
<div class="section">
|
|
557
|
+
<div class="section-title collapsible" onclick="toggleSection(this)">Transcription History</div>
|
|
558
|
+
<div class="collapsible-content" id="onnxSttTranscriptionHistory">
|
|
559
|
+
<div class="empty-state">No transcription history</div>
|
|
560
|
+
</div>
|
|
561
|
+
</div>
|
|
562
|
+
</div>
|
|
563
|
+
|
|
564
|
+
<!-- ONNX-TTS Status (hidden unless active) -->
|
|
565
|
+
<div class="card" id="onnxTtsCard" style="display:none">
|
|
566
|
+
<div class="card-header">
|
|
567
|
+
<span class="card-title">ONNX-TTS Status</span>
|
|
568
|
+
<span class="badge badge-info" id="onnxTtsGeneratorCount">0 generators</span>
|
|
569
|
+
</div>
|
|
570
|
+
<div id="onnxTtsGenerators"></div>
|
|
571
|
+
<div class="section">
|
|
572
|
+
<div class="section-title collapsible" onclick="toggleSection(this)">Model Load History</div>
|
|
573
|
+
<div class="collapsible-content" id="onnxTtsModelHistory">
|
|
574
|
+
<div class="empty-state">No model load history</div>
|
|
575
|
+
</div>
|
|
576
|
+
</div>
|
|
577
|
+
<div class="section">
|
|
578
|
+
<div class="section-title collapsible" onclick="toggleSection(this)">Synthesis History</div>
|
|
579
|
+
<div class="collapsible-content" id="onnxTtsSynthesisHistory">
|
|
580
|
+
<div class="empty-state">No synthesis history</div>
|
|
581
|
+
</div>
|
|
582
|
+
</div>
|
|
583
|
+
</div>
|
|
542
584
|
</div>
|
|
543
585
|
</div>
|
|
544
586
|
|
|
@@ -844,6 +886,59 @@
|
|
|
844
886
|
})
|
|
845
887
|
}
|
|
846
888
|
|
|
889
|
+
function formatBytes(bytes) {
|
|
890
|
+
if (!bytes || bytes === 0) return '-'
|
|
891
|
+
if (bytes < 1024) return bytes + ' B'
|
|
892
|
+
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB'
|
|
893
|
+
if (bytes < 1024 * 1024 * 1024) return (bytes / (1024 * 1024)).toFixed(1) + ' MB'
|
|
894
|
+
return (bytes / (1024 * 1024 * 1024)).toFixed(2) + ' GB'
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
function renderOnnxGenerators(containerId, countId, generators, label) {
|
|
898
|
+
const container = document.getElementById(containerId)
|
|
899
|
+
document.getElementById(countId).textContent = `${generators.length} generator${generators.length !== 1 ? 's' : ''}`
|
|
900
|
+
|
|
901
|
+
withScrollPreserve(container, () => {
|
|
902
|
+
if (generators.length === 0) {
|
|
903
|
+
container.innerHTML = `<div class="empty-state">No ${label} generators loaded</div>`
|
|
904
|
+
return
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
container.innerHTML = `
|
|
908
|
+
<div class="table-wrapper">
|
|
909
|
+
<div class="table-inner">
|
|
910
|
+
<table>
|
|
911
|
+
<thead>
|
|
912
|
+
<tr>
|
|
913
|
+
<th>ID</th>
|
|
914
|
+
<th>Model</th>
|
|
915
|
+
<th>DType</th>
|
|
916
|
+
<th>Provider</th>
|
|
917
|
+
<th>Device</th>
|
|
918
|
+
<th>Model Size</th>
|
|
919
|
+
<th>Pipelines</th>
|
|
920
|
+
</tr>
|
|
921
|
+
</thead>
|
|
922
|
+
<tbody>
|
|
923
|
+
${generators.map(g => `
|
|
924
|
+
<tr>
|
|
925
|
+
<td class="mono">${escapeHtml(g.id?.slice(0, 8) || '-')}</td>
|
|
926
|
+
<td>${formatModelName(g.repoId)}${g.vocoderRepoId ? '<br><span style="font-size:11px;color:var(--text-muted)">+ ' + formatModelName(g.vocoderRepoId) + '</span>' : ''}</td>
|
|
927
|
+
<td>${escapeHtml(typeof g.dtype === 'object' ? JSON.stringify(g.dtype) : g.dtype || '-')}</td>
|
|
928
|
+
<td><span class="badge ${g.provider === 'cpu' ? 'badge-info' : 'badge-success'}">${escapeHtml(g.provider || '-')}</span></td>
|
|
929
|
+
<td>${escapeHtml(g.device || '-')}</td>
|
|
930
|
+
<td>${formatBytes(g.modelBytes)}</td>
|
|
931
|
+
<td>${g.pipelines ?? 0}</td>
|
|
932
|
+
</tr>
|
|
933
|
+
`).join('')}
|
|
934
|
+
</tbody>
|
|
935
|
+
</table>
|
|
936
|
+
</div>
|
|
937
|
+
</div>
|
|
938
|
+
`
|
|
939
|
+
})
|
|
940
|
+
}
|
|
941
|
+
|
|
847
942
|
// Escape HTML
|
|
848
943
|
function escapeHtml(str) {
|
|
849
944
|
if (str == null) return ''
|
|
@@ -869,6 +964,8 @@
|
|
|
869
964
|
const llm = status.ggmlLlm || {}
|
|
870
965
|
const stt = status.ggmlStt || {}
|
|
871
966
|
const mlx = status.mlxLlm || {}
|
|
967
|
+
const onnxStt = status.onnxStt || {}
|
|
968
|
+
const onnxTts = status.onnxTts || {}
|
|
872
969
|
|
|
873
970
|
// LLM
|
|
874
971
|
renderLlmGenerators(llm.generators || [])
|
|
@@ -983,6 +1080,70 @@
|
|
|
983
1080
|
}
|
|
984
1081
|
},
|
|
985
1082
|
])
|
|
1083
|
+
|
|
1084
|
+
// ONNX-STT
|
|
1085
|
+
const hasOnnxStt = (onnxStt.generators?.length > 0) ||
|
|
1086
|
+
(onnxStt.history?.modelLoads?.length > 0) ||
|
|
1087
|
+
(onnxStt.history?.transcriptions?.length > 0)
|
|
1088
|
+
document.getElementById('onnxSttCard').style.display = hasOnnxStt ? '' : 'none'
|
|
1089
|
+
renderOnnxGenerators('onnxSttGenerators', 'onnxSttGeneratorCount', onnxStt.generators || [], 'ONNX STT')
|
|
1090
|
+
|
|
1091
|
+
renderHistory('onnxSttModelHistory', onnxStt.history?.modelLoads || [], [
|
|
1092
|
+
{ label: 'Time', render: i => `<span class="timestamp">${formatRelativeTime(i.timestamp)}</span>` },
|
|
1093
|
+
{ label: 'Model', render: i => formatModelName(i.repoId) },
|
|
1094
|
+
{ label: 'DType', render: i => escapeHtml(typeof i.dtype === 'object' ? JSON.stringify(i.dtype) : i.dtype || '-') },
|
|
1095
|
+
{ label: 'Provider', render: i => `<span class="badge ${i.provider === 'cpu' ? 'badge-info' : 'badge-success'}">${escapeHtml(i.provider || '-')}</span>` },
|
|
1096
|
+
{ label: 'Duration', render: i => `${(i.durationMs / 1000).toFixed(1)}s` },
|
|
1097
|
+
{ label: 'Status', render: i => i.success ?
|
|
1098
|
+
'<span class="badge badge-success">Success</span>' :
|
|
1099
|
+
`<span class="badge badge-error">Failed: ${escapeHtml(i.error || 'Unknown')}</span>`
|
|
1100
|
+
},
|
|
1101
|
+
])
|
|
1102
|
+
|
|
1103
|
+
renderHistory('onnxSttTranscriptionHistory', onnxStt.history?.transcriptions || [], [
|
|
1104
|
+
{ label: 'Time', render: i => `<span class="timestamp">${formatRelativeTime(i.timestamp)}</span>` },
|
|
1105
|
+
{ label: 'Model', render: i => formatModelName(i.repoId) },
|
|
1106
|
+
{ label: 'Provider', render: i => escapeHtml(i.provider || '-') },
|
|
1107
|
+
{ label: 'Segments', render: i => i.segmentCount ?? '-' },
|
|
1108
|
+
{ label: 'Text Len', render: i => i.textLength ?? '-' },
|
|
1109
|
+
{ label: 'Duration', render: i => `${(i.durationMs / 1000).toFixed(1)}s` },
|
|
1110
|
+
{ label: 'Status', render: i => i.success ?
|
|
1111
|
+
'<span class="badge badge-success">Success</span>' :
|
|
1112
|
+
`<span class="badge badge-error">Failed</span>`
|
|
1113
|
+
},
|
|
1114
|
+
])
|
|
1115
|
+
|
|
1116
|
+
// ONNX-TTS
|
|
1117
|
+
const hasOnnxTts = (onnxTts.generators?.length > 0) ||
|
|
1118
|
+
(onnxTts.history?.modelLoads?.length > 0) ||
|
|
1119
|
+
(onnxTts.history?.syntheses?.length > 0)
|
|
1120
|
+
document.getElementById('onnxTtsCard').style.display = hasOnnxTts ? '' : 'none'
|
|
1121
|
+
renderOnnxGenerators('onnxTtsGenerators', 'onnxTtsGeneratorCount', onnxTts.generators || [], 'ONNX TTS')
|
|
1122
|
+
|
|
1123
|
+
renderHistory('onnxTtsModelHistory', onnxTts.history?.modelLoads || [], [
|
|
1124
|
+
{ label: 'Time', render: i => `<span class="timestamp">${formatRelativeTime(i.timestamp)}</span>` },
|
|
1125
|
+
{ label: 'Model', render: i => formatModelName(i.repoId) },
|
|
1126
|
+
{ label: 'DType', render: i => escapeHtml(typeof i.dtype === 'object' ? JSON.stringify(i.dtype) : i.dtype || '-') },
|
|
1127
|
+
{ label: 'Provider', render: i => `<span class="badge ${i.provider === 'cpu' ? 'badge-info' : 'badge-success'}">${escapeHtml(i.provider || '-')}</span>` },
|
|
1128
|
+
{ label: 'Vocoder', render: i => i.vocoderRepoId ? formatModelName(i.vocoderRepoId) : '-' },
|
|
1129
|
+
{ label: 'Duration', render: i => `${(i.durationMs / 1000).toFixed(1)}s` },
|
|
1130
|
+
{ label: 'Status', render: i => i.success ?
|
|
1131
|
+
'<span class="badge badge-success">Success</span>' :
|
|
1132
|
+
`<span class="badge badge-error">Failed: ${escapeHtml(i.error || 'Unknown')}</span>`
|
|
1133
|
+
},
|
|
1134
|
+
])
|
|
1135
|
+
|
|
1136
|
+
renderHistory('onnxTtsSynthesisHistory', onnxTts.history?.syntheses || [], [
|
|
1137
|
+
{ label: 'Time', render: i => `<span class="timestamp">${formatRelativeTime(i.timestamp)}</span>` },
|
|
1138
|
+
{ label: 'Model', render: i => formatModelName(i.repoId) },
|
|
1139
|
+
{ label: 'Provider', render: i => escapeHtml(i.provider || '-') },
|
|
1140
|
+
{ label: 'Text Len', render: i => i.textLength ?? '-' },
|
|
1141
|
+
{ label: 'Duration', render: i => i.cached ? '<span class="badge badge-info">Cached</span>' : `${(i.durationMs / 1000).toFixed(1)}s` },
|
|
1142
|
+
{ label: 'Status', render: i => i.success ?
|
|
1143
|
+
'<span class="badge badge-success">Success</span>' :
|
|
1144
|
+
`<span class="badge badge-error">Failed</span>`
|
|
1145
|
+
},
|
|
1146
|
+
])
|
|
986
1147
|
}
|
|
987
1148
|
|
|
988
1149
|
// Fallback: Fetch status via HTTP polling
|
|
@@ -994,7 +1155,7 @@
|
|
|
994
1155
|
const response = await fetch('/buttress/status')
|
|
995
1156
|
const data = await response.json()
|
|
996
1157
|
// Direct JSON response (not tRPC wrapped)
|
|
997
|
-
if (data.ggmlLlm || data.ggmlStt || data.mlxLlm) {
|
|
1158
|
+
if (data.ggmlLlm || data.ggmlStt || data.mlxLlm || data.onnxStt || data.onnxTts) {
|
|
998
1159
|
updateUI(data)
|
|
999
1160
|
setConnectionStatus('connected')
|
|
1000
1161
|
}
|
package/lib/chunk-C8PTHxhX.mjs
DELETED