feat: SystemAiStatus + AskAi RPCs (v0.4.0)
`HubClient.systemAiStatus()` reports whether the hub-internal LLM hook is configured and which provider / privacy mode is active. `HubClient.askAi(prompt)` issues a one-shot prompt and returns the answer or a structured error kind so the UI can map each failure to its inline-fix copy. LoggedEvent gains `detail` upstream (no SDK change required). Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
parent
73dbdc16ef
commit
f0db42264f
5 changed files with 358 additions and 1 deletions
|
|
@ -2789,6 +2789,254 @@ class CheckUpdateResponse extends $pb.GeneratedMessage {
|
|||
void clearManifestUrl() => $_clearField(9);
|
||||
}
|
||||
|
||||
class SystemAiStatusResponse extends $pb.GeneratedMessage {
|
||||
factory SystemAiStatusResponse({
|
||||
$core.bool? enabled,
|
||||
$core.String? provider,
|
||||
$core.String? endpoint,
|
||||
$core.String? model,
|
||||
$core.String? privacyMode,
|
||||
$core.String? apiKeyEnv,
|
||||
}) {
|
||||
final $result = create();
|
||||
if (enabled != null) {
|
||||
$result.enabled = enabled;
|
||||
}
|
||||
if (provider != null) {
|
||||
$result.provider = provider;
|
||||
}
|
||||
if (endpoint != null) {
|
||||
$result.endpoint = endpoint;
|
||||
}
|
||||
if (model != null) {
|
||||
$result.model = model;
|
||||
}
|
||||
if (privacyMode != null) {
|
||||
$result.privacyMode = privacyMode;
|
||||
}
|
||||
if (apiKeyEnv != null) {
|
||||
$result.apiKeyEnv = apiKeyEnv;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
SystemAiStatusResponse._() : super();
|
||||
factory SystemAiStatusResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory SystemAiStatusResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'SystemAiStatusResponse', package: const $pb.PackageName(_omitMessageNames ? '' : 'fai.v1'), createEmptyInstance: create)
|
||||
..aOB(1, _omitFieldNames ? '' : 'enabled')
|
||||
..aOS(2, _omitFieldNames ? '' : 'provider')
|
||||
..aOS(3, _omitFieldNames ? '' : 'endpoint')
|
||||
..aOS(4, _omitFieldNames ? '' : 'model')
|
||||
..aOS(5, _omitFieldNames ? '' : 'privacyMode')
|
||||
..aOS(6, _omitFieldNames ? '' : 'apiKeyEnv')
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||
SystemAiStatusResponse clone() => SystemAiStatusResponse()..mergeFromMessage(this);
|
||||
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||
SystemAiStatusResponse copyWith(void Function(SystemAiStatusResponse) updates) => super.copyWith((message) => updates(message as SystemAiStatusResponse)) as SystemAiStatusResponse;
|
||||
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static SystemAiStatusResponse create() => SystemAiStatusResponse._();
|
||||
SystemAiStatusResponse createEmptyInstance() => create();
|
||||
static $pb.PbList<SystemAiStatusResponse> createRepeated() => $pb.PbList<SystemAiStatusResponse>();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static SystemAiStatusResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<SystemAiStatusResponse>(create);
|
||||
static SystemAiStatusResponse? _defaultInstance;
|
||||
|
||||
/// True iff `system_llm` is configured AND privacy_mode != off.
|
||||
@$pb.TagNumber(1)
|
||||
$core.bool get enabled => $_getBF(0);
|
||||
@$pb.TagNumber(1)
|
||||
set enabled($core.bool v) { $_setBool(0, v); }
|
||||
@$pb.TagNumber(1)
|
||||
$core.bool hasEnabled() => $_has(0);
|
||||
@$pb.TagNumber(1)
|
||||
void clearEnabled() => $_clearField(1);
|
||||
|
||||
/// openai / anthropic / "" — empty when disabled.
|
||||
@$pb.TagNumber(2)
|
||||
$core.String get provider => $_getSZ(1);
|
||||
@$pb.TagNumber(2)
|
||||
set provider($core.String v) { $_setString(1, v); }
|
||||
@$pb.TagNumber(2)
|
||||
$core.bool hasProvider() => $_has(1);
|
||||
@$pb.TagNumber(2)
|
||||
void clearProvider() => $_clearField(2);
|
||||
|
||||
/// The endpoint URL the operator configured. Empty when disabled.
|
||||
@$pb.TagNumber(3)
|
||||
$core.String get endpoint => $_getSZ(2);
|
||||
@$pb.TagNumber(3)
|
||||
set endpoint($core.String v) { $_setString(2, v); }
|
||||
@$pb.TagNumber(3)
|
||||
$core.bool hasEndpoint() => $_has(2);
|
||||
@$pb.TagNumber(3)
|
||||
void clearEndpoint() => $_clearField(3);
|
||||
|
||||
/// Model identifier. Empty when disabled.
|
||||
@$pb.TagNumber(4)
|
||||
$core.String get model => $_getSZ(3);
|
||||
@$pb.TagNumber(4)
|
||||
set model($core.String v) { $_setString(3, v); }
|
||||
@$pb.TagNumber(4)
|
||||
$core.bool hasModel() => $_has(3);
|
||||
@$pb.TagNumber(4)
|
||||
void clearModel() => $_clearField(4);
|
||||
|
||||
/// off / redacted / full — never empty.
|
||||
@$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);
|
||||
|
||||
/// Name of the env var holding the API key (empty = no auth).
|
||||
/// Studio's settings page renders the *name*; never the value.
|
||||
@$pb.TagNumber(6)
|
||||
$core.String get apiKeyEnv => $_getSZ(5);
|
||||
@$pb.TagNumber(6)
|
||||
set apiKeyEnv($core.String v) { $_setString(5, v); }
|
||||
@$pb.TagNumber(6)
|
||||
$core.bool hasApiKeyEnv() => $_has(5);
|
||||
@$pb.TagNumber(6)
|
||||
void clearApiKeyEnv() => $_clearField(6);
|
||||
}
|
||||
|
||||
class AskAiRequest extends $pb.GeneratedMessage {
|
||||
factory AskAiRequest({
|
||||
$core.String? prompt,
|
||||
}) {
|
||||
final $result = create();
|
||||
if (prompt != null) {
|
||||
$result.prompt = prompt;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
AskAiRequest._() : super();
|
||||
factory AskAiRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory AskAiRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'AskAiRequest', package: const $pb.PackageName(_omitMessageNames ? '' : 'fai.v1'), createEmptyInstance: create)
|
||||
..aOS(1, _omitFieldNames ? '' : 'prompt')
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||
AskAiRequest clone() => AskAiRequest()..mergeFromMessage(this);
|
||||
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||
AskAiRequest copyWith(void Function(AskAiRequest) updates) => super.copyWith((message) => updates(message as AskAiRequest)) as AskAiRequest;
|
||||
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static AskAiRequest create() => AskAiRequest._();
|
||||
AskAiRequest createEmptyInstance() => create();
|
||||
static $pb.PbList<AskAiRequest> createRepeated() => $pb.PbList<AskAiRequest>();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static AskAiRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<AskAiRequest>(create);
|
||||
static AskAiRequest? _defaultInstance;
|
||||
|
||||
/// The prompt the operator wants answered. Studio assembles
|
||||
/// this client-side from the audit event being explained
|
||||
/// and the chosen privacy mode.
|
||||
@$pb.TagNumber(1)
|
||||
$core.String get prompt => $_getSZ(0);
|
||||
@$pb.TagNumber(1)
|
||||
set prompt($core.String v) { $_setString(0, v); }
|
||||
@$pb.TagNumber(1)
|
||||
$core.bool hasPrompt() => $_has(0);
|
||||
@$pb.TagNumber(1)
|
||||
void clearPrompt() => $_clearField(1);
|
||||
}
|
||||
|
||||
class AskAiResponse extends $pb.GeneratedMessage {
|
||||
factory AskAiResponse({
|
||||
$core.String? errorKind,
|
||||
$core.String? text,
|
||||
$core.int? latencyMs,
|
||||
}) {
|
||||
final $result = create();
|
||||
if (errorKind != null) {
|
||||
$result.errorKind = errorKind;
|
||||
}
|
||||
if (text != null) {
|
||||
$result.text = text;
|
||||
}
|
||||
if (latencyMs != null) {
|
||||
$result.latencyMs = latencyMs;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
AskAiResponse._() : super();
|
||||
factory AskAiResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory AskAiResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'AskAiResponse', package: const $pb.PackageName(_omitMessageNames ? '' : 'fai.v1'), createEmptyInstance: create)
|
||||
..aOS(1, _omitFieldNames ? '' : 'errorKind')
|
||||
..aOS(2, _omitFieldNames ? '' : 'text')
|
||||
..a<$core.int>(3, _omitFieldNames ? '' : 'latencyMs', $pb.PbFieldType.OU3)
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||
AskAiResponse clone() => AskAiResponse()..mergeFromMessage(this);
|
||||
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||
AskAiResponse copyWith(void Function(AskAiResponse) updates) => super.copyWith((message) => updates(message as AskAiResponse)) as AskAiResponse;
|
||||
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static AskAiResponse create() => AskAiResponse._();
|
||||
AskAiResponse createEmptyInstance() => create();
|
||||
static $pb.PbList<AskAiResponse> createRepeated() => $pb.PbList<AskAiResponse>();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static AskAiResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<AskAiResponse>(create);
|
||||
static AskAiResponse? _defaultInstance;
|
||||
|
||||
/// Failure category, mapped from `system_llm::SystemLlmError`.
|
||||
/// Empty on success. Studio surfaces each value with a fix hint.
|
||||
/// Values: "" (success), "disabled", "env_missing", "network",
|
||||
/// "http", "parse", "empty_response".
|
||||
@$pb.TagNumber(1)
|
||||
$core.String get errorKind => $_getSZ(0);
|
||||
@$pb.TagNumber(1)
|
||||
set errorKind($core.String v) { $_setString(0, v); }
|
||||
@$pb.TagNumber(1)
|
||||
$core.bool hasErrorKind() => $_has(0);
|
||||
@$pb.TagNumber(1)
|
||||
void clearErrorKind() => $_clearField(1);
|
||||
|
||||
/// Human-readable diagnostic / answer. Always populated:
|
||||
/// either the assistant text on success, or the error detail
|
||||
/// on failure.
|
||||
@$pb.TagNumber(2)
|
||||
$core.String get text => $_getSZ(1);
|
||||
@$pb.TagNumber(2)
|
||||
set text($core.String v) { $_setString(1, v); }
|
||||
@$pb.TagNumber(2)
|
||||
$core.bool hasText() => $_has(1);
|
||||
@$pb.TagNumber(2)
|
||||
void clearText() => $_clearField(2);
|
||||
|
||||
/// Round-trip latency in milliseconds (success only).
|
||||
@$pb.TagNumber(3)
|
||||
$core.int get latencyMs => $_getIZ(2);
|
||||
@$pb.TagNumber(3)
|
||||
set latencyMs($core.int v) { $_setUnsignedInt32(2, v); }
|
||||
@$pb.TagNumber(3)
|
||||
$core.bool hasLatencyMs() => $_has(2);
|
||||
@$pb.TagNumber(3)
|
||||
void clearLatencyMs() => $_clearField(3);
|
||||
}
|
||||
|
||||
|
||||
const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names');
|
||||
const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names');
|
||||
|
|
|
|||
|
|
@ -187,6 +187,14 @@ class HubAdminClient extends $grpc.Client {
|
|||
'/fai.v1.HubAdmin/ChannelStatus',
|
||||
($1.Empty value) => value.writeToBuffer(),
|
||||
($core.List<$core.int> value) => $0.ChannelStatusResponse.fromBuffer(value));
|
||||
static final _$systemAiStatus = $grpc.ClientMethod<$1.Empty, $0.SystemAiStatusResponse>(
|
||||
'/fai.v1.HubAdmin/SystemAiStatus',
|
||||
($1.Empty value) => value.writeToBuffer(),
|
||||
($core.List<$core.int> value) => $0.SystemAiStatusResponse.fromBuffer(value));
|
||||
static final _$askAi = $grpc.ClientMethod<$0.AskAiRequest, $0.AskAiResponse>(
|
||||
'/fai.v1.HubAdmin/AskAi',
|
||||
($0.AskAiRequest value) => value.writeToBuffer(),
|
||||
($core.List<$core.int> value) => $0.AskAiResponse.fromBuffer(value));
|
||||
|
||||
HubAdminClient(super.channel, {super.options, super.interceptors});
|
||||
|
||||
|
|
@ -283,6 +291,21 @@ class HubAdminClient extends $grpc.Client {
|
|||
$grpc.ResponseFuture<$0.ChannelStatusResponse> channelStatus($1.Empty request, {$grpc.CallOptions? options}) {
|
||||
return $createUnaryCall(_$channelStatus, request, options: options);
|
||||
}
|
||||
|
||||
/// Read-only system-AI status. Lets Studio render the
|
||||
/// "configure in Settings" affordance when the feature is
|
||||
/// off, and the privacy-mode badge when it is on.
|
||||
$grpc.ResponseFuture<$0.SystemAiStatusResponse> systemAiStatus($1.Empty request, {$grpc.CallOptions? options}) {
|
||||
return $createUnaryCall(_$systemAiStatus, request, options: options);
|
||||
}
|
||||
|
||||
/// Ask the system AI a one-shot question. Errors carry the
|
||||
/// failure category (disabled / env-missing / http / parse)
|
||||
/// so Studio can map them to the inline-fix-hint copy from
|
||||
/// `docs/architecture/system-ai.md`.
|
||||
$grpc.ResponseFuture<$0.AskAiResponse> askAi($0.AskAiRequest request, {$grpc.CallOptions? options}) {
|
||||
return $createUnaryCall(_$askAi, request, options: options);
|
||||
}
|
||||
}
|
||||
|
||||
@$pb.GrpcServiceName('fai.v1.HubAdmin')
|
||||
|
|
@ -402,6 +425,20 @@ abstract class HubAdminServiceBase extends $grpc.Service {
|
|||
false,
|
||||
($core.List<$core.int> value) => $1.Empty.fromBuffer(value),
|
||||
($0.ChannelStatusResponse value) => value.writeToBuffer()));
|
||||
$addMethod($grpc.ServiceMethod<$1.Empty, $0.SystemAiStatusResponse>(
|
||||
'SystemAiStatus',
|
||||
systemAiStatus_Pre,
|
||||
false,
|
||||
false,
|
||||
($core.List<$core.int> value) => $1.Empty.fromBuffer(value),
|
||||
($0.SystemAiStatusResponse value) => value.writeToBuffer()));
|
||||
$addMethod($grpc.ServiceMethod<$0.AskAiRequest, $0.AskAiResponse>(
|
||||
'AskAi',
|
||||
askAi_Pre,
|
||||
false,
|
||||
false,
|
||||
($core.List<$core.int> value) => $0.AskAiRequest.fromBuffer(value),
|
||||
($0.AskAiResponse value) => value.writeToBuffer()));
|
||||
}
|
||||
|
||||
$async.Future<$0.CapabilityList> listCapabilities_Pre($grpc.ServiceCall $call, $async.Future<$1.Empty> $request) async {
|
||||
|
|
@ -468,6 +505,14 @@ abstract class HubAdminServiceBase extends $grpc.Service {
|
|||
return channelStatus($call, await $request);
|
||||
}
|
||||
|
||||
$async.Future<$0.SystemAiStatusResponse> systemAiStatus_Pre($grpc.ServiceCall $call, $async.Future<$1.Empty> $request) async {
|
||||
return systemAiStatus($call, await $request);
|
||||
}
|
||||
|
||||
$async.Future<$0.AskAiResponse> askAi_Pre($grpc.ServiceCall $call, $async.Future<$0.AskAiRequest> $request) async {
|
||||
return askAi($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);
|
||||
|
|
@ -484,4 +529,6 @@ abstract class HubAdminServiceBase extends $grpc.Service {
|
|||
$async.Future<$0.ServiceList> listServices($grpc.ServiceCall call, $1.Empty request);
|
||||
$async.Future<$0.CheckUpdateResponse> checkUpdate($grpc.ServiceCall call, $1.Empty request);
|
||||
$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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -669,3 +669,50 @@ final $typed_data.Uint8List checkUpdateResponseDescriptor = $convert.base64Decod
|
|||
'Zlc3RSZWFjaGFibGUSFgoGcmVhc29uGAggASgJUgZyZWFzb24SIQoMbWFuaWZlc3RfdXJsGAkg'
|
||||
'ASgJUgttYW5pZmVzdFVybA==');
|
||||
|
||||
@$core.Deprecated('Use systemAiStatusResponseDescriptor instead')
|
||||
const SystemAiStatusResponse$json = {
|
||||
'1': 'SystemAiStatusResponse',
|
||||
'2': [
|
||||
{'1': 'enabled', '3': 1, '4': 1, '5': 8, '10': 'enabled'},
|
||||
{'1': 'provider', '3': 2, '4': 1, '5': 9, '10': 'provider'},
|
||||
{'1': 'endpoint', '3': 3, '4': 1, '5': 9, '10': 'endpoint'},
|
||||
{'1': 'model', '3': 4, '4': 1, '5': 9, '10': 'model'},
|
||||
{'1': 'privacy_mode', '3': 5, '4': 1, '5': 9, '10': 'privacyMode'},
|
||||
{'1': 'api_key_env', '3': 6, '4': 1, '5': 9, '10': 'apiKeyEnv'},
|
||||
],
|
||||
};
|
||||
|
||||
/// Descriptor for `SystemAiStatusResponse`. Decode as a `google.protobuf.DescriptorProto`.
|
||||
final $typed_data.Uint8List systemAiStatusResponseDescriptor = $convert.base64Decode(
|
||||
'ChZTeXN0ZW1BaVN0YXR1c1Jlc3BvbnNlEhgKB2VuYWJsZWQYASABKAhSB2VuYWJsZWQSGgoIcH'
|
||||
'JvdmlkZXIYAiABKAlSCHByb3ZpZGVyEhoKCGVuZHBvaW50GAMgASgJUghlbmRwb2ludBIUCgVt'
|
||||
'b2RlbBgEIAEoCVIFbW9kZWwSIQoMcHJpdmFjeV9tb2RlGAUgASgJUgtwcml2YWN5TW9kZRIeCg'
|
||||
'thcGlfa2V5X2VudhgGIAEoCVIJYXBpS2V5RW52');
|
||||
|
||||
@$core.Deprecated('Use askAiRequestDescriptor instead')
|
||||
const AskAiRequest$json = {
|
||||
'1': 'AskAiRequest',
|
||||
'2': [
|
||||
{'1': 'prompt', '3': 1, '4': 1, '5': 9, '10': 'prompt'},
|
||||
],
|
||||
};
|
||||
|
||||
/// Descriptor for `AskAiRequest`. Decode as a `google.protobuf.DescriptorProto`.
|
||||
final $typed_data.Uint8List askAiRequestDescriptor = $convert.base64Decode(
|
||||
'CgxBc2tBaVJlcXVlc3QSFgoGcHJvbXB0GAEgASgJUgZwcm9tcHQ=');
|
||||
|
||||
@$core.Deprecated('Use askAiResponseDescriptor instead')
|
||||
const AskAiResponse$json = {
|
||||
'1': 'AskAiResponse',
|
||||
'2': [
|
||||
{'1': 'error_kind', '3': 1, '4': 1, '5': 9, '10': 'errorKind'},
|
||||
{'1': 'text', '3': 2, '4': 1, '5': 9, '10': 'text'},
|
||||
{'1': 'latency_ms', '3': 3, '4': 1, '5': 13, '10': 'latencyMs'},
|
||||
],
|
||||
};
|
||||
|
||||
/// Descriptor for `AskAiResponse`. Decode as a `google.protobuf.DescriptorProto`.
|
||||
final $typed_data.Uint8List askAiResponseDescriptor = $convert.base64Decode(
|
||||
'Cg1Bc2tBaVJlc3BvbnNlEh0KCmVycm9yX2tpbmQYASABKAlSCWVycm9yS2luZBISCgR0ZXh0GA'
|
||||
'IgASgJUgR0ZXh0Eh0KCmxhdGVuY3lfbXMYAyABKA1SCWxhdGVuY3lNcw==');
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,8 @@ typedef VerifyEventChainResponse = pb.VerifyEventChainResponse;
|
|||
typedef CheckUpdateResponse = pb.CheckUpdateResponse;
|
||||
typedef ChannelStatusResponse = pb.ChannelStatusResponse;
|
||||
typedef ChannelEntry = pb.ChannelEntry;
|
||||
typedef SystemAiStatusResponse = pb.SystemAiStatusResponse;
|
||||
typedef AskAiResponse = pb.AskAiResponse;
|
||||
typedef ModuleInfoResponse = pb.ModuleInfoResponse;
|
||||
typedef FlowSummary = pb.FlowSummary;
|
||||
typedef StoreEntry = pb.StoreEntry;
|
||||
|
|
@ -184,6 +186,19 @@ class HubClient {
|
|||
return _admin.channelStatus(Empty());
|
||||
}
|
||||
|
||||
/// Read-only system-AI status. `enabled=false` lets Studio
|
||||
/// render "configure in Settings" without making a request.
|
||||
Future<SystemAiStatusResponse> systemAiStatus() {
|
||||
return _admin.systemAiStatus(Empty());
|
||||
}
|
||||
|
||||
/// One-shot prompt to the configured System AI. Errors come
|
||||
/// back inside [AskAiResponse.errorKind] (not as exceptions)
|
||||
/// so Studio can map each category to its inline-fix copy.
|
||||
Future<AskAiResponse> askAi(String prompt) {
|
||||
return _admin.askAi(pb.AskAiRequest(prompt: prompt));
|
||||
}
|
||||
|
||||
/// Search the hub's bundled store index. All filters are
|
||||
/// optional; an empty query returns the first [limit] entries
|
||||
/// the index ships with.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue