ĀYŌDÈ Intelligence Operations
How the Studio routes AI work: the aitunerequest contract, the whole-lesson
context payload, synchronous versus RAG/async paths, whole-lesson panel
generation, assessment generation with its review-before-hydrate flow, and
the reference library the retrieval-backed operations draw on. Verified
against POC build 213 (20260910T123348).
The component’s menu surface is inventoried in Editor Component; this document covers what the host does with the request.
Contents
- The host/component split
- The lesson-context payload
- Routing and progress
- Applying a result
- Whole-lesson panels
- Assessment generation
- The reference library
The host/component split
The editor component only reports intent. It dispatches an
aitunerequest event carrying the selection, the backend operation
humanName (for example lesson-text-tune-content-simplify-v2), and flags
for whether the operation is RAG-enabled, a generate-family operation, or the
glossary define-term case.
The shell owns everything else: auth and realm state, building the request payload, choosing the synchronous or async endpoint, the progress UI, and presenting the result. This is the boundary that lets the same component work unchanged in Student Lab and published lessons, where no AI host exists.
The lesson-context payload
Every text-tune bundle shares one request contract, and its central idea is that the model always sees the whole lesson, even when acting on a few words:
lessonText is the concatenation of every panel’s MyST source in document
order, with the edited panel’s selection wrapped in fixed markers:
<<<AI_TUNE_SELECTION_START>>> … <<<AI_TUNE_SELECTION_END>>>
So an operation acting on one sentence still knows the lesson’s goals, reading level and terminology.
The payload is capped at 50,000 characters, matching the bundles’
lessonText maxLength. Over the cap it degrades in defined steps rather
than truncating blindly:
- Fall back to the marked panel alone, trimmed around the marked span with the remaining budget split roughly evenly before and after it — so the model keeps context on both sides of the selection.
- If even the marked selection exceeds the cap, truncate it. Pathological, but defined.
Routing and progress
| Operation class | Endpoint |
|---|---|
| Most operations | POST /v2/ai/generate/{humanName} — synchronous |
| RAG-enabled operations | Async submit, then poll — retrieval adds latency |
There is no true progress signal from the backend: the async poll reports
only a coarse status. Rather than fake a progress bar, the Studio paces it
from measured history — an exponential moving average of each operation’s own
past durations (weighted 0.6 old / 0.4 new), kept in localStorage and
seeded with a class default of 45 s for RAG operations and 12 s otherwise.
The modal shows the stage, elapsed time and completion.
A full-window wait animation covers the operation, and it suspends while any decision dialog is open, so an animation never sits on top of a question the instructor has to answer.
Applying a result
Results arrive in a compare view — original alongside proposed — with four actions:
| Action | Effect |
|---|---|
| Copy | To the clipboard; the source is untouched |
| Replace | Substitutes the selection, as one undo step |
| Insert Before | Inserts as its own block before the selection’s line |
| Insert After | Inserts as its own block after it |
Generate-family operations default to insertion rather than replacement — Key Takeaways and Learning Objectives prefer Insert Before — because they add material rather than revise it.
The glossary define-term operation is the one exception to the compare view: its generated, language-level-matched definition lands in the standard glossary define dialog — the same one the manual command opens, prefilled and editable — so an AI definition is reviewed and accepted through exactly the same gate as a hand-written one.
Whole-lesson panels
Lesson ▸ ĀYŌDÈ Intelligence generates a dedicated panel from the entire lesson, distinct from the selection-scoped operations.
| Target | Bundle | RAG | Default position |
|---|---|---|---|
| Summary | lesson-text-tune-generate-summary-whole-lesson-v1 |
No | Last |
| Learning Objectives | lesson-text-tune-generate-learning-objectives-whole-lesson-v1 |
Yes | First |
| Key Takeaways | lesson-text-tune-generate-key-takeaways-whole-lesson-v1 |
No | First |
These bundles are marker-free — there is no selection — so the request
body is just { lessonText }, plus rootRealmEIDurn for the RAG-enabled
objectives bundle.
Four rules govern the behavior:
- Generated panels are excluded from the input.
buildWholeLessonTextskips the three target panels by title, so re-running an operation never feeds prior generated output back into itself. - The target is found by case-insensitive title, which is also the Generate-versus-Update discriminator. A panel the instructor has renamed reads as absent, and a fresh one is created.
- No compare modal. The result is written straight into its dedicated panel. There is nothing to diff against on a create, and on an update the panel is wholly generated content.
- No reorder on update. An update overwrites the existing panel’s source only — never moving, reordering, indenting or re-parenting it. Position is chosen once, on create.
Assessment generation
The one flow with a mandatory human gate between the model and the lesson.
Raised by the component’s Generate/Update assessment panel submenu as an
aitunerequest with detail.kind === "assessment", and handled by a
four-stage path:
1. Build the request. Whole-lesson lessonText for context, plus a
scoped sourceText — the selected passage if there is one, otherwise the
whole current panel — plus rootRealmEIDurn. Enqueued as a RAG whole-lesson
bundle and polled to a structured display-plus-assessment envelope.
2. Diff. On Generate every item is new. On Update incoming items are
matched against the existing hydrated challenges by challengeRef, falling
back to a content signature — the normalized prompt plus the
evaluationMode — because a freshly generated item has no ref yet. Items
resolve as kept, new or removed.
3. Review. The instructor resolves the diff per item. Nothing reaches the lesson before this.
4. Hydrate. Accepted items become challenge panels under a child
assessment panel — itself a mission whose children are the challenges —
beneath the right-clicked panel.
Two invariants matter to implementers:
challengeRefis POC-minted, never AI-emitted. The model has no business assigning platform identity. Refs are minted byensureChallengeRef, and matching on Update exists precisely so an existing panel’s ref is preserved rather than reissued.- No second AI call at persistence. Hydration maps the envelope onto the
ordinary challenge model, after which the existing publish path
(assessment sidecar → challenge config → assessment package →
POST /v2/lessons/{eid}/generated-challenges) carries it with no further model involvement.
The reference library
RAG-enabled operations retrieve from the corpus attached to the
Reference Library space (as rootRealmEIDurn). Library ▸ Upload
resource… and Upload resource from URL… put material there.
Two ingestion paths converge on the same corpus endpoint:
| Mode | Path |
|---|---|
| URL | POST /v2/web/extract (the server fetches the URL) → poll → GET metadata (/metadata/web/raw) → POST /v2/corpus/add |
| File | writeAsset into the self zone → POST /v2/text/extract → poll → GET metadata (/metadata/text/raw) → POST /v2/corpus/add |
File mode requires additional Curator privileges beyond URL mode — file-system access and file create/write on self for the upload, plus the text-extract trigger. Both modes need asset-metadata read.
The corpus POST only enqueues ingestion, so the Studio polls the job to a terminal state before reporting success: “done” means the material is actually retrievable, not merely accepted. Progress is narrated through the same wait animation (“Adding to corpus…”).
The upload target is a single realm or sub-space, picked from the same realm tree the Reference Library tab uses — an upload always goes to exactly one place, so this is deliberately single-selection.