Skip to content

Package: course-builder

Generated from api/packages/course-builder

Source: api/packages/course-builder. The sections after the README are extracted from the code on every docs build.

Turns an author’s source (Markdown, PDF, DOCX) into a cited course through a short interview, an outline with learning objectives the author approves, generated lessons and quizzes, and an apply through the LMS domain services. Afterwards any element can be refined by chatting about it; every change is a reviewable diff and a new blueprint version. Records: ADR 0010, 0011, 0022–0029; plan docs/plans/phase-2.md.

Upload ─▶ IngestRun: Source Document + fragments (frg_… ids from the heading position)
─▶ InterviewRun (light model): 6 questions as catalogue controls; answers fill the Course Brief
─▶ OutlineRun (default model): objectives + outline, proposed as a version ── author approves/edits/rejects
─▶ GenerateRun: lessons ▸ grounding ▸ quizzes + final test ▸ metadata ▸ content version (resumable steps)
─▶ apply proposal ── author approves ─▶ ApplyRun: course, lessons, topics, GIFT questions, landing page
─▶ element chat: patch version as a DiffView ── approve ─▶ re-apply of the changed elements; undo/redo/restore

Everything the browser sees is an AG-UI event (GET …/sessions/{id}/events, SSE with resume); the interactive cards are A2UI v0.9 surfaces from the @ulams/ui builder catalogue, built by code from validated data. The model never writes UI markup, never calls tools and never sees the source outside an untrusted wrapper in the user turn.

Terminal window
vendor/bin/phpunit --testsuite course-builder # fake driver; includes a recorded live run
php artisan course-builder:eval --fixtures=all --author=1 # free, fake driver
php artisan course-builder:eval --fixtures=coffee --live --author=1 # real model, costs money
Method Path Auth Action
GET /api/admin/course-builder/sessions yes CourseBuilderController@index
POST /api/admin/course-builder/sessions yes CourseBuilderController@store
GET /api/admin/course-builder/sessions/{session} yes CourseBuilderController@show
DELETE /api/admin/course-builder/sessions/{session} yes CourseBuilderController@destroy
POST /api/admin/course-builder/sessions/{session}/sources yes CourseBuilderController@upload
GET /api/admin/course-builder/sessions/{session}/sources/{source} yes CourseBuilderController@source
GET /api/admin/course-builder/sessions/{session}/citations yes CourseBuilderController@citations
GET /api/admin/course-builder/fragments/{fragment} yes CourseBuilderController@fragment
GET /api/admin/course-builder/sessions/{session}/brief yes CourseBuilderController@brief
PUT /api/admin/course-builder/sessions/{session}/brief yes CourseBuilderController@updateBrief
POST /api/admin/course-builder/sessions/{session}/runs yes CourseBuilderController@run
GET /api/admin/course-builder/sessions/{session}/events yes EventStreamController@stream
GET /api/admin/course-builder/runs/{run} yes CourseBuilderController@runStatus
POST /api/admin/course-builder/runs/{run}/cancel yes CourseBuilderController@cancel
POST /api/admin/course-builder/runs/{run}/steps/{step}/retry yes CourseBuilderController@retryStep
GET /api/admin/course-builder/sessions/{session}/versions yes CourseBuilderController@versions
GET /api/admin/course-builder/versions/{version} yes CourseBuilderController@version
GET /api/admin/course-builder/versions/{version}/diff yes CourseBuilderController@diff
POST /api/admin/course-builder/versions/{version}/approve yes CourseBuilderController@approve
POST /api/admin/course-builder/versions/{version}/reject yes CourseBuilderController@reject
POST /api/admin/course-builder/versions/{version}/restore yes CourseBuilderController@restore
POST /api/admin/course-builder/sessions/{session}/undo yes CourseBuilderController@undo
POST /api/admin/course-builder/sessions/{session}/redo yes CourseBuilderController@redo
POST /api/admin/course-builder/sessions/{session}/outline yes CourseBuilderController@editOutline
POST /api/admin/course-builder/sessions/{session}/elements/{element}/variants yes CourseBuilderController@variants
POST /api/admin/course-builder/sessions/{session}/apply yes CourseBuilderController@apply
POST /api/admin/course-builder/sessions/{session}/new-site yes CourseBuilderController@newSite
GET /api/admin/course-builder/sessions/{session}/publish-check yes CourseBuilderController@publishCheck
POST /api/admin/course-builder/sessions/{session}/publish yes CourseBuilderController@publish
GET /api/admin/course-builder/sessions/{session}/usage yes CourseBuilderController@usage
Permission Seeded for roles Constant
course_builder_use admin, tutor CourseBuilderPermissionsEnum::COURSE_BUILDER_USE

