feat(dashboard): configure services from clickable service cards

This commit is contained in:
William Valentin
2026-02-19 10:50:16 -08:00
parent 3b507d503f
commit 7a2176c15c
4 changed files with 442 additions and 7 deletions
+126
View File
@@ -419,6 +419,132 @@ const PATCHABLE_KEYS: Record<string, (config: Config, value: unknown) => boolean
config.automation.daily_briefing.model_tier = value;
return true;
},
'automation.gmail.enabled': (config, value) => {
if (typeof value !== 'boolean') {return false;}
config.automation ??= {} as Config['automation'];
config.automation.gmail ??= {} as NonNullable<Config['automation']['gmail']>;
config.automation.gmail.enabled = value;
return true;
},
'automation.gcal.enabled': (config, value) => {
if (typeof value !== 'boolean') {return false;}
config.automation ??= {} as Config['automation'];
config.automation.gcal ??= {} as NonNullable<Config['automation']['gcal']>;
config.automation.gcal.enabled = value;
return true;
},
'automation.gdocs.enabled': (config, value) => {
if (typeof value !== 'boolean') {return false;}
config.automation ??= {} as Config['automation'];
config.automation.gdocs ??= {} as NonNullable<Config['automation']['gdocs']>;
config.automation.gdocs.enabled = value;
return true;
},
'automation.gdrive.enabled': (config, value) => {
if (typeof value !== 'boolean') {return false;}
config.automation ??= {} as Config['automation'];
config.automation.gdrive ??= {} as NonNullable<Config['automation']['gdrive']>;
config.automation.gdrive.enabled = value;
return true;
},
'automation.gtasks.enabled': (config, value) => {
if (typeof value !== 'boolean') {return false;}
config.automation ??= {} as Config['automation'];
config.automation.gtasks ??= {} as NonNullable<Config['automation']['gtasks']>;
config.automation.gtasks.enabled = value;
return true;
},
'automation.heartbeat.enabled': (config, value) => {
if (typeof value !== 'boolean') {return false;}
config.automation ??= {} as Config['automation'];
config.automation.heartbeat ??= {} as Config['automation']['heartbeat'];
config.automation.heartbeat.enabled = value;
return true;
},
'automation.heartbeat.interval': (config, value) => {
if (typeof value !== 'string' || value.trim().length === 0) {return false;}
config.automation ??= {} as Config['automation'];
config.automation.heartbeat ??= {} as Config['automation']['heartbeat'];
config.automation.heartbeat.interval = value.trim();
return true;
},
'automation.heartbeat.notify_cooldown': (config, value) => {
if (typeof value !== 'string' || value.trim().length === 0) {return false;}
config.automation ??= {} as Config['automation'];
config.automation.heartbeat ??= {} as Config['automation']['heartbeat'];
config.automation.heartbeat.notify_cooldown = value.trim();
return true;
},
'automation.heartbeat.failure_threshold': (config, value) => {
if (typeof value !== 'number' || !Number.isFinite(value) || value < 1 || value > 10) {return false;}
config.automation ??= {} as Config['automation'];
config.automation.heartbeat ??= {} as Config['automation']['heartbeat'];
config.automation.heartbeat.failure_threshold = Math.floor(value);
return true;
},
'automation.heartbeat.disk_threshold_mb': (config, value) => {
if (typeof value !== 'number' || !Number.isFinite(value) || value < 10) {return false;}
config.automation ??= {} as Config['automation'];
config.automation.heartbeat ??= {} as Config['automation']['heartbeat'];
config.automation.heartbeat.disk_threshold_mb = Math.floor(value);
return true;
},
'automation.heartbeat.process_memory_threshold_mb': (config, value) => {
if (typeof value !== 'number' || !Number.isFinite(value) || value < 64) {return false;}
config.automation ??= {} as Config['automation'];
config.automation.heartbeat ??= {} as Config['automation']['heartbeat'];
config.automation.heartbeat.process_memory_threshold_mb = Math.floor(value);
return true;
},
'automation.heartbeat.backup_failure_threshold': (config, value) => {
if (typeof value !== 'number' || !Number.isFinite(value) || value < 1 || value > 10) {return false;}
config.automation ??= {} as Config['automation'];
config.automation.heartbeat ??= {} as Config['automation']['heartbeat'];
config.automation.heartbeat.backup_failure_threshold = Math.floor(value);
return true;
},
'automation.heartbeat.provider_error_rate_threshold': (config, value) => {
if (typeof value !== 'number' || !Number.isFinite(value) || value < 0 || value > 1) {return false;}
config.automation ??= {} as Config['automation'];
config.automation.heartbeat ??= {} as Config['automation']['heartbeat'];
config.automation.heartbeat.provider_error_rate_threshold = value;
return true;
},
'automation.heartbeat.provider_error_min_calls': (config, value) => {
if (typeof value !== 'number' || !Number.isFinite(value) || value < 1) {return false;}
config.automation ??= {} as Config['automation'];
config.automation.heartbeat ??= {} as Config['automation']['heartbeat'];
config.automation.heartbeat.provider_error_min_calls = Math.floor(value);
return true;
},
'automation.heartbeat.checks': (config, value) => {
const allowed = ['gateway', 'model', 'channels', 'memory', 'disk', 'process_memory', 'backup', 'provider_errors'];
if (!Array.isArray(value) || !value.every((entry) => typeof entry === 'string' && allowed.includes(entry))) {
return false;
}
config.automation ??= {} as Config['automation'];
config.automation.heartbeat ??= {} as Config['automation']['heartbeat'];
config.automation.heartbeat.checks = value as Config['automation']['heartbeat']['checks'];
return true;
},
'backup.enabled': (config, value) => {
if (typeof value !== 'boolean') {return false;}
config.backup ??= {} as Config['backup'];
config.backup.enabled = value;
return true;
},
'audio.enabled': (config, value) => {
if (typeof value !== 'boolean') {return false;}
config.audio ??= {} as Config['audio'];
config.audio.enabled = value;
return true;
},
'sandbox.enabled': (config, value) => {
if (typeof value !== 'boolean') {return false;}
config.sandbox ??= {} as Config['sandbox'];
config.sandbox.enabled = value;
return true;
},
'memory.daily_log.enabled': (config, value) => {
if (typeof value !== 'boolean') {return false;}
config.memory ??= {} as Config['memory'];