Skip to content

levelbuilder: generate lesson with AI (and project)#72651

Open
breville wants to merge 4 commits into
levelbuilder-ai-generate-lessonfrom
levelbuilder-ai-generate-lesson-project
Open

levelbuilder: generate lesson with AI (and project)#72651
breville wants to merge 4 commits into
levelbuilder-ai-generate-lessonfrom
levelbuilder-ai-generate-lesson-project

Conversation

@breville
Copy link
Copy Markdown
Member

@breville breville commented May 12, 2026

This builds on #72537 with an idea from @Erin007: an optional weblab2 project ID can be provided, and it's then passed as context to the lesson outline & lesson levels generation steps.

This means a levelbuilder can provide an example project which the generation process can then teach step by step.

Screenshot 2026-05-12 at 1 32 08 PM

breville and others added 4 commits May 12, 2026 18:10
New optional field on the lesson generator: a Web Lab 2 channel id
whose project source describes the app the lesson is building toward.
When set, the per-level AI prompts get the project's files as
additional "final goal" context so each weblab2 level reads as a step
on the path to that app, and adjacent panels can motivate or
foreshadow concepts that show up in the code. The student never sees
the target source; it lands only in the AI prompt.

Backend
- Add generate_project_channel_id serialized_attr on Lesson, exposed
  as generateProjectChannelId in summarize_for_lesson_edit and
  permitted by LessonsController#lesson_params.

Frontend
- New field on /generate above the prefix row; persisted alongside
  the outline by the existing saveLessonActivities save path. '' on
  save clears the value.
- helpers/targetProject.ts: format the channel's MultiFileSource into
  a flat "=== path ===\n<contents>" listing for the prompt. Skips
  non-user file types and bails to null on shapes that aren't
  MultiFileSource (Blockly, Excalidraw, missing source).
- levelApi.ts: loadProjectSources(channelId) hits GET
  /v3/sources/<id>/main.json (the same endpoint Lab2 uses at runtime;
  unauth-gated by abuse-score only).
- LessonGenerator fetches once per run, formats, threads through to
  every panels and weblab2 per-level call. Both AI prompts grow an
  explicit "Target project" section instructing the model to use it
  as a destination, not to emit it verbatim — the per-level
  description still scopes what the current level should build.
- Soft-fail end-to-end: a missing channel id, a failed fetch, or an
  unreadable shape just runs the generator without the extra context.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The outline phase is the highest-leverage decision in the run (it
picks the entire level sequence) and previously didn't see the
target project at all. Now it does: generateLessonOutline takes an
optional targetProject and quotes it under a "Target project"
section telling the model to plan weblab2 milestones as steps from
blank to that code, and to pick panels that motivate or recap the
concepts the target uses.

Refactor the source-fetch out of handleGenerate into a shared
loadTargetProject callback used by both handleGenerateOutline and
handleGenerate, so each invocation re-fetches (cheap; avoids stale
data if the channel id changes mid-session). Errors stay
soft-failing: no channel id, a failed fetch, or an unreadable shape
just runs the call with no target context — same as before this
change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The field feeds straight into the Generate-outline call, so putting
it inside the same collapsible panel — between the outline textarea
and the Generate-outline button — makes the data flow visible. The
levelbuilder reads top-to-bottom: describe the lesson, name an
optional target app, click Generate. Adds .outlineProjectRow /
.outlineProjectInput styles to match the rest of the block (label
above, help text below, 360px input).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Matches the outline-textarea pattern above it (description prose
before the field). Also switches the help element from <small> to
<p> so it sits in the normal paragraph flow above the input rather
than visually attaching to whatever followed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant