feat(base)!: one budget per person for all their assistants, the effort each takes, the operator's lists by page

A grant now says only which assistant a person may use, and keeps their
agreement; the limits are the person's (assistant_budget): one per UTC
day and month in money and in tokens, each optional, money counting the
assistants with prices, tokens every one (Halkyon Learn's ADR 0021, D58,
D59). assistantOperator.grant gives several people several assistants
with one budget, change sets one person's exactly, revoke takes back
everything; grantees and granteesOf list people with their assistants,
budget and use, 50 at a time. The migration carries each person's grant
limits into a budget: per unit, their sum, a grant without a limit making
it none.

assistants.env gives each assistant a default and a highest effort
(_EFFORT, _MAX_EFFORT; refused at start where the provider takes none);
ask takes one within that range, refusing another (invalidEffort), and
caps the output at its ceiling (D63).

instanceOperator.waiting and accounts come 50 at a time from an offset,
and counts gives the rows of the operator's screen (D62).

BREAKING CHANGE: the offer, the grants and the operator's lists changed
shape; Learn's server now asks for build 25.

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 15:07:04 +01:00
commit 24ed63585e
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -1,4 +1,4 @@
# The instance's assistants (Halkyon Learn's ADR 0021, points 4 and 8, D37 and D38):
# The instance's assistants (Halkyon Learn's ADR 0021, points 4 and 8, D37, D38, D63):
# copy to deploy/assistants.env, restrict it (chmod 600), and fill in. It is git-ignored,
# goes to Halkyon Learn's server alone (compose.yaml, `env_file`), never into an image,
# the database or its backups; keep it with deploy/.env's secrets (in Proton Pass).
@ -6,10 +6,10 @@
# restart: docker compose up -d server. Anything the server can't use stops it as it
# starts, naming the variable.
#
# Nobody has an assistant until an operator grants it to them in the app, with limits
# per day and month; each person agrees once to what goes where. The instance keeps
# what each person used (requests, tokens, cost) per day for 3 months, never what was
# asked.
# Nobody has an assistant until an operator grants it to them in the app, with a budget
# per day and month for all their assistants together, in money and in tokens (D58,
# D59); each person agrees once to what goes where. The instance keeps what each person
# used (requests, tokens, cost) per day for 3 months, never what was asked.
# The assistants' IDs, in the order people see them, by commas or spaces: a letter,
# then letters, digits or _. Each names its variables below (claude: ASSISTANT_CLAUDE_…)
@ -42,11 +42,19 @@ ASSISTANT_CLAUDE_KEY=
# on: people may add images (a card's picture, a PDF page) for a model that reads them.
#ASSISTANT_CLAUDE_IMAGES=on
# What the model costs per million tokens, as the provider bills it, in
# ASSISTANT_CURRENCY, with a point for decimals: both or none. With prices, limits and
# figures are in money; without, in tokens. A change counts from then on; a grant made
# before prices came or went holds no more until its limits are set again.
# ASSISTANT_CURRENCY, with a point for decimals: both or none. With prices, it counts
# against a budget's money and tokens; without, against its tokens alone. A change
# counts from then on.
#ASSISTANT_CLAUDE_PRICE_INPUT=2
#ASSISTANT_CLAUDE_PRICE_OUTPUT=10
# How much the model thinks before it answers: low, medium, high, xhigh or max
# (Anthropic's names, sent in each provider's own field; Gemini takes low to high,
# Mistral none). EFFORT is what a question takes unless the person picks one;
# MAX_EFFORT the highest they may pick (unset: EFFORT). Both unset: the model's own,
# and nothing to pick. More effort spends more tokens, at the same price per token, and
# leaves more room for the answer (8,192 tokens at low to 65,536 at max).
#ASSISTANT_CLAUDE_EFFORT=medium
#ASSISTANT_CLAUDE_MAX_EFFORT=high
# A second one, through OpenAI's Responses API:
#ASSISTANTS=claude gpt