-
+
-
-
{node.name}
+
+
{node.name}
{node.labels && Object.keys(node.labels).length > 0 && (
-
+
{Object.entries(node.labels).slice(0, 3).map(([k, v]) => (
- {k}={v}
+ {k}={v}
))}
{Object.keys(node.labels).length > 3 && (
-
+
+{Object.keys(node.labels).length - 3}
)}
@@ -611,13 +590,13 @@ export default function NodeInstallPicker({
-
+
{STATUS_LABELS[node.status] || node.status}
-
+
{totalVRAM ? (
- <>{vendor && {vendor} }{totalVRAM}>
+ <>{vendor && {vendor} }{totalVRAM}>
) : totalRAM ? (
CPU · {totalRAM}
) : — }
@@ -625,11 +604,11 @@ export default function NodeInstallPicker({
{rowState?.status === 'installing' ? (
- Installing
+ Installing
) : rowState?.status === 'done' ? (
- Installed
+ Installed
) : rowState?.status === 'error' ? (
- Failed
- {rowState.error}
+ Failed
+ {rowState.error}
) : suit === 'installed' ? (
-
+
Installed
) : suit === 'override' ? (
- Override
+ Override
) : (
-
+
Compatible
)}
@@ -661,7 +640,7 @@ export default function NodeInstallPicker({
})}
{filteredNodes.length === 0 && (
-
+
No nodes match the current filters.
@@ -671,29 +650,22 @@ export default function NodeInstallPicker({
{pendingCount > 0 && (
-
- +{pendingCount} awaiting approval — approve from Nodes .
+
+ +{pendingCount} awaiting approval — approve from Nodes .
)}
{/* Mismatch confirm */}
{showMismatchConfirm && (
-
-
+
+
Installing {targetLabel.toLowerCase()} on {counts.overrides} node{counts.overrides === 1 ? '' : 's'} that don't match. Those nodes will run inference on the chosen build, not their native GPU. Continue?
-
+
setShowMismatchConfirm(false)}>
Cancel
-
+
Install on {targetLabel.replace(' build', '')}
@@ -704,20 +676,13 @@ export default function NodeInstallPicker({
{!noNodes && (
-
-
+
+
{totalAttempted > 0 ? (
<>
{doneCount} of {totalAttempted} done
{errorCount > 0 && (
- <> ·
{errorCount} failed >
+ <> ·
{errorCount} failed >
)}
>
) : (
diff --git a/core/http/react-ui/src/components/PatternListEditor.jsx b/core/http/react-ui/src/components/PatternListEditor.jsx
index a8965246cd99..e0122286ac35 100644
--- a/core/http/react-ui/src/components/PatternListEditor.jsx
+++ b/core/http/react-ui/src/components/PatternListEditor.jsx
@@ -30,14 +30,14 @@ export default function PatternListEditor({ value, onChange }) {
return (
-
+
Restricted regex: literals, […] classes, \w \d \s, ?*+{'{m,n}'}, anchors.
Each pattern must contain a fixed literal run of ≥3 characters (e.g. sk-prefix-);
. and capturing groups are not allowed. Matches report under the pattern name.
{rows.length === 0 && (
-
+
No custom patterns. Enable built-ins above, or add a pattern for an internal credential
format (e.g. tok-[A-Za-z0-9]{'{32,64}'}).
@@ -98,8 +98,7 @@ export default function PatternListEditor({ value, onChange }) {
))}
-
+
Add pattern
diff --git a/core/http/react-ui/src/components/ResourceMonitor.jsx b/core/http/react-ui/src/components/ResourceMonitor.jsx
index c4555af1daf5..ea5198e7fde3 100644
--- a/core/http/react-ui/src/components/ResourceMonitor.jsx
+++ b/core/http/react-ui/src/components/ResourceMonitor.jsx
@@ -5,7 +5,7 @@ export default function ResourceMonitor() {
const { resources, loading } = useResources()
if (loading || !resources) {
- return
Loading resources...
+ return
Loading resources...
}
const gpus = resources.gpus || []
@@ -15,8 +15,8 @@ export default function ResourceMonitor() {
return (
-
-
+
+
System Resources
@@ -48,7 +48,7 @@ export default function ResourceMonitor() {
)}
-
+
@@ -73,7 +73,7 @@ export default function ResourceMonitor() {
-
+
@@ -91,7 +91,7 @@ export default function ResourceMonitor() {
{isGpu && aggregate.gpu_count > 1 && (
Total VRAM
-
+
{formatBytes(aggregate.used_memory)} / {formatBytes(aggregate.total_memory)} ({aggregate.usage_percent?.toFixed(1)}%)
diff --git a/core/http/react-ui/src/components/RouterCandidatesEditor.jsx b/core/http/react-ui/src/components/RouterCandidatesEditor.jsx
index 5d744c8d4639..a90bc3a587d0 100644
--- a/core/http/react-ui/src/components/RouterCandidatesEditor.jsx
+++ b/core/http/react-ui/src/components/RouterCandidatesEditor.jsx
@@ -60,9 +60,8 @@ export default function RouterCandidatesEditor({ value, onChange }) {
Add candidate
@@ -95,7 +94,7 @@ function CandidateRow({ index, total, row, knownLabels, knownLabelSet, onChange,
}}
>
-
#{index + 1}
+
#{index + 1}
Add policy
@@ -79,21 +78,19 @@ function PolicyRow({ row, duplicate, onChange, onRemove }) {
}}
>
onChange((r) => ({ ...r, label: e.target.value }))}
- style={{ fontFamily: 'var(--font-mono)', fontSize: '0.8125rem' }}
title={duplicate ? 'Duplicate label — candidates won\'t be able to distinguish them' : ''}
/>
onChange((r) => ({ ...r, description: e.target.value }))}
- style={{ fontSize: '0.8125rem' }}
/>
setFocusIndex(-1) : undefined}
>
- {allOption}
+ {allOption}
{enterTarget?.type === 'all' && (
↵
)}
@@ -201,7 +201,7 @@ export default function SearchableSelect({
style={itemStyle(isActive, isFocused)}
onMouseEnter={focusIndex !== i ? () => setFocusIndex(i) : undefined}
>
- {o.label}
+ {o.label}
{o.badge && (
setUrl(e.target.value)}
- style={{ width: '100%', marginBottom: 'var(--spacing-xs)' }}
/>
setName(e.target.value)}
- style={{ width: '100%', marginBottom: 'var(--spacing-xs)' }}
/>
setAuthToken(e.target.value)}
- style={{ width: '100%', marginBottom: 'var(--spacing-xs)' }}
/>
setUseProxy(e.target.checked)} />
Use CORS proxy
-
+
setAddDialog(false)}>Cancel
Add
@@ -229,7 +226,7 @@ export default function UnifiedMCPDropdown({
checked={isActive}
onChange={() => onClientToggle(server.id)}
/>
-