Compare commits

...

3 commits

Author SHA1 Message Date
flemming-it
aacb2406b4 chore: regenerate stubs for chain.v1.DataSource
Some checks failed
Security / Security check (push) Failing after 2s
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-09-09 12:36:44 +02:00
flemming-it
4c7db58bce 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>
2026-09-08 17:51:28 +02:00
flemming-it
1d3d33d55a feat: installModuleStreaming for live install progress
Wraps the new HubAdmin/InstallModuleStream: yields one update per
phase and, during the download, as bytes arrive; completes on success
and surfaces the hub's failure text as a stream error, so callers
handle failures exactly as with the unary installModule. Generated
stubs regenerated from the protos (additive only).

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
2026-09-08 13:38:35 +02:00
4 changed files with 827 additions and 1 deletions

View file

@ -3576,6 +3576,246 @@ class InstallModuleResponse extends $pb.GeneratedMessage {
void clearCapabilityCount() => $_clearField(3); void clearCapabilityCount() => $_clearField(3);
} }
enum InstallProgressEvent_Event { update, finished, failed, notSet }
/// One message in an InstallModuleStream.
class InstallProgressEvent extends $pb.GeneratedMessage {
factory InstallProgressEvent({
InstallProgressUpdate? update,
InstallModuleResponse? finished,
$core.String? failed,
}) {
final result = create();
if (update != null) result.update = update;
if (finished != null) result.finished = finished;
if (failed != null) result.failed = failed;
return result;
}
InstallProgressEvent._();
factory InstallProgressEvent.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory InstallProgressEvent.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static const $core.Map<$core.int, InstallProgressEvent_Event>
_InstallProgressEvent_EventByTag = {
1: InstallProgressEvent_Event.update,
2: InstallProgressEvent_Event.finished,
3: InstallProgressEvent_Event.failed,
0: InstallProgressEvent_Event.notSet
};
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'InstallProgressEvent',
package: const $pb.PackageName(_omitMessageNames ? '' : 'chain.v1'),
createEmptyInstance: create)
..oo(0, [1, 2, 3])
..aOM<InstallProgressUpdate>(1, _omitFieldNames ? '' : 'update',
subBuilder: InstallProgressUpdate.create)
..aOM<InstallModuleResponse>(2, _omitFieldNames ? '' : 'finished',
subBuilder: InstallModuleResponse.create)
..aOS(3, _omitFieldNames ? '' : 'failed')
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
InstallProgressEvent clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
InstallProgressEvent copyWith(void Function(InstallProgressEvent) updates) =>
super.copyWith((message) => updates(message as InstallProgressEvent))
as InstallProgressEvent;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static InstallProgressEvent create() => InstallProgressEvent._();
@$core.override
InstallProgressEvent createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static InstallProgressEvent getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<InstallProgressEvent>(create);
static InstallProgressEvent? _defaultInstance;
@$pb.TagNumber(1)
@$pb.TagNumber(2)
@$pb.TagNumber(3)
InstallProgressEvent_Event whichEvent() =>
_InstallProgressEvent_EventByTag[$_whichOneof(0)]!;
@$pb.TagNumber(1)
@$pb.TagNumber(2)
@$pb.TagNumber(3)
void clearEvent() => $_clearField($_whichOneof(0));
/// Progress moved, or a phase started or finished.
@$pb.TagNumber(1)
InstallProgressUpdate get update => $_getN(0);
@$pb.TagNumber(1)
set update(InstallProgressUpdate value) => $_setField(1, value);
@$pb.TagNumber(1)
$core.bool hasUpdate() => $_has(0);
@$pb.TagNumber(1)
void clearUpdate() => $_clearField(1);
@$pb.TagNumber(1)
InstallProgressUpdate ensureUpdate() => $_ensure(0);
/// The install succeeded; always the final message.
@$pb.TagNumber(2)
InstallModuleResponse get finished => $_getN(1);
@$pb.TagNumber(2)
set finished(InstallModuleResponse value) => $_setField(2, value);
@$pb.TagNumber(2)
$core.bool hasFinished() => $_has(1);
@$pb.TagNumber(2)
void clearFinished() => $_clearField(2);
@$pb.TagNumber(2)
InstallModuleResponse ensureFinished() => $_ensure(1);
/// The install failed; always the final message. Carries the same
/// text the unary call would have returned as its status message.
@$pb.TagNumber(3)
$core.String get failed => $_getSZ(2);
@$pb.TagNumber(3)
set failed($core.String value) => $_setString(2, value);
@$pb.TagNumber(3)
$core.bool hasFailed() => $_has(2);
@$pb.TagNumber(3)
void clearFailed() => $_clearField(3);
}
/// A single progress observation.
class InstallProgressUpdate extends $pb.GeneratedMessage {
factory InstallProgressUpdate({
$core.String? phase,
$core.String? stage,
$core.double? percent,
$fixnum.Int64? bytesReceived,
$fixnum.Int64? bytesTotal,
$core.bool? phaseDone,
}) {
final result = create();
if (phase != null) result.phase = phase;
if (stage != null) result.stage = stage;
if (percent != null) result.percent = percent;
if (bytesReceived != null) result.bytesReceived = bytesReceived;
if (bytesTotal != null) result.bytesTotal = bytesTotal;
if (phaseDone != null) result.phaseDone = phaseDone;
return result;
}
InstallProgressUpdate._();
factory InstallProgressUpdate.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory InstallProgressUpdate.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'InstallProgressUpdate',
package: const $pb.PackageName(_omitMessageNames ? '' : 'chain.v1'),
createEmptyInstance: create)
..aOS(1, _omitFieldNames ? '' : 'phase')
..aOS(2, _omitFieldNames ? '' : 'stage')
..aD(3, _omitFieldNames ? '' : 'percent', fieldType: $pb.PbFieldType.OF)
..a<$fixnum.Int64>(
4, _omitFieldNames ? '' : 'bytesReceived', $pb.PbFieldType.OU6,
defaultOrMaker: $fixnum.Int64.ZERO)
..a<$fixnum.Int64>(
5, _omitFieldNames ? '' : 'bytesTotal', $pb.PbFieldType.OU6,
defaultOrMaker: $fixnum.Int64.ZERO)
..aOB(6, _omitFieldNames ? '' : 'phaseDone')
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
InstallProgressUpdate clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
InstallProgressUpdate copyWith(
void Function(InstallProgressUpdate) updates) =>
super.copyWith((message) => updates(message as InstallProgressUpdate))
as InstallProgressUpdate;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static InstallProgressUpdate create() => InstallProgressUpdate._();
@$core.override
InstallProgressUpdate createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static InstallProgressUpdate getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<InstallProgressUpdate>(create);
static InstallProgressUpdate? _defaultInstance;
/// Stable phase identifier: "resolve", "download" or "install".
/// Clients map it to their own wording; it is not display text.
@$pb.TagNumber(1)
$core.String get phase => $_getSZ(0);
@$pb.TagNumber(1)
set phase($core.String value) => $_setString(0, value);
@$pb.TagNumber(1)
$core.bool hasPhase() => $_has(0);
@$pb.TagNumber(1)
void clearPhase() => $_clearField(1);
/// English fallback label for the phase ("Downloading"). Clients with
/// their own translations key off `phase` and ignore this.
@$pb.TagNumber(2)
$core.String get stage => $_getSZ(1);
@$pb.TagNumber(2)
set stage($core.String value) => $_setString(1, value);
@$pb.TagNumber(2)
$core.bool hasStage() => $_has(1);
@$pb.TagNumber(2)
void clearStage() => $_clearField(2);
/// Overall progress across all phases, 0..100, monotonic. Absent
/// means the extent is not knowable yet show an indeterminate
/// indicator, never a bar parked at zero.
@$pb.TagNumber(3)
$core.double get percent => $_getN(2);
@$pb.TagNumber(3)
set percent($core.double value) => $_setFloat(2, value);
@$pb.TagNumber(3)
$core.bool hasPercent() => $_has(2);
@$pb.TagNumber(3)
void clearPercent() => $_clearField(3);
/// Bytes received so far during the download phase.
@$pb.TagNumber(4)
$fixnum.Int64 get bytesReceived => $_getI64(3);
@$pb.TagNumber(4)
set bytesReceived($fixnum.Int64 value) => $_setInt64(3, value);
@$pb.TagNumber(4)
$core.bool hasBytesReceived() => $_has(3);
@$pb.TagNumber(4)
void clearBytesReceived() => $_clearField(4);
/// Total bytes the server announced. Zero means the server sent no
/// content-length, so only `bytes_received` is meaningful.
@$pb.TagNumber(5)
$fixnum.Int64 get bytesTotal => $_getI64(4);
@$pb.TagNumber(5)
set bytesTotal($fixnum.Int64 value) => $_setInt64(4, value);
@$pb.TagNumber(5)
$core.bool hasBytesTotal() => $_has(4);
@$pb.TagNumber(5)
void clearBytesTotal() => $_clearField(5);
/// The named phase just finished.
@$pb.TagNumber(6)
$core.bool get phaseDone => $_getBF(5);
@$pb.TagNumber(6)
set phaseDone($core.bool value) => $_setBool(5, value);
@$pb.TagNumber(6)
$core.bool hasPhaseDone() => $_has(5);
@$pb.TagNumber(6)
void clearPhaseDone() => $_clearField(6);
}
class UninstallModuleRequest extends $pb.GeneratedMessage { class UninstallModuleRequest extends $pb.GeneratedMessage {
factory UninstallModuleRequest({ factory UninstallModuleRequest({
$core.String? name, $core.String? name,
@ -5253,6 +5493,7 @@ class StoreEntry extends $pb.GeneratedMessage {
$core.String? canonicalCategoryLabel, $core.String? canonicalCategoryLabel,
$core.String? installVerification, $core.String? installVerification,
$core.Iterable<$core.String>? maintainers, $core.Iterable<$core.String>? maintainers,
DataSource? dataSource,
}) { }) {
final result = create(); final result = create();
if (name != null) result.name = name; if (name != null) result.name = name;
@ -5285,6 +5526,7 @@ class StoreEntry extends $pb.GeneratedMessage {
if (installVerification != null) if (installVerification != null)
result.installVerification = installVerification; result.installVerification = installVerification;
if (maintainers != null) result.maintainers.addAll(maintainers); if (maintainers != null) result.maintainers.addAll(maintainers);
if (dataSource != null) result.dataSource = dataSource;
return result; return result;
} }
@ -5327,6 +5569,8 @@ class StoreEntry extends $pb.GeneratedMessage {
..aOS(24, _omitFieldNames ? '' : 'canonicalCategoryLabel') ..aOS(24, _omitFieldNames ? '' : 'canonicalCategoryLabel')
..aOS(25, _omitFieldNames ? '' : 'installVerification') ..aOS(25, _omitFieldNames ? '' : 'installVerification')
..pPS(26, _omitFieldNames ? '' : 'maintainers') ..pPS(26, _omitFieldNames ? '' : 'maintainers')
..aOM<DataSource>(27, _omitFieldNames ? '' : 'dataSource',
subBuilder: DataSource.create)
..hasRequiredFields = false; ..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
@ -5620,6 +5864,122 @@ class StoreEntry extends $pb.GeneratedMessage {
/// any clients render an honest "not specified". /// any clients render an honest "not specified".
@$pb.TagNumber(26) @$pb.TagNumber(26)
$pb.PbList<$core.String> get maintainers => $_getList(25); $pb.PbList<$core.String> get maintainers => $_getList(25);
/// Where the module's data comes from, for `source.*` capabilities.
/// Absent for every other module: a text splitter reaches no
/// third-party material and has no provenance to declare.
@$pb.TagNumber(27)
DataSource get dataSource => $_getN(26);
@$pb.TagNumber(27)
set dataSource(DataSource value) => $_setField(27, value);
@$pb.TagNumber(27)
$core.bool hasDataSource() => $_has(26);
@$pb.TagNumber(27)
void clearDataSource() => $_clearField(27);
@$pb.TagNumber(27)
DataSource ensureDataSource() => $_ensure(26);
}
/// Provenance of the material a `source.*` module fetches.
///
/// Separate from the module's own licence, which covers its code. A
/// module can be Apache-2.0 while the corpus it reaches is
/// public-domain statute, CC-BY, or licence-gated. Clients show this
/// before the install button so an operator sees the terms they are
/// taking on.
class DataSource extends $pb.GeneratedMessage {
factory DataSource({
$core.String? name,
$core.String? url,
$core.String? license,
$core.String? attribution,
}) {
final result = create();
if (name != null) result.name = name;
if (url != null) result.url = url;
if (license != null) result.license = license;
if (attribution != null) result.attribution = attribution;
return result;
}
DataSource._();
factory DataSource.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory DataSource.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'DataSource',
package: const $pb.PackageName(_omitMessageNames ? '' : 'chain.v1'),
createEmptyInstance: create)
..aOS(1, _omitFieldNames ? '' : 'name')
..aOS(2, _omitFieldNames ? '' : 'url')
..aOS(3, _omitFieldNames ? '' : 'license')
..aOS(4, _omitFieldNames ? '' : 'attribution')
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
DataSource clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
DataSource copyWith(void Function(DataSource) updates) =>
super.copyWith((message) => updates(message as DataSource)) as DataSource;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static DataSource create() => DataSource._();
@$core.override
DataSource createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static DataSource getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<DataSource>(create);
static DataSource? _defaultInstance;
/// Publisher, as a person would name it.
@$pb.TagNumber(1)
$core.String get name => $_getSZ(0);
@$pb.TagNumber(1)
set name($core.String value) => $_setString(0, value);
@$pb.TagNumber(1)
$core.bool hasName() => $_has(0);
@$pb.TagNumber(1)
void clearName() => $_clearField(1);
/// Canonical URL of the upstream source.
@$pb.TagNumber(2)
$core.String get url => $_getSZ(1);
@$pb.TagNumber(2)
set url($core.String value) => $_setString(1, value);
@$pb.TagNumber(2)
$core.bool hasUrl() => $_has(1);
@$pb.TagNumber(2)
void clearUrl() => $_clearField(2);
/// Terms in plain words, not SPDX: the material often carries no
/// software licence at all.
@$pb.TagNumber(3)
$core.String get license => $_getSZ(2);
@$pb.TagNumber(3)
set license($core.String value) => $_setString(2, value);
@$pb.TagNumber(3)
$core.bool hasLicense() => $_has(2);
@$pb.TagNumber(3)
void clearLicense() => $_clearField(3);
/// Attribution the operator must carry with the output. Empty when
/// the upstream requires none.
@$pb.TagNumber(4)
$core.String get attribution => $_getSZ(3);
@$pb.TagNumber(4)
set attribution($core.String value) => $_setString(3, value);
@$pb.TagNumber(4)
$core.bool hasAttribution() => $_has(3);
@$pb.TagNumber(4)
void clearAttribution() => $_clearField(4);
} }
class ChannelStatusResponse extends $pb.GeneratedMessage { class ChannelStatusResponse extends $pb.GeneratedMessage {
@ -6990,6 +7350,186 @@ class PullSystemAiModelResponse extends $pb.GeneratedMessage {
void clearElapsedMs() => $_clearField(3); void clearElapsedMs() => $_clearField(3);
} }
enum PullProgressEvent_Event { update, finished, notSet }
/// One message in a PullSystemAiModelStream.
class PullProgressEvent extends $pb.GeneratedMessage {
factory PullProgressEvent({
PullProgressUpdate? update,
PullSystemAiModelResponse? finished,
}) {
final result = create();
if (update != null) result.update = update;
if (finished != null) result.finished = finished;
return result;
}
PullProgressEvent._();
factory PullProgressEvent.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory PullProgressEvent.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static const $core.Map<$core.int, PullProgressEvent_Event>
_PullProgressEvent_EventByTag = {
1: PullProgressEvent_Event.update,
2: PullProgressEvent_Event.finished,
0: PullProgressEvent_Event.notSet
};
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'PullProgressEvent',
package: const $pb.PackageName(_omitMessageNames ? '' : 'chain.v1'),
createEmptyInstance: create)
..oo(0, [1, 2])
..aOM<PullProgressUpdate>(1, _omitFieldNames ? '' : 'update',
subBuilder: PullProgressUpdate.create)
..aOM<PullSystemAiModelResponse>(2, _omitFieldNames ? '' : 'finished',
subBuilder: PullSystemAiModelResponse.create)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
PullProgressEvent clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
PullProgressEvent copyWith(void Function(PullProgressEvent) updates) =>
super.copyWith((message) => updates(message as PullProgressEvent))
as PullProgressEvent;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static PullProgressEvent create() => PullProgressEvent._();
@$core.override
PullProgressEvent createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static PullProgressEvent getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<PullProgressEvent>(create);
static PullProgressEvent? _defaultInstance;
@$pb.TagNumber(1)
@$pb.TagNumber(2)
PullProgressEvent_Event whichEvent() =>
_PullProgressEvent_EventByTag[$_whichOneof(0)]!;
@$pb.TagNumber(1)
@$pb.TagNumber(2)
void clearEvent() => $_clearField($_whichOneof(0));
/// The pull moved on.
@$pb.TagNumber(1)
PullProgressUpdate get update => $_getN(0);
@$pb.TagNumber(1)
set update(PullProgressUpdate value) => $_setField(1, value);
@$pb.TagNumber(1)
$core.bool hasUpdate() => $_has(0);
@$pb.TagNumber(1)
void clearUpdate() => $_clearField(1);
@$pb.TagNumber(1)
PullProgressUpdate ensureUpdate() => $_ensure(0);
/// Terminal message, success or failure (see its error_kind).
@$pb.TagNumber(2)
PullSystemAiModelResponse get finished => $_getN(1);
@$pb.TagNumber(2)
set finished(PullSystemAiModelResponse value) => $_setField(2, value);
@$pb.TagNumber(2)
$core.bool hasFinished() => $_has(1);
@$pb.TagNumber(2)
void clearFinished() => $_clearField(2);
@$pb.TagNumber(2)
PullSystemAiModelResponse ensureFinished() => $_ensure(1);
}
/// A single observation while a model downloads.
class PullProgressUpdate extends $pb.GeneratedMessage {
factory PullProgressUpdate({
$core.String? status,
$fixnum.Int64? completed,
$fixnum.Int64? total,
}) {
final result = create();
if (status != null) result.status = status;
if (completed != null) result.completed = completed;
if (total != null) result.total = total;
return result;
}
PullProgressUpdate._();
factory PullProgressUpdate.fromBuffer($core.List<$core.int> data,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromBuffer(data, registry);
factory PullProgressUpdate.fromJson($core.String json,
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
create()..mergeFromJson(json, registry);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
_omitMessageNames ? '' : 'PullProgressUpdate',
package: const $pb.PackageName(_omitMessageNames ? '' : 'chain.v1'),
createEmptyInstance: create)
..aOS(1, _omitFieldNames ? '' : 'status')
..a<$fixnum.Int64>(
2, _omitFieldNames ? '' : 'completed', $pb.PbFieldType.OU6,
defaultOrMaker: $fixnum.Int64.ZERO)
..a<$fixnum.Int64>(3, _omitFieldNames ? '' : 'total', $pb.PbFieldType.OU6,
defaultOrMaker: $fixnum.Int64.ZERO)
..hasRequiredFields = false;
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
PullProgressUpdate clone() => deepCopy();
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
PullProgressUpdate copyWith(void Function(PullProgressUpdate) updates) =>
super.copyWith((message) => updates(message as PullProgressUpdate))
as PullProgressUpdate;
@$core.override
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static PullProgressUpdate create() => PullProgressUpdate._();
@$core.override
PullProgressUpdate createEmptyInstance() => create();
@$core.pragma('dart2js:noInline')
static PullProgressUpdate getDefault() => _defaultInstance ??=
$pb.GeneratedMessage.$_defaultFor<PullProgressUpdate>(create);
static PullProgressUpdate? _defaultInstance;
/// The backend's own status text, e.g. "pulling manifest". Passed
/// through verbatim rather than translated: it names layers and
/// digests a client cannot reconstruct.
@$pb.TagNumber(1)
$core.String get status => $_getSZ(0);
@$pb.TagNumber(1)
set status($core.String value) => $_setString(0, value);
@$pb.TagNumber(1)
$core.bool hasStatus() => $_has(0);
@$pb.TagNumber(1)
void clearStatus() => $_clearField(1);
/// Bytes fetched so far for the layer this status refers to.
@$pb.TagNumber(2)
$fixnum.Int64 get completed => $_getI64(1);
@$pb.TagNumber(2)
set completed($fixnum.Int64 value) => $_setInt64(1, value);
@$pb.TagNumber(2)
$core.bool hasCompleted() => $_has(1);
@$pb.TagNumber(2)
void clearCompleted() => $_clearField(2);
/// Size of that layer; zero for statuses that carry no size, which
/// clients show as indeterminate rather than as zero progress.
@$pb.TagNumber(3)
$fixnum.Int64 get total => $_getI64(2);
@$pb.TagNumber(3)
set total($fixnum.Int64 value) => $_setInt64(2, value);
@$pb.TagNumber(3)
$core.bool hasTotal() => $_has(2);
@$pb.TagNumber(3)
void clearTotal() => $_clearField(3);
}
class HardwareInfoResponse extends $pb.GeneratedMessage { class HardwareInfoResponse extends $pb.GeneratedMessage {
factory HardwareInfoResponse({ factory HardwareInfoResponse({
$core.String? tier, $core.String? tier,

View file

@ -442,6 +442,21 @@ class HubAdminClient extends $grpc.Client {
return $createUnaryCall(_$installModule, request, options: options); return $createUnaryCall(_$installModule, request, options: options);
} }
/// Same install, with live progress. Emits an update per phase and,
/// during the download, as bytes arrive; the last message carries
/// either the finished response or the error. Clients that only need
/// the outcome keep using the unary InstallModule above this exists
/// so a waiting operator can see that a slow download is progressing
/// rather than hung.
$grpc.ResponseStream<$0.InstallProgressEvent> installModuleStream(
$0.InstallModuleRequest request, {
$grpc.CallOptions? options,
}) {
return $createStreamingCall(
_$installModuleStream, $async.Stream.fromIterable([request]),
options: options);
}
/// Remove an installed module by name. Wipes the module /// Remove an installed module by name. Wipes the module
/// directory and re-scans the registry; writes a /// directory and re-scans the registry; writes a
/// `module.uninstalled` audit event. Surfaced by the Studio /// `module.uninstalled` audit event. Surfaced by the Studio
@ -803,6 +818,19 @@ class HubAdminClient extends $grpc.Client {
return $createUnaryCall(_$pullSystemAiModel, request, options: options); return $createUnaryCall(_$pullSystemAiModel, request, options: options);
} }
/// Same pull, with live progress. A model pull moves gigabytes, so
/// the unary form above leaves a person waiting minutes with nothing
/// to look at. Emits Ollama's own status plus byte counts per layer,
/// ending in the response.
$grpc.ResponseStream<$0.PullProgressEvent> pullSystemAiModelStream(
$0.PullSystemAiModelRequest request, {
$grpc.CallOptions? options,
}) {
return $createStreamingCall(
_$pullSystemAiModelStream, $async.Stream.fromIterable([request]),
options: options);
}
/// Drop every cached System-AI explanation. Surfaced in /// Drop every cached System-AI explanation. Surfaced in
/// Studio's Settings so operators can force a clean slate /// Studio's Settings so operators can force a clean slate
/// without changing model/privacy mode (which also flushes). /// without changing model/privacy mode (which also flushes).
@ -956,6 +984,11 @@ class HubAdminClient extends $grpc.Client {
'/chain.v1.HubAdmin/InstallModule', '/chain.v1.HubAdmin/InstallModule',
($0.InstallModuleRequest value) => value.writeToBuffer(), ($0.InstallModuleRequest value) => value.writeToBuffer(),
$0.InstallModuleResponse.fromBuffer); $0.InstallModuleResponse.fromBuffer);
static final _$installModuleStream =
$grpc.ClientMethod<$0.InstallModuleRequest, $0.InstallProgressEvent>(
'/chain.v1.HubAdmin/InstallModuleStream',
($0.InstallModuleRequest value) => value.writeToBuffer(),
$0.InstallProgressEvent.fromBuffer);
static final _$uninstallModule = static final _$uninstallModule =
$grpc.ClientMethod<$0.UninstallModuleRequest, $0.UninstallModuleResponse>( $grpc.ClientMethod<$0.UninstallModuleRequest, $0.UninstallModuleResponse>(
'/chain.v1.HubAdmin/UninstallModule', '/chain.v1.HubAdmin/UninstallModule',
@ -1119,6 +1152,11 @@ class HubAdminClient extends $grpc.Client {
'/chain.v1.HubAdmin/PullSystemAiModel', '/chain.v1.HubAdmin/PullSystemAiModel',
($0.PullSystemAiModelRequest value) => value.writeToBuffer(), ($0.PullSystemAiModelRequest value) => value.writeToBuffer(),
$0.PullSystemAiModelResponse.fromBuffer); $0.PullSystemAiModelResponse.fromBuffer);
static final _$pullSystemAiModelStream =
$grpc.ClientMethod<$0.PullSystemAiModelRequest, $0.PullProgressEvent>(
'/chain.v1.HubAdmin/PullSystemAiModelStream',
($0.PullSystemAiModelRequest value) => value.writeToBuffer(),
$0.PullProgressEvent.fromBuffer);
static final _$clearSystemLlmCache = static final _$clearSystemLlmCache =
$grpc.ClientMethod<$1.Empty, $0.ClearSystemLlmCacheResponse>( $grpc.ClientMethod<$1.Empty, $0.ClearSystemLlmCacheResponse>(
'/chain.v1.HubAdmin/ClearSystemLlmCache', '/chain.v1.HubAdmin/ClearSystemLlmCache',
@ -1285,6 +1323,15 @@ abstract class HubAdminServiceBase extends $grpc.Service {
($core.List<$core.int> value) => ($core.List<$core.int> value) =>
$0.InstallModuleRequest.fromBuffer(value), $0.InstallModuleRequest.fromBuffer(value),
($0.InstallModuleResponse value) => value.writeToBuffer())); ($0.InstallModuleResponse value) => value.writeToBuffer()));
$addMethod(
$grpc.ServiceMethod<$0.InstallModuleRequest, $0.InstallProgressEvent>(
'InstallModuleStream',
installModuleStream_Pre,
false,
true,
($core.List<$core.int> value) =>
$0.InstallModuleRequest.fromBuffer(value),
($0.InstallProgressEvent value) => value.writeToBuffer()));
$addMethod($grpc.ServiceMethod<$0.UninstallModuleRequest, $addMethod($grpc.ServiceMethod<$0.UninstallModuleRequest,
$0.UninstallModuleResponse>( $0.UninstallModuleResponse>(
'UninstallModule', 'UninstallModule',
@ -1550,6 +1597,15 @@ abstract class HubAdminServiceBase extends $grpc.Service {
($core.List<$core.int> value) => ($core.List<$core.int> value) =>
$0.PullSystemAiModelRequest.fromBuffer(value), $0.PullSystemAiModelRequest.fromBuffer(value),
($0.PullSystemAiModelResponse value) => value.writeToBuffer())); ($0.PullSystemAiModelResponse value) => value.writeToBuffer()));
$addMethod(
$grpc.ServiceMethod<$0.PullSystemAiModelRequest, $0.PullProgressEvent>(
'PullSystemAiModelStream',
pullSystemAiModelStream_Pre,
false,
true,
($core.List<$core.int> value) =>
$0.PullSystemAiModelRequest.fromBuffer(value),
($0.PullProgressEvent value) => value.writeToBuffer()));
$addMethod($grpc.ServiceMethod<$1.Empty, $0.ClearSystemLlmCacheResponse>( $addMethod($grpc.ServiceMethod<$1.Empty, $0.ClearSystemLlmCacheResponse>(
'ClearSystemLlmCache', 'ClearSystemLlmCache',
clearSystemLlmCache_Pre, clearSystemLlmCache_Pre,
@ -1737,6 +1793,15 @@ abstract class HubAdminServiceBase extends $grpc.Service {
$async.Future<$0.InstallModuleResponse> installModule( $async.Future<$0.InstallModuleResponse> installModule(
$grpc.ServiceCall call, $0.InstallModuleRequest request); $grpc.ServiceCall call, $0.InstallModuleRequest request);
$async.Stream<$0.InstallProgressEvent> installModuleStream_Pre(
$grpc.ServiceCall $call,
$async.Future<$0.InstallModuleRequest> $request) async* {
yield* installModuleStream($call, await $request);
}
$async.Stream<$0.InstallProgressEvent> installModuleStream(
$grpc.ServiceCall call, $0.InstallModuleRequest request);
$async.Future<$0.UninstallModuleResponse> uninstallModule_Pre( $async.Future<$0.UninstallModuleResponse> uninstallModule_Pre(
$grpc.ServiceCall $call, $grpc.ServiceCall $call,
$async.Future<$0.UninstallModuleRequest> $request) async { $async.Future<$0.UninstallModuleRequest> $request) async {
@ -2017,6 +2082,15 @@ abstract class HubAdminServiceBase extends $grpc.Service {
$async.Future<$0.PullSystemAiModelResponse> pullSystemAiModel( $async.Future<$0.PullSystemAiModelResponse> pullSystemAiModel(
$grpc.ServiceCall call, $0.PullSystemAiModelRequest request); $grpc.ServiceCall call, $0.PullSystemAiModelRequest request);
$async.Stream<$0.PullProgressEvent> pullSystemAiModelStream_Pre(
$grpc.ServiceCall $call,
$async.Future<$0.PullSystemAiModelRequest> $request) async* {
yield* pullSystemAiModelStream($call, await $request);
}
$async.Stream<$0.PullProgressEvent> pullSystemAiModelStream(
$grpc.ServiceCall call, $0.PullSystemAiModelRequest request);
$async.Future<$0.ClearSystemLlmCacheResponse> clearSystemLlmCache_Pre( $async.Future<$0.ClearSystemLlmCacheResponse> clearSystemLlmCache_Pre(
$grpc.ServiceCall $call, $async.Future<$1.Empty> $request) async { $grpc.ServiceCall $call, $async.Future<$1.Empty> $request) async {
return clearSystemLlmCache($call, await $request); return clearSystemLlmCache($call, await $request);

View file

@ -998,6 +998,73 @@ final $typed_data.Uint8List installModuleResponseDescriptor = $convert.base64Dec
'IgASgJUgd2ZXJzaW9uEikKEGNhcGFiaWxpdHlfY291bnQYAyABKAVSD2NhcGFiaWxpdHlDb3Vu' 'IgASgJUgd2ZXJzaW9uEikKEGNhcGFiaWxpdHlfY291bnQYAyABKAVSD2NhcGFiaWxpdHlDb3Vu'
'dA=='); 'dA==');
@$core.Deprecated('Use installProgressEventDescriptor instead')
const InstallProgressEvent$json = {
'1': 'InstallProgressEvent',
'2': [
{
'1': 'update',
'3': 1,
'4': 1,
'5': 11,
'6': '.chain.v1.InstallProgressUpdate',
'9': 0,
'10': 'update'
},
{
'1': 'finished',
'3': 2,
'4': 1,
'5': 11,
'6': '.chain.v1.InstallModuleResponse',
'9': 0,
'10': 'finished'
},
{'1': 'failed', '3': 3, '4': 1, '5': 9, '9': 0, '10': 'failed'},
],
'8': [
{'1': 'event'},
],
};
/// Descriptor for `InstallProgressEvent`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List installProgressEventDescriptor = $convert.base64Decode(
'ChRJbnN0YWxsUHJvZ3Jlc3NFdmVudBI5CgZ1cGRhdGUYASABKAsyHy5jaGFpbi52MS5JbnN0YW'
'xsUHJvZ3Jlc3NVcGRhdGVIAFIGdXBkYXRlEj0KCGZpbmlzaGVkGAIgASgLMh8uY2hhaW4udjEu'
'SW5zdGFsbE1vZHVsZVJlc3BvbnNlSABSCGZpbmlzaGVkEhgKBmZhaWxlZBgDIAEoCUgAUgZmYW'
'lsZWRCBwoFZXZlbnQ=');
@$core.Deprecated('Use installProgressUpdateDescriptor instead')
const InstallProgressUpdate$json = {
'1': 'InstallProgressUpdate',
'2': [
{'1': 'phase', '3': 1, '4': 1, '5': 9, '10': 'phase'},
{'1': 'stage', '3': 2, '4': 1, '5': 9, '10': 'stage'},
{
'1': 'percent',
'3': 3,
'4': 1,
'5': 2,
'9': 0,
'10': 'percent',
'17': true
},
{'1': 'bytes_received', '3': 4, '4': 1, '5': 4, '10': 'bytesReceived'},
{'1': 'bytes_total', '3': 5, '4': 1, '5': 4, '10': 'bytesTotal'},
{'1': 'phase_done', '3': 6, '4': 1, '5': 8, '10': 'phaseDone'},
],
'8': [
{'1': '_percent'},
],
};
/// Descriptor for `InstallProgressUpdate`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List installProgressUpdateDescriptor = $convert.base64Decode(
'ChVJbnN0YWxsUHJvZ3Jlc3NVcGRhdGUSFAoFcGhhc2UYASABKAlSBXBoYXNlEhQKBXN0YWdlGA'
'IgASgJUgVzdGFnZRIdCgdwZXJjZW50GAMgASgCSABSB3BlcmNlbnSIAQESJQoOYnl0ZXNfcmVj'
'ZWl2ZWQYBCABKARSDWJ5dGVzUmVjZWl2ZWQSHwoLYnl0ZXNfdG90YWwYBSABKARSCmJ5dGVzVG'
'90YWwSHQoKcGhhc2VfZG9uZRgGIAEoCFIJcGhhc2VEb25lQgoKCF9wZXJjZW50');
@$core.Deprecated('Use uninstallModuleRequestDescriptor instead') @$core.Deprecated('Use uninstallModuleRequestDescriptor instead')
const UninstallModuleRequest$json = { const UninstallModuleRequest$json = {
'1': 'UninstallModuleRequest', '1': 'UninstallModuleRequest',
@ -1414,6 +1481,19 @@ const StoreEntry$json = {
'10': 'installVerification' '10': 'installVerification'
}, },
{'1': 'maintainers', '3': 26, '4': 3, '5': 9, '10': 'maintainers'}, {'1': 'maintainers', '3': 26, '4': 3, '5': 9, '10': 'maintainers'},
{
'1': 'data_source',
'3': 27,
'4': 1,
'5': 11,
'6': '.chain.v1.DataSource',
'9': 0,
'10': 'dataSource',
'17': true
},
],
'8': [
{'1': '_data_source'},
], ],
}; };
@ -1434,7 +1514,25 @@ final $typed_data.Uint8List storeEntryDescriptor = $convert.base64Decode(
'aW5kEhYKBnNvdXJjZRgWIAEoCVIGc291cmNlEi0KEmNhbm9uaWNhbF9jYXRlZ29yeRgXIAEoCV' 'aW5kEhYKBnNvdXJjZRgWIAEoCVIGc291cmNlEi0KEmNhbm9uaWNhbF9jYXRlZ29yeRgXIAEoCV'
'IRY2Fub25pY2FsQ2F0ZWdvcnkSOAoYY2Fub25pY2FsX2NhdGVnb3J5X2xhYmVsGBggASgJUhZj' 'IRY2Fub25pY2FsQ2F0ZWdvcnkSOAoYY2Fub25pY2FsX2NhdGVnb3J5X2xhYmVsGBggASgJUhZj'
'YW5vbmljYWxDYXRlZ29yeUxhYmVsEjEKFGluc3RhbGxfdmVyaWZpY2F0aW9uGBkgASgJUhNpbn' 'YW5vbmljYWxDYXRlZ29yeUxhYmVsEjEKFGluc3RhbGxfdmVyaWZpY2F0aW9uGBkgASgJUhNpbn'
'N0YWxsVmVyaWZpY2F0aW9uEiAKC21haW50YWluZXJzGBogAygJUgttYWludGFpbmVycw=='); 'N0YWxsVmVyaWZpY2F0aW9uEiAKC21haW50YWluZXJzGBogAygJUgttYWludGFpbmVycxI6Cgtk'
'YXRhX3NvdXJjZRgbIAEoCzIULmNoYWluLnYxLkRhdGFTb3VyY2VIAFIKZGF0YVNvdXJjZYgBAU'
'IOCgxfZGF0YV9zb3VyY2U=');
@$core.Deprecated('Use dataSourceDescriptor instead')
const DataSource$json = {
'1': 'DataSource',
'2': [
{'1': 'name', '3': 1, '4': 1, '5': 9, '10': 'name'},
{'1': 'url', '3': 2, '4': 1, '5': 9, '10': 'url'},
{'1': 'license', '3': 3, '4': 1, '5': 9, '10': 'license'},
{'1': 'attribution', '3': 4, '4': 1, '5': 9, '10': 'attribution'},
],
};
/// Descriptor for `DataSource`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List dataSourceDescriptor = $convert.base64Decode(
'CgpEYXRhU291cmNlEhIKBG5hbWUYASABKAlSBG5hbWUSEAoDdXJsGAIgASgJUgN1cmwSGAoHbG'
'ljZW5zZRgDIAEoCVIHbGljZW5zZRIgCgthdHRyaWJ1dGlvbhgEIAEoCVILYXR0cmlidXRpb24=');
@$core.Deprecated('Use channelStatusResponseDescriptor instead') @$core.Deprecated('Use channelStatusResponseDescriptor instead')
const ChannelStatusResponse$json = { const ChannelStatusResponse$json = {
@ -1701,6 +1799,55 @@ final $typed_data.Uint8List pullSystemAiModelResponseDescriptor = $convert.base6
'ChlQdWxsU3lzdGVtQWlNb2RlbFJlc3BvbnNlEh0KCmVycm9yX2tpbmQYASABKAlSCWVycm9yS2' 'ChlQdWxsU3lzdGVtQWlNb2RlbFJlc3BvbnNlEh0KCmVycm9yX2tpbmQYASABKAlSCWVycm9yS2'
'luZBISCgR0ZXh0GAIgASgJUgR0ZXh0Eh0KCmVsYXBzZWRfbXMYAyABKA1SCWVsYXBzZWRNcw=='); 'luZBISCgR0ZXh0GAIgASgJUgR0ZXh0Eh0KCmVsYXBzZWRfbXMYAyABKA1SCWVsYXBzZWRNcw==');
@$core.Deprecated('Use pullProgressEventDescriptor instead')
const PullProgressEvent$json = {
'1': 'PullProgressEvent',
'2': [
{
'1': 'update',
'3': 1,
'4': 1,
'5': 11,
'6': '.chain.v1.PullProgressUpdate',
'9': 0,
'10': 'update'
},
{
'1': 'finished',
'3': 2,
'4': 1,
'5': 11,
'6': '.chain.v1.PullSystemAiModelResponse',
'9': 0,
'10': 'finished'
},
],
'8': [
{'1': 'event'},
],
};
/// Descriptor for `PullProgressEvent`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List pullProgressEventDescriptor = $convert.base64Decode(
'ChFQdWxsUHJvZ3Jlc3NFdmVudBI2CgZ1cGRhdGUYASABKAsyHC5jaGFpbi52MS5QdWxsUHJvZ3'
'Jlc3NVcGRhdGVIAFIGdXBkYXRlEkEKCGZpbmlzaGVkGAIgASgLMiMuY2hhaW4udjEuUHVsbFN5'
'c3RlbUFpTW9kZWxSZXNwb25zZUgAUghmaW5pc2hlZEIHCgVldmVudA==');
@$core.Deprecated('Use pullProgressUpdateDescriptor instead')
const PullProgressUpdate$json = {
'1': 'PullProgressUpdate',
'2': [
{'1': 'status', '3': 1, '4': 1, '5': 9, '10': 'status'},
{'1': 'completed', '3': 2, '4': 1, '5': 4, '10': 'completed'},
{'1': 'total', '3': 3, '4': 1, '5': 4, '10': 'total'},
],
};
/// Descriptor for `PullProgressUpdate`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List pullProgressUpdateDescriptor = $convert.base64Decode(
'ChJQdWxsUHJvZ3Jlc3NVcGRhdGUSFgoGc3RhdHVzGAEgASgJUgZzdGF0dXMSHAoJY29tcGxldG'
'VkGAIgASgEUgljb21wbGV0ZWQSFAoFdG90YWwYAyABKARSBXRvdGFs');
@$core.Deprecated('Use hardwareInfoResponseDescriptor instead') @$core.Deprecated('Use hardwareInfoResponseDescriptor instead')
const HardwareInfoResponse$json = { const HardwareInfoResponse$json = {
'1': 'HardwareInfoResponse', '1': 'HardwareInfoResponse',

View file

@ -110,6 +110,8 @@ typedef ProjectInfo = pb.ProjectInfo;
typedef StoreEntry = pb.StoreEntry; typedef StoreEntry = pb.StoreEntry;
typedef StoreSearchResponse = pb.StoreSearchResponse; typedef StoreSearchResponse = pb.StoreSearchResponse;
typedef InstallModuleResponse = pb.InstallModuleResponse; typedef InstallModuleResponse = pb.InstallModuleResponse;
typedef InstallProgressUpdate = pb.InstallProgressUpdate;
typedef PullProgressUpdate = pb.PullProgressUpdate;
typedef Payload = pb_common.Payload; typedef Payload = pb_common.Payload;
typedef SubmitResponse = pb.SubmitResponse; typedef SubmitResponse = pb.SubmitResponse;
// Live-stream (T2) + detached-invocation (T3) wire types, re-exported // Live-stream (T2) + detached-invocation (T3) wire types, re-exported
@ -831,6 +833,69 @@ class HubClient {
)); ));
} }
/// Install a module while watching it happen.
///
/// Emits an update per phase and, during the download, as bytes
/// arrive. The stream completes when the install succeeds, and
/// carries the hub's failure text as a stream error when it does
/// not, so callers handle failures the same way as with
/// [installModule]. Use [onFinished] to receive the installed
/// module's name and version.
///
/// A caller that only needs the outcome should keep using the
/// unary [installModule]; this exists so a waiting operator can
/// see that a slow download is progressing rather than hung.
Stream<InstallProgressUpdate> installModuleStreaming({
required String source,
String expectedSha256 = '',
String version = '',
void Function(InstallModuleResponse result)? onFinished,
}) async* {
final stream = _admin.installModuleStream(pb.InstallModuleRequest(
source: source,
expectedSha256: expectedSha256,
version: version,
));
await for (final event in stream) {
if (event.hasUpdate()) {
yield event.update;
} else if (event.hasFinished()) {
onFinished?.call(event.finished);
return;
} else if (event.hasFailed()) {
throw Exception(event.failed);
}
}
}
/// 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 /// All saved flows known to the hub. Each entry carries the
/// flow name, on-disk path and byte size. /// flow name, on-disk path and byte size.
Future<List<FlowSummary>> listFlows() async { Future<List<FlowSummary>> listFlows() async {