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
|
|
@ -119,6 +119,7 @@ class HubService {
|
|||
model: r.model,
|
||||
privacyMode: r.privacyMode,
|
||||
apiKeyEnv: r.apiKeyEnv,
|
||||
cacheCount: r.cacheCount.toInt(),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -126,15 +127,29 @@ class HubService {
|
|||
/// answer + latency on success or an [AskAiResult] with
|
||||
/// `errorKind` set on failure (never throws). Studio maps
|
||||
/// the error kind to its inline-fix copy.
|
||||
Future<AskAiResult> askAi(String prompt) async {
|
||||
final r = await _client.askAi(prompt);
|
||||
Future<AskAiResult> askAi(String prompt, {bool forceFresh = false}) async {
|
||||
final r = await _client.askAi(prompt, forceFresh: forceFresh);
|
||||
return AskAiResult(
|
||||
errorKind: r.errorKind,
|
||||
text: r.text,
|
||||
latencyMs: r.latencyMs,
|
||||
cached: r.cached,
|
||||
cachedAt: r.cachedAt,
|
||||
cacheHits: r.cacheHits,
|
||||
);
|
||||
}
|
||||
|
||||
/// Drop every cached System-AI explanation. Returns the count
|
||||
/// of entries that were purged.
|
||||
Future<int> clearSystemLlmCache() {
|
||||
return _client.clearSystemLlmCache();
|
||||
}
|
||||
|
||||
/// Forget a single cached entry by prompt (for "Regenerate").
|
||||
Future<void> forgetCachedExplanation(String prompt) {
|
||||
return _client.forgetCachedExplanation(prompt);
|
||||
}
|
||||
|
||||
/// Persist a new System-AI configuration. The hub writes back
|
||||
/// to `~/.fai/config.yaml` and hot-reloads the in-memory copy
|
||||
/// in one round-trip; the caller gets the resulting status
|
||||
|
|
@ -160,6 +175,7 @@ class HubService {
|
|||
model: r.model,
|
||||
privacyMode: r.privacyMode,
|
||||
apiKeyEnv: r.apiKeyEnv,
|
||||
cacheCount: r.cacheCount.toInt(),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -687,6 +703,10 @@ class SystemAiStatus {
|
|||
/// off / redacted / full.
|
||||
final String privacyMode;
|
||||
final String apiKeyEnv;
|
||||
/// Number of cached System-AI explanations currently stored.
|
||||
/// Surfaced in Doctor + Settings so operators see the cache
|
||||
/// earning its keep.
|
||||
final int cacheCount;
|
||||
|
||||
const SystemAiStatus({
|
||||
required this.enabled,
|
||||
|
|
@ -695,6 +715,7 @@ class SystemAiStatus {
|
|||
required this.model,
|
||||
required this.privacyMode,
|
||||
required this.apiKeyEnv,
|
||||
this.cacheCount = 0,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -705,13 +726,25 @@ class AskAiResult {
|
|||
/// On success: the assistant's reply.
|
||||
/// On failure: a human-readable diagnostic.
|
||||
final String text;
|
||||
/// Round-trip latency in ms (success only).
|
||||
/// Round-trip latency in ms (success only). For cache hits
|
||||
/// this is the *original* generation latency.
|
||||
final int latencyMs;
|
||||
/// True iff the answer came from the persistent cache.
|
||||
final bool cached;
|
||||
/// ISO-8601 timestamp the cached entry was first generated.
|
||||
/// Empty for fresh answers.
|
||||
final String cachedAt;
|
||||
/// How many times this entry has been served from cache.
|
||||
/// 0 for fresh answers.
|
||||
final int cacheHits;
|
||||
|
||||
const AskAiResult({
|
||||
required this.errorKind,
|
||||
required this.text,
|
||||
required this.latencyMs,
|
||||
this.cached = false,
|
||||
this.cachedAt = '',
|
||||
this.cacheHits = 0,
|
||||
});
|
||||
|
||||
bool get isSuccess => errorKind.isEmpty;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue