fix(studio): System-AI test-connection error is copyable
Some checks failed
Security / Security check (push) Failing after 1s

The System-AI editor rendered its failure (test connection, save, model
pull) as a bare Text(_error) — selectable-but-not-copyable, the exact
thing the operator needs to paste back. Route it through ChainErrorBox
(selectable + one-tap copy button), and show a failed test result via
ChainErrorBox too instead of a plain SelectableText.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
flemming-it 2026-06-19 01:52:52 +02:00
parent 8724b19234
commit 7f59334176

View file

@ -11,6 +11,7 @@ import '../data/hub.dart';
import '../l10n/app_localizations.dart'; import '../l10n/app_localizations.dart';
import '../theme/theme.dart'; import '../theme/theme.dart';
import '../theme/tokens.dart'; import '../theme/tokens.dart';
import 'chain_error_box.dart';
import 'chain_pill.dart'; import 'chain_pill.dart';
/// Provider preset metadata kept in sync with /// Provider preset metadata kept in sync with
@ -459,12 +460,10 @@ class _FaiSystemAiEditorState extends State<ChainSystemAiEditor> {
], ],
if (_error != null) ...[ if (_error != null) ...[
const SizedBox(height: ChainSpace.md), const SizedBox(height: ChainSpace.md),
Text( // Copyable every error the operator sees must be
_error!, // selectable + one-tap copyable (ChainErrorBox), never
style: theme.textTheme.bodySmall?.copyWith( // a bare Text they can't paste back.
color: theme.colorScheme.error, ChainErrorBox(text: _error!, isError: true, maxHeight: 200),
),
),
], ],
if (_testResult != null) ...[ if (_testResult != null) ...[
const SizedBox(height: ChainSpace.md), const SizedBox(height: ChainSpace.md),
@ -650,10 +649,17 @@ class _TestResultPanel extends StatelessWidget {
], ],
), ),
const SizedBox(height: 4), const SizedBox(height: 4),
SelectableText( // Success the reply preview (selectable). Failure the
ok ? l.systemAiReplyPrefix(result.text) : result.text, // raw error in a ChainErrorBox with an explicit copy button,
style: ChainTheme.mono(size: 11, color: theme.colorScheme.onSurface), // so the operator can paste the exact failure back.
), if (ok)
SelectableText(
l.systemAiReplyPrefix(result.text),
style:
ChainTheme.mono(size: 11, color: theme.colorScheme.onSurface),
)
else
ChainErrorBox(text: result.text, isError: true, maxHeight: 200),
if (!ok && result.fixHint(l).isNotEmpty) ...[ if (!ok && result.fixHint(l).isNotEmpty) ...[
const SizedBox(height: ChainSpace.xs), const SizedBox(height: ChainSpace.xs),
Text( Text(