import { sdk } from '../sdk' import { sparkConfigYaml } from '../fileModels/sparkConfig.yaml' const { InputSpec, Value } = sdk // This action is intentionally minimal: just the required wiring needed before // Spark Control can do anything — the two Spark node addresses and SSH users. // Every other knob (vLLM/service ports, container names, support-service hosts, // integrations, webhooks) now lives behind the ⚙ Settings gear in the dashboard // itself, which is where StartOS 0.4 expects routine config to live (and most // operators never open StartOS actions). The optional keys still exist in the // config.yaml schema (set by older versions); they're read into env at launch // and migrated into the in-app settings overlay on first boot, so nothing is // lost on upgrade — they're simply edited in the dashboard from now on. const inputSpec = InputSpec.of({ spark1_host: Value.text({ name: 'Spark 1 hostname or IP', description: 'The head node of your DGX Spark cluster — the one that has ~/spark-vllm-docker cloned and runs the vLLM container. Enter its LAN IP (recommended) or hostname.', required: true, default: null, placeholder: 'e.g. 192.168.1.10', masked: false, }), spark1_user: Value.text({ name: 'Spark 1 SSH user', description: 'The user account on Spark 1 to SSH in as — whatever you log in as when you ssh into it manually.', required: true, default: null, placeholder: 'your SSH username', masked: false, }), spark2_host: Value.text({ name: 'Spark 2 hostname or IP', description: 'The worker node of your DGX Spark cluster (also runs always-on services like Parakeet and Kokoro). Enter its LAN IP or hostname.', required: true, default: null, placeholder: 'e.g. 192.168.1.11', masked: false, }), spark2_user: Value.text({ name: 'Spark 2 SSH user', description: 'The user account on Spark 2 to SSH in as. Usually the same as Spark 1.', required: true, default: null, placeholder: 'your SSH username', masked: false, }), }) export const configureSparks = sdk.Action.withInput( 'configure-sparks', async () => ({ name: 'Configure Sparks', description: 'Set your two Spark node addresses and SSH users — the required wiring. Everything else (ports, container names, support services, integrations) is configured under ⚙ Settings in the Spark Control dashboard.', warning: null, visibility: 'enabled', allowedStatuses: 'any', group: null, }), async () => inputSpec, async ({ effects }) => { // Prefill from the saved config, but only the keys this (trimmed) form owns. const cfg = await sparkConfigYaml.read().once() if (!cfg) return null return { spark1_host: cfg.spark1_host, spark1_user: cfg.spark1_user, spark2_host: cfg.spark2_host, spark2_user: cfg.spark2_user, } }, async ({ effects, input }) => { // merge() only touches the four keys we submit, leaving any legacy optional // values already in config.yaml intact. const normalized = Object.fromEntries( Object.entries(input).map(([k, v]) => [k, v ?? '']), ) as Record await sparkConfigYaml.merge(effects, normalized) return null }, )