Registered with AdministrableConfig::registerConfig (editable in the admin panel under Configuration → Settings).

None.

Event Description Notification templates
ElementPatched An element was changed by an approved chat edit (other packages mark work based on the old text as out of date).
EventLog Appends AG-UI events to course_builder_events (ADR 0011). The row id is the SSE event id. After each append the session’s “last event” key in the cache is bumped so open SSE connections wake without querying the table on every tick. A2UI v0.9 surfaces travel as ACTIVITY_SNAPSHOT events with activity type a2ui-surface; @ag-ui/core 1.0.2 defines no A2UI convention, and activity events carry exactly this kind of structured, replaceable UI state. The adapter on each side is this class and @ulams/sdk.
SourceIngested A source was converted and its fragments written (first upload of a builder session). Other packages react to it: Living Course records revision 1 of the source.
Command Description Signature
course-builder:eval Evaluate the Course Builder on golden fixtures (fake driver by default, –live for the real model) course-builder:eval {--fixtures=coffee : all, or a comma list of coffee, injection, git, pdf, docx} {--live : call the real model} {--record : write cassettes (tests/cassettes) from this run} {--author= : user id that owns the eval sessions (default: the first admin)} {--patch=1 : also run one element-chat patch on a quiz question} {--total-minutes=30 : course length for the brief}
course-builder:prune-events Delete Course Builder AG-UI events older than the retention period course-builder:prune-events
course-builder:session:export Write a builder session (brief, current and applied versions, sources and fragments) to a tar archive course-builder:session:export {session : Session id} {path : Archive to write (.tar)}
course-builder:session:import Create a builder session from an archive for an author of this tenant. The last output line is JSON with the new session id. course-builder:session:import {path : Archive written by course-builder:session:export} {--author-email= : The author of the new session; created as an admin with an invitation when missing} {--author-name= : Display name for a new author}

None.

COURSE_BUILDER_ADMIN_URL, COURSE_BUILDER_AUTO_FORMATS, COURSE_BUILDER_CONCURRENT_RUNS, COURSE_BUILDER_DISK, COURSE_BUILDER_DOCX_UNCOMPRESSED_MB, COURSE_BUILDER_EVAL_MONTHLY_USD, COURSE_BUILDER_EVENTS_RETENTION_DAYS, COURSE_BUILDER_FRONT_URL, COURSE_BUILDER_H5P, COURSE_BUILDER_INTERACTIVE, COURSE_BUILDER_LESSON_CONCURRENCY, COURSE_BUILDER_LIASCRIPT, COURSE_BUILDER_PDF_PAGES, COURSE_BUILDER_PRIVATE_ROOT, COURSE_BUILDER_QUEUE, COURSE_BUILDER_QUEUE_CONNECTION, COURSE_BUILDER_SESSION_COST_USD, COURSE_BUILDER_SESSION_TOKENS, COURSE_BUILDER_SESSIONS_PER_DAY, COURSE_BUILDER_SOURCE_MB, COURSE_BUILDER_SOURCE_TOKENS, COURSE_BUILDER_SSE_POLL_MS, COURSE_BUILDER_SSE_SECONDS, QUEUE_CONNECTION