ADR 0021, step 2's app half. halkyon_app asks the module's assistant endpoints (ServerpodAssistantGateway, ServerpodAssistantOperatorGateway) and a person's own provider directly (halkyon_llm), behind AssistantRepository: an AssistantChoice is a GrantedAssistant, asked through the instance, which counts it, or a PersonalAssistant with the person's own key, which the instance never sees. assistant_messages.dart turns a conversation into the endpoint's models and back. AssistantsCard, for an app's settings: what is granted and left of its limits, agreed to once on a sheet saying what goes where, the person's use by UTC month, the instance's privacy page, and their own assistants where the operator allows own keys (kept ones stay listed, unasked, where it doesn't). AssistantGrantsCard on InstanceOperatorScreen: grants by handle with their limits in the pricing's unit, changed and taken back after asking, everyone's use by month; a found account's menu grants too. Nothing shows where nothing is offered or can be read. package:halkyon_app/assistant_models.dart holds the models in pure Dart. Learn keeps own assistants in the person's settings (ownAssistants, schema 12, SettingsOwnAssistants); SettingsRepository.update refuses (OwnAssistantRefused) to write a key where the settings would not be sealed (SettingsGateway.seals). Learn depends on halkyon_llm directly. Todo wires the gateways; a member offers no assistant. No feature asks an assistant yet (step 3). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
106 lines
2.8 KiB
Dart
106 lines
2.8 KiB
Dart
import 'package:equatable/equatable.dart';
|
|
import 'package:halkyon_app/src/assistant/model/assistant_offer.dart';
|
|
|
|
/// An assistant the operator set in `deploy/assistants.env`, as the
|
|
/// operator's screen shows it (Halkyon Learn's ADR 0021, point 4): never
|
|
/// its key.
|
|
final class const SetUpAssistant({
|
|
required final String id,
|
|
required final String name,
|
|
required final String protocol,
|
|
required final String host,
|
|
required final String model,
|
|
final bool images = false,
|
|
|
|
/// What a million of the request's tokens cost, in the instance's
|
|
/// currency; null without prices.
|
|
final double? priceInput,
|
|
|
|
/// What a million of the answer's tokens cost; null without prices.
|
|
final double? priceOutput,
|
|
}) with Equatable {
|
|
/// What its limits are counted in: money with prices, else tokens (D38).
|
|
AssistantLimitUnit get unit => priceInput != null && priceOutput != null
|
|
? AssistantLimitUnit.money
|
|
: AssistantLimitUnit.tokens;
|
|
|
|
@override
|
|
List<Object?> get props => [
|
|
id,
|
|
name,
|
|
protocol,
|
|
host,
|
|
model,
|
|
images,
|
|
priceInput,
|
|
priceOutput,
|
|
];
|
|
}
|
|
|
|
/// The assistants the operator set, for their screen.
|
|
final class const AssistantsSetUp({
|
|
/// Each, in the operator's order; none where none is set.
|
|
final List<SetUpAssistant> assistants = const [],
|
|
|
|
/// The currency of the prices (ISO 4217).
|
|
final String currency = 'USD',
|
|
|
|
/// Whether people may add their own keys.
|
|
final bool ownKeys = false,
|
|
}) with Equatable {
|
|
/// The assistant [id] names; null for one not set (any more).
|
|
SetUpAssistant? named(String id) {
|
|
for (final assistant in assistants) {
|
|
if (assistant.id == id) {
|
|
return assistant;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
@override
|
|
List<Object?> get props => [assistants, currency, ownKeys];
|
|
}
|
|
|
|
/// An assistant granted to an account, as the operator sees it (D2, D4).
|
|
final class const AssistantGrant({
|
|
/// The account's ID.
|
|
required final String account,
|
|
|
|
/// Its handle; null for one without.
|
|
final String? handle,
|
|
|
|
/// The assistant's ID.
|
|
required final String assistant,
|
|
|
|
/// Whether the assistant is still set; a grant of one taken out of the
|
|
/// file stays, unused.
|
|
final bool assistantSet = true,
|
|
required final DateTime grantedAt,
|
|
|
|
/// What [dailyLimit] and [monthlyLimit] are counted in.
|
|
final AssistantLimitUnit unit = AssistantLimitUnit.tokens,
|
|
final int? dailyLimit,
|
|
final int? monthlyLimit,
|
|
|
|
/// When the person agreed to what goes where; null until they do.
|
|
final DateTime? agreedAt,
|
|
|
|
/// Whether its limits are in another unit than the pricing's now, to be
|
|
/// set again.
|
|
final bool outdated = false,
|
|
}) with Equatable {
|
|
@override
|
|
List<Object?> get props => [
|
|
account,
|
|
handle,
|
|
assistant,
|
|
assistantSet,
|
|
grantedAt,
|
|
unit,
|
|
dailyLimit,
|
|
monthlyLimit,
|
|
agreedAt,
|
|
outdated,
|
|
];
|
|
}
|