feat(studio): hardware-aware model recommendations + sidebar clock (v0.14.0)
System-AI editor now fetches the detected hardware tier and the hub's curated model database on open. Each model chip's colour + tooltip combines both: green star when curated quality is good/excellent AND min_hw_tier ≤ host; orange when quality is fine but the host is below min_hw_tier; warning for "basic" curated entries. Tooltip exposes the curator's note, parameter count, context window, and licence. Banner above the form shows "Detected: <summary> · curation reviewed <date>". Sidebar footer gains a small monospaced live clock between the theme toggle and the settings icon. Tooltip exposes full local ISO + UTC for cross-checking against audit-log timestamps. Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
parent
a83a138259
commit
942c29a395
5 changed files with 395 additions and 35 deletions
|
|
@ -230,6 +230,46 @@ class HubService {
|
|||
);
|
||||
}
|
||||
|
||||
/// Detected host hardware. Used by the System-AI editor to
|
||||
/// mark models as "recommended" / "may be slow" against the
|
||||
/// operator's actual machine.
|
||||
Future<HardwareSnapshot> hardwareInfo() async {
|
||||
final r = await _client.hardwareInfo();
|
||||
return HardwareSnapshot(
|
||||
tier: r.tier,
|
||||
cpuBrand: r.cpuBrand,
|
||||
cpuCores: r.cpuCores,
|
||||
ramMb: r.ramMb.toInt(),
|
||||
appleSilicon: r.appleSilicon,
|
||||
dedicatedGpu: r.dedicatedGpu,
|
||||
summary: r.summary,
|
||||
);
|
||||
}
|
||||
|
||||
/// Bundled curated model database. Refresh requires a hub
|
||||
/// redeploy; the `lastReviewed` field shows how stale the
|
||||
/// curation is.
|
||||
Future<CuratedSnapshot> listSystemAiCuratedModels() async {
|
||||
final r = await _client.listSystemAiCuratedModels();
|
||||
return CuratedSnapshot(
|
||||
lastReviewed: r.lastReviewed,
|
||||
models: r.models
|
||||
.map(
|
||||
(m) => CuratedModelInfo(
|
||||
id: m.id,
|
||||
family: m.family,
|
||||
paramsB: m.paramsB,
|
||||
qualityTier: m.qualityTier,
|
||||
minHwTier: m.minHwTier,
|
||||
contextK: m.contextK,
|
||||
notes: m.notes,
|
||||
license: m.license,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
|
||||
/// Active channel + per-channel daemon status snapshot.
|
||||
Future<ChannelStatusSnapshot> channelStatus() async {
|
||||
final r = await _client.channelStatus();
|
||||
|
|
@ -707,6 +747,103 @@ class ChannelStatusSnapshot {
|
|||
});
|
||||
}
|
||||
|
||||
/// Detected host hardware — see
|
||||
/// docs/architecture/system-ai.md → "Hardware tiers".
|
||||
class HardwareSnapshot {
|
||||
/// One of: tiny / small / balanced / large / unknown.
|
||||
final String tier;
|
||||
final String cpuBrand;
|
||||
final int cpuCores;
|
||||
final int ramMb;
|
||||
final bool appleSilicon;
|
||||
final bool dedicatedGpu;
|
||||
/// Human-readable summary the editor renders verbatim.
|
||||
final String summary;
|
||||
|
||||
const HardwareSnapshot({
|
||||
required this.tier,
|
||||
required this.cpuBrand,
|
||||
required this.cpuCores,
|
||||
required this.ramMb,
|
||||
required this.appleSilicon,
|
||||
required this.dedicatedGpu,
|
||||
required this.summary,
|
||||
});
|
||||
|
||||
/// Numeric rank used for "is `min_hw_tier` ≤ detected?"
|
||||
/// comparisons. Unknown sits at -1 so it never qualifies as
|
||||
/// "at least" anything; the editor falls back to size-only
|
||||
/// heuristics in that case.
|
||||
int get rank {
|
||||
switch (tier) {
|
||||
case 'tiny':
|
||||
return 0;
|
||||
case 'small':
|
||||
return 1;
|
||||
case 'balanced':
|
||||
return 2;
|
||||
case 'large':
|
||||
return 3;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// One curated model with editorial metadata. Wire-faithful
|
||||
/// with `crates/fai_hub/system-ai/models.yaml`.
|
||||
class CuratedModelInfo {
|
||||
final String id;
|
||||
final String family;
|
||||
final double paramsB;
|
||||
/// basic / good / excellent.
|
||||
final String qualityTier;
|
||||
/// tiny / small / balanced / large.
|
||||
final String minHwTier;
|
||||
final int contextK;
|
||||
final String notes;
|
||||
final String license;
|
||||
|
||||
const CuratedModelInfo({
|
||||
required this.id,
|
||||
required this.family,
|
||||
required this.paramsB,
|
||||
required this.qualityTier,
|
||||
required this.minHwTier,
|
||||
required this.contextK,
|
||||
required this.notes,
|
||||
required this.license,
|
||||
});
|
||||
|
||||
/// Same rank as HardwareSnapshot; lets us compare with `<=`.
|
||||
int get minHwRank {
|
||||
switch (minHwTier) {
|
||||
case 'tiny':
|
||||
return 0;
|
||||
case 'small':
|
||||
return 1;
|
||||
case 'balanced':
|
||||
return 2;
|
||||
case 'large':
|
||||
return 3;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Curated database snapshot returned from the hub.
|
||||
class CuratedSnapshot {
|
||||
/// ISO date string from `models.yaml`, e.g. "2026-05-07".
|
||||
final String lastReviewed;
|
||||
final List<CuratedModelInfo> models;
|
||||
|
||||
const CuratedSnapshot({
|
||||
required this.lastReviewed,
|
||||
required this.models,
|
||||
});
|
||||
}
|
||||
|
||||
/// One row from the store-index search.
|
||||
class StoreItem {
|
||||
final String name;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue