feat(studio): cached/Regenerate UX in audit Explain (v0.16.0)
Audit drilldown's explanation panel now surfaces whether the answer came from the cache: - "cached" pill next to the SYSTEM AI label, tooltip shows the original generation date + hit count. - Latency renders as "orig 47000 ms" so the operator sees what a live call would have cost. - Refresh icon next to the latency triggers Regenerate — drops the entry, re-asks the model. System-AI editor shows a cache-status row when the cache is non-empty with a one-click Clear button. Hidden on fresh installs to keep the dialog quiet. Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
parent
b32b4b5bda
commit
d82738e17e
6 changed files with 161 additions and 9 deletions
|
|
@ -240,6 +240,27 @@ class _FaiSystemAiEditorState extends State<FaiSystemAiEditor> {
|
|||
}
|
||||
}
|
||||
|
||||
Future<void> _clearCache() async {
|
||||
try {
|
||||
final purged = await HubService.instance.clearSystemLlmCache();
|
||||
if (!mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Cleared $purged cached System-AI explanations.')),
|
||||
);
|
||||
// Pop with the same status (since the editor's `initial`
|
||||
// is now stale w.r.t. cacheCount); caller will re-fetch
|
||||
// status on next open.
|
||||
setState(() {
|
||||
// Force a rebuild that hides the row; cheap.
|
||||
});
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Cache clear failed: $e')),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _test() async {
|
||||
setState(() {
|
||||
_testing = true;
|
||||
|
|
@ -420,6 +441,13 @@ class _FaiSystemAiEditorState extends State<FaiSystemAiEditor> {
|
|||
value: _privacyMode,
|
||||
onChanged: (v) => setState(() => _privacyMode = v),
|
||||
),
|
||||
if (widget.initial.cacheCount > 0) ...[
|
||||
const SizedBox(height: FaiSpace.md),
|
||||
_CacheStatusRow(
|
||||
cacheCount: widget.initial.cacheCount,
|
||||
onClear: _saving || _testing ? null : _clearCache,
|
||||
),
|
||||
],
|
||||
if (_error != null) ...[
|
||||
const SizedBox(height: FaiSpace.md),
|
||||
Text(
|
||||
|
|
@ -1083,3 +1111,56 @@ class _SuitabilityLegend extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Displays the System-AI cache count plus a "Clear cache"
|
||||
/// button. Hidden when the cache is empty so the dialog stays
|
||||
/// quiet for fresh installs. Lives inline so the operator sees
|
||||
/// the cache exists, what it costs, and how to drop it without
|
||||
/// reading docs.
|
||||
class _CacheStatusRow extends StatelessWidget {
|
||||
final int cacheCount;
|
||||
final VoidCallback? onClear;
|
||||
|
||||
const _CacheStatusRow({required this.cacheCount, required this.onClear});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: FaiSpace.sm,
|
||||
vertical: 6,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: theme.colorScheme.surfaceContainerHigh,
|
||||
borderRadius: BorderRadius.circular(FaiRadius.sm),
|
||||
border: Border.all(color: theme.colorScheme.outlineVariant),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.bolt,
|
||||
size: 14,
|
||||
color: theme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Cache: $cacheCount cached explanation${cacheCount == 1 ? "" : "s"}. '
|
||||
'Identical prompts hit the cache; switching model or privacy '
|
||||
'mode flushes automatically.',
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
color: theme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
),
|
||||
TextButton.icon(
|
||||
onPressed: onClear,
|
||||
icon: const Icon(Icons.delete_outline, size: 14),
|
||||
label: const Text('Clear'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue