feat: pullSystemAiModelStreaming for live model-download progress

Wraps HubAdmin/PullSystemAiModelStream: yields the backend's own
status and byte counts per layer, and hands the terminal response to
onFinished, whose errorKind stays the failure signal. Stubs
regenerated from the protos (additive only).

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
flemming-it 2026-09-08 17:51:28 +02:00
parent 1d3d33d55a
commit 4c7db58bce
4 changed files with 294 additions and 0 deletions

View file

@ -111,6 +111,7 @@ typedef StoreEntry = pb.StoreEntry;
typedef StoreSearchResponse = pb.StoreSearchResponse;
typedef InstallModuleResponse = pb.InstallModuleResponse;
typedef InstallProgressUpdate = pb.InstallProgressUpdate;
typedef PullProgressUpdate = pb.PullProgressUpdate;
typedef Payload = pb_common.Payload;
typedef SubmitResponse = pb.SubmitResponse;
// Live-stream (T2) + detached-invocation (T3) wire types, re-exported
@ -867,6 +868,34 @@ class HubClient {
}
}
/// Pull a model while watching it happen.
///
/// A model pull moves gigabytes; the unary [pullSystemAiModel]
/// leaves the caller waiting minutes with nothing to show. Emits the
/// backend's own status plus byte counts per layer, and calls
/// [onFinished] with the terminal response, whose `errorKind` is
/// non-empty when the pull failed.
Stream<PullProgressUpdate> pullSystemAiModelStreaming({
required String endpoint,
required String model,
String apiKeyEnv = '',
void Function(PullSystemAiModelResponse result)? onFinished,
}) async* {
final stream = _admin.pullSystemAiModelStream(pb.PullSystemAiModelRequest(
endpoint: endpoint,
model: model,
apiKeyEnv: apiKeyEnv,
));
await for (final event in stream) {
if (event.hasUpdate()) {
yield event.update;
} else if (event.hasFinished()) {
onFinished?.call(event.finished);
return;
}
}
}
/// All saved flows known to the hub. Each entry carries the
/// flow name, on-disk path and byte size.
Future<List<FlowSummary>> listFlows() async {