feat(app): the operator's overview of screens, grants to several people at once with one budget each, assistants by provider

Halkyon Learn's ADR 0021, D57 to D63, on halkyon_base's budgets and
effort:

- The operator's screen is an overview (Waiting, Operators, Accounts,
  Assistants, each with its count) whose rows open screens of their own,
  read 50 at a time as they scroll (OperatorListCubit, OperatorPage), so
  hundreds of accounts push nothing else down (D62).
- A handle is picked among the accounts there are (AccountSuggestionField):
  appointing an operator and granting take no other (D61).
- AssistantGrantsScreen replaces AssistantGrantsCard: the assistants set
  up by provider, with their efforts and prices; the people granted, found
  by their handle's start; one sheet granting several assistants, a
  provider's at once, to several people, each with one budget in money and
  tokens a day and a month, or changing one person's (D58, D59).
- Assistants are grouped by provider wherever they are listed, each under
  its name with a dot in its colour (ProviderLabel, D60).
- AssistantsCard shows what is left of the person's budget for all their
  assistants together; the months of the figures run oldest first (D57).
- AssistantChoice says the efforts a question may ask at and the ceiling
  on output each asks for (D63); a person's own key gets none and keeps
  4,096 tokens.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-10-26 16:05:49 +01:00
commit cc87120bc8
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -1987,6 +1987,24 @@ abstract class HalkyonAppLocalizations {
/// **'Waiting'**
String get operatorWaitingTitle;
/// How many operate the instance, in the overview's row.
///
/// In en, this message translates to:
/// **'{count, plural, =1{1 operator} other{{count} operators}}'**
String operatorOperatorsCount(int count);
/// The overview's row leading to every account, and that screen's title.
///
/// In en, this message translates to:
/// **'Accounts'**
String get operatorAccountsTitle;
/// How many accounts the instance has.
///
/// In en, this message translates to:
/// **'{count, plural, =1{1 account} other{{count} accounts}}'**
String operatorAccountsCount(int count);
/// The waiting card, empty.
///
/// In en, this message translates to:
@ -2089,11 +2107,11 @@ abstract class HalkyonAppLocalizations {
/// **'Handle'**
String get operatorHandle;
/// The card searching accounts by the start of their handle.
/// Below a field suggesting handles as they are typed.
///
/// In en, this message translates to:
/// **'Find an account'**
String get operatorFindTitle;
/// **'Only handles there are here are suggested.'**
String get operatorHandleSuggested;
/// A search that found nothing.
///
@ -2203,10 +2221,82 @@ abstract class HalkyonAppLocalizations {
/// **'Nobody has an assistant yet.'**
String get assistantGrantsNone;
/// How many assistants are set up, in the overview's row.
///
/// In en, this message translates to:
/// **'{count, plural, =0{None set up} =1{1 assistant} other{{count} assistants}}'**
String assistantSetCount(int count);
/// How many people have an assistant, after how many are set up.
///
/// In en, this message translates to:
/// **'{count, plural, =0{nobody granted} =1{1 person} other{{count} people}}'**
String assistantPeopleCount(int count);
/// The card of the assistants set up in deploy/assistants.env.
///
/// In en, this message translates to:
/// **'Set up here'**
String get assistantSetUpTitle;
/// The card, and the sheet section, of the people granted assistants.
///
/// In en, this message translates to:
/// **'People'**
String get assistantPeopleTitle;
/// No person granted one matches the start of a handle typed.
///
/// In en, this message translates to:
/// **'Nobody with an assistant has a handle starting like this.'**
String get assistantGranteesFoundNone;
/// An assistant set up without prices, which a budget counts in tokens alone.
///
/// In en, this message translates to:
/// **'No prices: counts its tokens only'**
String get assistantUnpriced;
/// How much a model thinks before it answers, as a word in a sentence.
///
/// In en, this message translates to:
/// **'{effort, select, low{low} medium{medium} high{high} xhigh{extra high} max{max} other{{effort}}}'**
String assistantEffort(String effort);
/// How much a model thinks before it answers, as a name standing alone, as in a menu.
///
/// In en, this message translates to:
/// **'{effort, select, low{Low} medium{Medium} high{High} xhigh{Extra high} max{Max} other{{effort}}}'**
String assistantEffortName(String effort);
/// An assistant's effort unless asked otherwise, and the highest a question may ask.
///
/// In en, this message translates to:
/// **'Effort {effort}, up to {max}'**
String assistantEffortSetUp(String effort, String max);
/// An assistant's effort, the only one it takes.
///
/// In en, this message translates to:
/// **'Effort {effort}'**
String assistantEffortFixed(String effort);
/// An assistant granted that is no longer set up.
///
/// In en, this message translates to:
/// **'{name} (no longer set up)'**
String assistantNameUnset(String name);
/// How many of a person's assistants they haven't agreed to yet.
///
/// In en, this message translates to:
/// **'{count, plural, =1{1 not agreed to yet} other{{count} not agreed to yet}}'**
String assistantNotAgreedCount(int count);
/// Opens the sheet granting an assistant to an account.
///
/// In en, this message translates to:
/// **'Grant an assistant'**
/// **'Grant assistants'**
String get assistantGrant;
/// The grant sheet's button.
@ -2215,48 +2305,72 @@ abstract class HalkyonAppLocalizations {
/// **'Grant'**
String get assistantGrantSave;
/// A grant's menu item, and the sheet's title, changing its limits.
/// The sheet changing a person's assistants and budget, and a person's menu item.
///
/// In en, this message translates to:
/// **'Change limits'**
/// **'Change assistants'**
String get assistantGrantChange;
/// Above the choice of assistant in the grant sheet.
///
/// In en, this message translates to:
/// **'Assistant'**
String get assistantGrantAssistant;
/// The daily limit field.
///
/// In en, this message translates to:
/// **'Limit a day'**
String get assistantGrantDaily;
/// The monthly limit field.
///
/// In en, this message translates to:
/// **'Limit a month'**
String get assistantGrantMonthly;
/// Under the limit fields: the instance counts by UTC days and months (D42).
///
/// In en, this message translates to:
/// **'Empty for none. Days and months are UTC\'s.'**
String get assistantGrantLimitHelper;
/// The sheet's section of a person's budget.
///
/// In en, this message translates to:
/// **'Budget, for all of them together'**
String get assistantGrantBudget;
/// A budget field.
///
/// In en, this message translates to:
/// **'Money a day'**
String get assistantGrantMoneyDaily;
/// A budget field.
///
/// In en, this message translates to:
/// **'Money a month'**
String get assistantGrantMoneyMonthly;
/// A budget field.
///
/// In en, this message translates to:
/// **'Tokens a day'**
String get assistantGrantTokensDaily;
/// A budget field.
///
/// In en, this message translates to:
/// **'Tokens a month'**
String get assistantGrantTokensMonthly;
/// Below the budget fields.
///
/// In en, this message translates to:
/// **'Money counts the assistants with prices, tokens count every one. Whichever runs out first stops them.'**
String get assistantGrantMoneyNote;
/// Before the people whose budget a grant replaces, each with theirs.
///
/// In en, this message translates to:
/// **'{count, plural, =1{Granting replaces the budget this person has:} other{Granting replaces the budgets these people have:}}'**
String assistantGrantReplaces(int count);
/// Changing a person's assistants drops those no longer set up.
///
/// In en, this message translates to:
/// **'Saving takes back what is no longer set up: {names}.'**
String assistantGrantUnsetDropped(String names);
/// A limit typed that is no amount or number of tokens.
///
/// In en, this message translates to:
/// **'Not a number this takes'**
String get assistantGrantLimitInvalid;
/// The grant sheet: the handle typed is nobody's.
///
/// In en, this message translates to:
/// **'No account has this handle.'**
String get assistantGrantNoHandle;
/// After a limit in tokens, for an assistant without prices.
///
/// In en, this message translates to:
@ -2266,7 +2380,7 @@ abstract class HalkyonAppLocalizations {
/// In the grant sheet: consent (D40) and what the operator sees (D3).
///
/// In en, this message translates to:
/// **'They agree once to what goes where before they ask it. You see how much they use, never what they ask.'**
/// **'They agree once to what goes where before they ask one. Assistants they have already stay. You see how much they use, never what they ask.'**
String get assistantGrantNote;
/// A daily limit.
@ -2287,46 +2401,22 @@ abstract class HalkyonAppLocalizations {
/// **'No limits'**
String get assistantNoLimits;
/// A grant whose person agreed to what goes where.
///
/// In en, this message translates to:
/// **'Agreed'**
String get assistantGrantAgreed;
/// A grant whose person hasn't agreed yet.
///
/// In en, this message translates to:
/// **'Not agreed yet'**
String get assistantGrantNotAgreed;
/// A grant whose limits are in another unit than the pricing now; it answers nothing until set again.
///
/// In en, this message translates to:
/// **'Its prices changed: set its limits again'**
String get assistantGrantOutdated;
/// A grant of an assistant taken out of deploy/assistants.env.
///
/// In en, this message translates to:
/// **'No longer set up'**
String get assistantGrantUnset;
/// A grant's menu item.
///
/// In en, this message translates to:
/// **'Take back'**
String get assistantRevoke;
/// Asks before taking a grant back.
/// Asks before taking every assistant back from a person.
///
/// In en, this message translates to:
/// **'Take back {assistant}?'**
String assistantRevokeTitle(String assistant);
/// **'Take back every assistant?'**
String get assistantRevokeAllTitle;
/// Under the question taking a grant back.
///
/// In en, this message translates to:
/// **'They can no longer ask it. What they used stays counted.'**
/// **'They can no longer ask any of them, and their budget goes. What they used stays counted.'**
String get assistantRevokeMessage;
/// Opens everyone's figures (D3).
@ -2389,18 +2479,18 @@ abstract class HalkyonAppLocalizations {
/// **'{left} of {limit} left this month'**
String assistantLeftThisMonth(String left, String limit);
/// The person's budget for all their assistants.
///
/// In en, this message translates to:
/// **'Your budget, for all of them'**
String get assistantYourBudget;
/// Opens the consent sheet of an assistant not agreed to yet.
///
/// In en, this message translates to:
/// **'Read and agree'**
String get assistantAgree;
/// An assistant whose limits are outdated: it answers nothing until the operator sets them again.
///
/// In en, this message translates to:
/// **'Waits for its limits to be set again'**
String get assistantWaitsForLimits;
/// Opens the person's own figures.
///
/// In en, this message translates to:
@ -2593,6 +2683,12 @@ abstract class HalkyonAppLocalizations {
/// **'Agree to what goes where first.'**
String get assistantProblemNotAgreed;
/// A question asked an effort its assistant does not take.
///
/// In en, this message translates to:
/// **'It doesn\'t think at this effort.'**
String get assistantProblemInvalidEffort;
/// limitReached, with when it resets.
///
/// In en, this message translates to:
@ -2605,12 +2701,6 @@ abstract class HalkyonAppLocalizations {
/// **'Its limit is reached for now.'**
String get assistantProblemLimitReachedNow;
/// limitOutdated.
///
/// In en, this message translates to:
/// **'It waits for its limits to be set again.'**
String get assistantProblemLimitOutdated;
/// imagesNotRead.
///
/// In en, this message translates to: