feat(studio): in-place System AI editor (v0.12.0)
Replaces the read-only System AI block in Settings with a real
editor. Operator never has to touch ~/.fai/config.yaml again
to change provider, endpoint, model, API-key env-var, or
privacy mode.
UX choices that align with the zero-learning-curve rule:
* Provider dropdown lists Ollama / OpenAI / LM Studio / vLLM
/ Custom by friendly name. Each selection auto-fills the
endpoint and api_key_env defaults — but only when the
field is still empty or matches a different preset's
default, so manual overrides are never clobbered.
* Each provider has a one-line description rendered under
the dropdown ("Ollama → Local `ollama serve`. Models stay
on your machine. No API key needed.") and a model-hint
placeholder ("gemma3:4b · llama3.2:3b · qwen2.5-coder:7b")
that goes away when a model is typed.
* Privacy mode is a vertical radio group with each option's
description in place — no doc-lookup needed.
* "Test connection" sends an `ok`-ping and renders the
same error-kind → fix-hint mapping the audit drill-down
uses.
* "Save" persists + hot-reloads the hub. No daemon restart
required. UI status badge flips to "enabled · <privacy>"
immediately.
`fai_dart_sdk` 0.5.0 carries the underlying `updateSystemAi` /
`testSystemAi` RPCs.
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
parent
4c4e2bb1eb
commit
15ea403c86
6 changed files with 601 additions and 5 deletions
|
|
@ -9,6 +9,7 @@ import '../data/hub.dart';
|
|||
import '../theme/theme.dart';
|
||||
import '../theme/tokens.dart';
|
||||
import 'fai_pill.dart';
|
||||
import 'fai_system_ai_editor.dart';
|
||||
|
||||
class FaiSettingsDialog extends StatefulWidget {
|
||||
const FaiSettingsDialog({super.key});
|
||||
|
|
@ -236,7 +237,18 @@ class _FaiSettingsDialogState extends State<FaiSettingsDialog> {
|
|||
],
|
||||
if (_aiStatus != null) ...[
|
||||
const SizedBox(height: FaiSpace.lg),
|
||||
_SystemAiPanel(status: _aiStatus!),
|
||||
_SystemAiPanel(
|
||||
status: _aiStatus!,
|
||||
onEdit: () async {
|
||||
final updated = await FaiSystemAiEditor.show(
|
||||
context,
|
||||
_aiStatus!,
|
||||
);
|
||||
if (updated != null && mounted) {
|
||||
setState(() => _aiStatus = updated);
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
|
|
@ -346,8 +358,9 @@ class _ChannelRow extends StatelessWidget {
|
|||
|
||||
class _SystemAiPanel extends StatelessWidget {
|
||||
final SystemAiStatus status;
|
||||
final VoidCallback onEdit;
|
||||
|
||||
const _SystemAiPanel({required this.status});
|
||||
const _SystemAiPanel({required this.status, required this.onEdit});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
@ -379,6 +392,12 @@ class _SystemAiPanel extends StatelessWidget {
|
|||
: FaiPillTone.neutral,
|
||||
),
|
||||
],
|
||||
const Spacer(),
|
||||
TextButton.icon(
|
||||
onPressed: onEdit,
|
||||
icon: const Icon(Icons.edit_outlined, size: 14),
|
||||
label: Text(status.enabled ? 'Edit…' : 'Configure…'),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
|
|
@ -392,7 +411,10 @@ class _SystemAiPanel extends StatelessWidget {
|
|||
Padding(
|
||||
padding: const EdgeInsets.only(top: 2),
|
||||
child: Text(
|
||||
'Off — explanations on failed events are disabled. Add a `system_llm:` block to ~/.fai/config.yaml and restart the daemon. See docs/architecture/system-ai.md.',
|
||||
'Off — failure explanations on the audit page are disabled. '
|
||||
'Click Configure… to pick a provider (Ollama / OpenAI / LM '
|
||||
'Studio / vLLM / Custom). Operator config is rewritten in place; '
|
||||
'no daemon restart needed.',
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
color: theme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue