diff --git a/lib/src/generated/fai/v1/hub.pb.dart b/lib/src/generated/fai/v1/hub.pb.dart index a105731..814fd8d 100644 --- a/lib/src/generated/fai/v1/hub.pb.dart +++ b/lib/src/generated/fai/v1/hub.pb.dart @@ -3037,6 +3037,114 @@ class AskAiResponse extends $pb.GeneratedMessage { void clearLatencyMs() => $_clearField(3); } +class UpdateSystemAiRequest extends $pb.GeneratedMessage { + factory UpdateSystemAiRequest({ + $core.String? provider, + $core.String? endpoint, + $core.String? model, + $core.String? apiKeyEnv, + $core.String? privacyMode, + }) { + final $result = create(); + if (provider != null) { + $result.provider = provider; + } + if (endpoint != null) { + $result.endpoint = endpoint; + } + if (model != null) { + $result.model = model; + } + if (apiKeyEnv != null) { + $result.apiKeyEnv = apiKeyEnv; + } + if (privacyMode != null) { + $result.privacyMode = privacyMode; + } + return $result; + } + UpdateSystemAiRequest._() : super(); + factory UpdateSystemAiRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory UpdateSystemAiRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'UpdateSystemAiRequest', package: const $pb.PackageName(_omitMessageNames ? '' : 'fai.v1'), createEmptyInstance: create) + ..aOS(1, _omitFieldNames ? '' : 'provider') + ..aOS(2, _omitFieldNames ? '' : 'endpoint') + ..aOS(3, _omitFieldNames ? '' : 'model') + ..aOS(4, _omitFieldNames ? '' : 'apiKeyEnv') + ..aOS(5, _omitFieldNames ? '' : 'privacyMode') + ..hasRequiredFields = false + ; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + UpdateSystemAiRequest clone() => UpdateSystemAiRequest()..mergeFromMessage(this); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + UpdateSystemAiRequest copyWith(void Function(UpdateSystemAiRequest) updates) => super.copyWith((message) => updates(message as UpdateSystemAiRequest)) as UpdateSystemAiRequest; + + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static UpdateSystemAiRequest create() => UpdateSystemAiRequest._(); + UpdateSystemAiRequest createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static UpdateSystemAiRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static UpdateSystemAiRequest? _defaultInstance; + + /// ollama / openai / lmstudio / vllm / custom (defaults to + /// ollama if empty). + @$pb.TagNumber(1) + $core.String get provider => $_getSZ(0); + @$pb.TagNumber(1) + set provider($core.String v) { $_setString(0, v); } + @$pb.TagNumber(1) + $core.bool hasProvider() => $_has(0); + @$pb.TagNumber(1) + void clearProvider() => $_clearField(1); + + /// Full URL up to and including /v1. Empty + privacy_mode!=off + /// → returns InvalidArgument. + @$pb.TagNumber(2) + $core.String get endpoint => $_getSZ(1); + @$pb.TagNumber(2) + set endpoint($core.String v) { $_setString(1, v); } + @$pb.TagNumber(2) + $core.bool hasEndpoint() => $_has(1); + @$pb.TagNumber(2) + void clearEndpoint() => $_clearField(2); + + /// Model identifier the provider expects. Empty + + /// privacy_mode!=off → returns InvalidArgument. + @$pb.TagNumber(3) + $core.String get model => $_getSZ(2); + @$pb.TagNumber(3) + set model($core.String v) { $_setString(2, v); } + @$pb.TagNumber(3) + $core.bool hasModel() => $_has(2); + @$pb.TagNumber(3) + void clearModel() => $_clearField(3); + + /// Name of the env var holding the API key. Empty = no auth. + @$pb.TagNumber(4) + $core.String get apiKeyEnv => $_getSZ(3); + @$pb.TagNumber(4) + set apiKeyEnv($core.String v) { $_setString(3, v); } + @$pb.TagNumber(4) + $core.bool hasApiKeyEnv() => $_has(3); + @$pb.TagNumber(4) + void clearApiKeyEnv() => $_clearField(4); + + /// off / redacted / full. Empty defaults to "off". + @$pb.TagNumber(5) + $core.String get privacyMode => $_getSZ(4); + @$pb.TagNumber(5) + set privacyMode($core.String v) { $_setString(4, v); } + @$pb.TagNumber(5) + $core.bool hasPrivacyMode() => $_has(4); + @$pb.TagNumber(5) + void clearPrivacyMode() => $_clearField(5); +} + const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names'); const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names'); diff --git a/lib/src/generated/fai/v1/hub.pbgrpc.dart b/lib/src/generated/fai/v1/hub.pbgrpc.dart index f2bd092..0c5cd2d 100644 --- a/lib/src/generated/fai/v1/hub.pbgrpc.dart +++ b/lib/src/generated/fai/v1/hub.pbgrpc.dart @@ -195,6 +195,14 @@ class HubAdminClient extends $grpc.Client { '/fai.v1.HubAdmin/AskAi', ($0.AskAiRequest value) => value.writeToBuffer(), ($core.List<$core.int> value) => $0.AskAiResponse.fromBuffer(value)); + static final _$updateSystemAi = $grpc.ClientMethod<$0.UpdateSystemAiRequest, $0.SystemAiStatusResponse>( + '/fai.v1.HubAdmin/UpdateSystemAi', + ($0.UpdateSystemAiRequest value) => value.writeToBuffer(), + ($core.List<$core.int> value) => $0.SystemAiStatusResponse.fromBuffer(value)); + static final _$testSystemAi = $grpc.ClientMethod<$1.Empty, $0.AskAiResponse>( + '/fai.v1.HubAdmin/TestSystemAi', + ($1.Empty value) => value.writeToBuffer(), + ($core.List<$core.int> value) => $0.AskAiResponse.fromBuffer(value)); HubAdminClient(super.channel, {super.options, super.interceptors}); @@ -306,6 +314,23 @@ class HubAdminClient extends $grpc.Client { $grpc.ResponseFuture<$0.AskAiResponse> askAi($0.AskAiRequest request, {$grpc.CallOptions? options}) { return $createUnaryCall(_$askAi, request, options: options); } + + /// Persist a new system-AI configuration. Updates the live + /// hub state AND writes back to ~/.fai/config.yaml so the + /// change survives daemon restart. Used by Studio's settings + /// editor. Returns the resulting status (same shape as + /// SystemAiStatus) so the UI can refresh in one round-trip. + $grpc.ResponseFuture<$0.SystemAiStatusResponse> updateSystemAi($0.UpdateSystemAiRequest request, {$grpc.CallOptions? options}) { + return $createUnaryCall(_$updateSystemAi, request, options: options); + } + + /// Probe the configured provider with an empty ping (model + /// listing or short message). Returns the same error_kind + /// taxonomy as AskAi so Studio's "Test connection" button + /// can render the same inline fix copy. + $grpc.ResponseFuture<$0.AskAiResponse> testSystemAi($1.Empty request, {$grpc.CallOptions? options}) { + return $createUnaryCall(_$testSystemAi, request, options: options); + } } @$pb.GrpcServiceName('fai.v1.HubAdmin') @@ -439,6 +464,20 @@ abstract class HubAdminServiceBase extends $grpc.Service { false, ($core.List<$core.int> value) => $0.AskAiRequest.fromBuffer(value), ($0.AskAiResponse value) => value.writeToBuffer())); + $addMethod($grpc.ServiceMethod<$0.UpdateSystemAiRequest, $0.SystemAiStatusResponse>( + 'UpdateSystemAi', + updateSystemAi_Pre, + false, + false, + ($core.List<$core.int> value) => $0.UpdateSystemAiRequest.fromBuffer(value), + ($0.SystemAiStatusResponse value) => value.writeToBuffer())); + $addMethod($grpc.ServiceMethod<$1.Empty, $0.AskAiResponse>( + 'TestSystemAi', + testSystemAi_Pre, + false, + false, + ($core.List<$core.int> value) => $1.Empty.fromBuffer(value), + ($0.AskAiResponse value) => value.writeToBuffer())); } $async.Future<$0.CapabilityList> listCapabilities_Pre($grpc.ServiceCall $call, $async.Future<$1.Empty> $request) async { @@ -513,6 +552,14 @@ abstract class HubAdminServiceBase extends $grpc.Service { return askAi($call, await $request); } + $async.Future<$0.SystemAiStatusResponse> updateSystemAi_Pre($grpc.ServiceCall $call, $async.Future<$0.UpdateSystemAiRequest> $request) async { + return updateSystemAi($call, await $request); + } + + $async.Future<$0.AskAiResponse> testSystemAi_Pre($grpc.ServiceCall $call, $async.Future<$1.Empty> $request) async { + return testSystemAi($call, await $request); + } + $async.Future<$0.CapabilityList> listCapabilities($grpc.ServiceCall call, $1.Empty request); $async.Future<$0.ModuleInfoResponse> moduleInfo($grpc.ServiceCall call, $0.ModuleInfoRequest request); $async.Future<$0.CheckPermissionResponse> checkPermission($grpc.ServiceCall call, $0.CheckPermissionRequest request); @@ -531,4 +578,6 @@ abstract class HubAdminServiceBase extends $grpc.Service { $async.Future<$0.ChannelStatusResponse> channelStatus($grpc.ServiceCall call, $1.Empty request); $async.Future<$0.SystemAiStatusResponse> systemAiStatus($grpc.ServiceCall call, $1.Empty request); $async.Future<$0.AskAiResponse> askAi($grpc.ServiceCall call, $0.AskAiRequest request); + $async.Future<$0.SystemAiStatusResponse> updateSystemAi($grpc.ServiceCall call, $0.UpdateSystemAiRequest request); + $async.Future<$0.AskAiResponse> testSystemAi($grpc.ServiceCall call, $1.Empty request); } diff --git a/lib/src/generated/fai/v1/hub.pbjson.dart b/lib/src/generated/fai/v1/hub.pbjson.dart index 612c1e1..48df095 100644 --- a/lib/src/generated/fai/v1/hub.pbjson.dart +++ b/lib/src/generated/fai/v1/hub.pbjson.dart @@ -716,3 +716,22 @@ final $typed_data.Uint8List askAiResponseDescriptor = $convert.base64Decode( 'Cg1Bc2tBaVJlc3BvbnNlEh0KCmVycm9yX2tpbmQYASABKAlSCWVycm9yS2luZBISCgR0ZXh0GA' 'IgASgJUgR0ZXh0Eh0KCmxhdGVuY3lfbXMYAyABKA1SCWxhdGVuY3lNcw=='); +@$core.Deprecated('Use updateSystemAiRequestDescriptor instead') +const UpdateSystemAiRequest$json = { + '1': 'UpdateSystemAiRequest', + '2': [ + {'1': 'provider', '3': 1, '4': 1, '5': 9, '10': 'provider'}, + {'1': 'endpoint', '3': 2, '4': 1, '5': 9, '10': 'endpoint'}, + {'1': 'model', '3': 3, '4': 1, '5': 9, '10': 'model'}, + {'1': 'api_key_env', '3': 4, '4': 1, '5': 9, '10': 'apiKeyEnv'}, + {'1': 'privacy_mode', '3': 5, '4': 1, '5': 9, '10': 'privacyMode'}, + ], +}; + +/// Descriptor for `UpdateSystemAiRequest`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List updateSystemAiRequestDescriptor = $convert.base64Decode( + 'ChVVcGRhdGVTeXN0ZW1BaVJlcXVlc3QSGgoIcHJvdmlkZXIYASABKAlSCHByb3ZpZGVyEhoKCG' + 'VuZHBvaW50GAIgASgJUghlbmRwb2ludBIUCgVtb2RlbBgDIAEoCVIFbW9kZWwSHgoLYXBpX2tl' + 'eV9lbnYYBCABKAlSCWFwaUtleUVudhIhCgxwcml2YWN5X21vZGUYBSABKAlSC3ByaXZhY3lNb2' + 'Rl'); + diff --git a/lib/src/hub_client.dart b/lib/src/hub_client.dart index c855595..7898190 100644 --- a/lib/src/hub_client.dart +++ b/lib/src/hub_client.dart @@ -199,6 +199,32 @@ class HubClient { return _admin.askAi(pb.AskAiRequest(prompt: prompt)); } + /// Persist a new System-AI configuration. Validates + + /// writes back to ~/.fai/config.yaml + hot-reloads the live + /// hub state in one call. Returns the resulting status so + /// the UI can refresh in one round-trip. + Future updateSystemAi({ + required String provider, + required String endpoint, + required String model, + required String apiKeyEnv, + required String privacyMode, + }) { + return _admin.updateSystemAi(pb.UpdateSystemAiRequest( + provider: provider, + endpoint: endpoint, + model: model, + apiKeyEnv: apiKeyEnv, + privacyMode: privacyMode, + )); + } + + /// Probe the configured provider with a tiny ping. Same + /// error-kind taxonomy as [askAi]. + Future testSystemAi() { + return _admin.testSystemAi(Empty()); + } + /// Search the hub's bundled store index. All filters are /// optional; an empty query returns the first [limit] entries /// the index ships with. diff --git a/pubspec.yaml b/pubspec.yaml index 8dd5ecb..ede5387 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: fai_dart_sdk description: gRPC client SDK for the F∆I Platform hub. Used by F∆I Studio and Tier-3 domain apps. -version: 0.4.0 +version: 0.5.0 publish_to: 'none' repository: https://git.flemming.ws/fai/dart-sdk