From a491f294831d22a14bc431c6abeef58deb45c54f Mon Sep 17 00:00:00 2001
From: LordMathis
Date: Thu, 2 Oct 2025 23:18:33 +0200
Subject: [PATCH] Add node selection functionality to InstanceSettingsCard and
define Node API
---
.../instance/InstanceSettingsCard.tsx | 52 ++++++++++++++++++-
webui/src/lib/api.ts | 15 ++++++
webui/src/schemas/instanceOptions.ts | 3 ++
3 files changed, 69 insertions(+), 1 deletion(-)
diff --git a/webui/src/components/instance/InstanceSettingsCard.tsx b/webui/src/components/instance/InstanceSettingsCard.tsx
index c85eda9..124986b 100644
--- a/webui/src/components/instance/InstanceSettingsCard.tsx
+++ b/webui/src/components/instance/InstanceSettingsCard.tsx
@@ -1,4 +1,4 @@
-import React from 'react'
+import React, { useState, useEffect } from 'react'
import type { CreateInstanceOptions } from '@/types/instance'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { Label } from '@/components/ui/label'
@@ -7,6 +7,8 @@ import AutoRestartConfiguration from '@/components/instance/AutoRestartConfigura
import NumberInput from '@/components/form/NumberInput'
import CheckboxInput from '@/components/form/CheckboxInput'
import EnvironmentVariablesInput from '@/components/form/EnvironmentVariablesInput'
+import SelectInput from '@/components/form/SelectInput'
+import { nodesApi, type NodeResponse } from '@/lib/api'
interface InstanceSettingsCardProps {
instanceName: string
@@ -25,6 +27,42 @@ const InstanceSettingsCard: React.FC = ({
onNameChange,
onChange
}) => {
+ const [nodes, setNodes] = useState([])
+ const [loadingNodes, setLoadingNodes] = useState(true)
+
+ useEffect(() => {
+ const fetchNodes = async () => {
+ try {
+ const fetchedNodes = await nodesApi.list()
+ setNodes(fetchedNodes)
+ } catch (error) {
+ console.error('Failed to fetch nodes:', error)
+ } finally {
+ setLoadingNodes(false)
+ }
+ }
+
+ fetchNodes()
+ }, [])
+
+ const nodeOptions = [
+ { value: '', label: 'Default (Main Node)' },
+ ...nodes.map(node => ({
+ value: node.name,
+ label: node.name
+ }))
+ ]
+
+ const handleNodeChange = (value: string | undefined) => {
+ if (value) {
+ onChange('nodes', [value])
+ } else {
+ onChange('nodes', undefined)
+ }
+ }
+
+ const selectedNode = formData.nodes && formData.nodes.length > 0 ? formData.nodes[0] : ''
+
return (
@@ -50,6 +88,18 @@ const InstanceSettingsCard: React.FC = ({
+ {/* Node Selection */}
+ {!loadingNodes && nodes.length > 0 && (
+
+ )}
+
{/* Auto Restart Configuration */}
apiCall("/nodes"),
+
+ // GET /nodes/{name}
+ get: (name: string) => apiCall(`/nodes/${name}`),
+};
+
// Instance API functions
export const instancesApi = {
// GET /instances
diff --git a/webui/src/schemas/instanceOptions.ts b/webui/src/schemas/instanceOptions.ts
index 0af09c1..3cbf523 100644
--- a/webui/src/schemas/instanceOptions.ts
+++ b/webui/src/schemas/instanceOptions.ts
@@ -39,6 +39,9 @@ export const CreateInstanceOptionsSchema = z.object({
// Backend configuration
backend_type: z.enum([BackendType.LLAMA_CPP, BackendType.MLX_LM, BackendType.VLLM]).optional(),
backend_options: BackendOptionsSchema.optional(),
+
+ // Node configuration
+ nodes: z.array(z.string()).optional(),
})
// Re-export types and schemas from backend files