@novedu/cli 0.17.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +134 -1
- package/dist/main.js +1857 -343
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -5,7 +5,8 @@ requires Node >= 20). It covers two jobs:
|
|
|
5
5
|
|
|
6
6
|
- **Validate activity YAML** — tutors, fragment libraries, quizzes, writing
|
|
7
7
|
activities, and coding activities — with the app's exact validation pipeline,
|
|
8
|
-
offline and without signing in.
|
|
8
|
+
offline and without signing in. `prompts` dumps the exact system prompts an
|
|
9
|
+
activity produces, the same way.
|
|
9
10
|
- **Manage the app as a teacher** — sign in with Microsoft Entra ID, then mint
|
|
10
11
|
activity codes, upload app-hosted YAML files and images, and triage student
|
|
11
12
|
reports, straight from the terminal (or from a coding agent, see below).
|
|
@@ -42,6 +43,54 @@ npx @novedu/cli validate ./my-quiz.yaml --kind quiz --json
|
|
|
42
43
|
validates every fragment library it references.
|
|
43
44
|
- Exit code `0` = valid, `1` = errors found — usable as a pre-commit / CI gate.
|
|
44
45
|
|
|
46
|
+
## Seeing the exact prompts: `prompts`
|
|
47
|
+
|
|
48
|
+
`prompts` prints the **exact system prompts** an activity YAML produces — the
|
|
49
|
+
strings the app really sends to the model. Offline and sign-in-free, exactly like
|
|
50
|
+
`validate`.
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# A tutor's assembled system prompt (summary: kind, id, model, size per prompt)
|
|
54
|
+
npx @novedu/cli prompts ./activities/examples/sorting-algorithms/sorting-tutor.yaml
|
|
55
|
+
|
|
56
|
+
# A quiz: one grading prompt per question + the discussion prompt, full text as JSON
|
|
57
|
+
npx @novedu/cli prompts ./sorting-quiz.yaml --kind quiz --json
|
|
58
|
+
|
|
59
|
+
# A writing activity's coach prompt, a coding activity's injected system prompt
|
|
60
|
+
npx @novedu/cli prompts ./my-writing.yaml --kind writing
|
|
61
|
+
npx @novedu/cli prompts ./my-coding.yaml --kind coding
|
|
62
|
+
|
|
63
|
+
# A published activity by URL (same argument as `validate`)
|
|
64
|
+
npx @novedu/cli prompts https://raw.githubusercontent.com/Teaching-HTL-Leonding/novedu-chat-mvp/refs/heads/main/activities/examples/sorting-algorithms/sorting-tutor.yaml
|
|
65
|
+
|
|
66
|
+
# Pull out one question's grading prompt
|
|
67
|
+
npx @novedu/cli prompts ./sorting-quiz.yaml --kind quiz --json \
|
|
68
|
+
| jq -r '.grading.questions[] | select(.id=="q3") | .system'
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
- The argument is a **local path or a public `http(s)` URL**, exactly like
|
|
72
|
+
`validate`'s; relative `fragment_files` / `quiz_files` / `text_files` resolve
|
|
73
|
+
against the activity's own location (sibling file, or sibling URL). "Offline"
|
|
74
|
+
means no app server, no database and no LLM call — not "no network".
|
|
75
|
+
- `--kind` accepts `tutor` (default), `quiz`, `writing` or `coding` — the same
|
|
76
|
+
caller-declared flag as `validate`. There is no `fragment` kind: a library has
|
|
77
|
+
no prompt of its own; its fragments appear **rendered in place** inside the
|
|
78
|
+
activity that places them.
|
|
79
|
+
- Every dump comes out of the app's own prompt builders and runtime loaders (no
|
|
80
|
+
re-implementation), so what you see is what the model gets: fragments resolved,
|
|
81
|
+
and — for a compound quiz — every `quiz_files` include fetched, each imported
|
|
82
|
+
question carrying its source quiz's preamble.
|
|
83
|
+
- Every dump carries `{ kind, id, llm: { provider, model } }`. A **quiz** adds
|
|
84
|
+
`grading` (a `system` prompt per question, the user-message templates and the
|
|
85
|
+
grader's JSON-Schema response contract) and `discussion` (the chat's `system`
|
|
86
|
+
prompt, the three seed-message templates and the verdict wording). A **coding**
|
|
87
|
+
activity also reports `upstreamSystemMessage` — what the proxy puts on the wire.
|
|
88
|
+
- The **activity's own** `llm` block is reported; a code's per-code LLM override
|
|
89
|
+
is not applied (a dump describes a file, and a file has no code).
|
|
90
|
+
- This runs the runtime load path, so a file that cannot be loaded exits `1` with
|
|
91
|
+
JSON errors on stderr. Use `validate` for the strict authoring check — the two
|
|
92
|
+
are complementary.
|
|
93
|
+
|
|
45
94
|
## Authentication
|
|
46
95
|
|
|
47
96
|
Commands that talk to the running app authenticate with Microsoft Entra ID:
|
|
@@ -87,6 +136,7 @@ codes create --module <tutor|quiz|writing|coding> --file <url>
|
|
|
87
136
|
[--start <iso>] [--end <iso>] [--note <text>]
|
|
88
137
|
[--llm-provider <p> --llm-model <m>]
|
|
89
138
|
codes list [--search <q>] [--module <m>] [--all]
|
|
139
|
+
codes sync <registry-file> [--lock <path>] [--dry-run] [--json]
|
|
90
140
|
files upload <name> [--kind <tutor|fragment|quiz|writing|coding>]
|
|
91
141
|
(--file <path> | reads stdin)
|
|
92
142
|
files list [--search <q>] [--all]
|
|
@@ -103,6 +153,8 @@ images list [--search <q>] [--all]
|
|
|
103
153
|
shareable `url`. `--start`/`--end` must be ISO 8601 **with an explicit
|
|
104
154
|
offset or `Z`** (e.g. `2026-07-07T08:00:00Z`); the
|
|
105
155
|
`--llm-provider`/`--llm-model` override pair is both-or-nothing.
|
|
156
|
+
- `codes sync <registry-file>` mints codes for a whole **course** at once — see
|
|
157
|
+
[Many activities at once](#many-activities-at-once-codes-sync) below.
|
|
106
158
|
- `files upload <name>` is an **upsert**: creating a new file requires
|
|
107
159
|
`--kind`; an existing file's kind is frozen at create time (a contradicting
|
|
108
160
|
`--kind` fails with 409). The YAML comes from `--file <path>` or stdin.
|
|
@@ -150,6 +202,87 @@ image:
|
|
|
150
202
|
alt: Merge sort splitting an array
|
|
151
203
|
```
|
|
152
204
|
|
|
205
|
+
## Many activities at once: `codes sync`
|
|
206
|
+
|
|
207
|
+
A course with twenty quizzes should not be twenty `codes create` calls whose
|
|
208
|
+
codes you paste into twenty files by hand. Instead, keep an **activity registry**
|
|
209
|
+
next to the material: one hand-written YAML file listing every activity under a
|
|
210
|
+
stable key, plus a **lock file** the CLI generates and you commit.
|
|
211
|
+
|
|
212
|
+
```yaml
|
|
213
|
+
# yaml-language-server: $schema=https://raw.githubusercontent.com/Teaching-HTL-Leonding/novedu-chat-mvp/refs/heads/main/activities/registry/registry-yaml.schema.json
|
|
214
|
+
# ddp-activities.yaml — the registry (you write this)
|
|
215
|
+
base-url: "https://raw.githubusercontent.com/acme/course/refs/heads/main/"
|
|
216
|
+
|
|
217
|
+
activities:
|
|
218
|
+
quizzes:
|
|
219
|
+
welcome:
|
|
220
|
+
file: 0010-introduction/0010-welcome-quiz.yaml
|
|
221
|
+
note: "Creative Coding book: Welcome (0010)"
|
|
222
|
+
number-systems:
|
|
223
|
+
file: 0030-conditions/0050-number-systems-quiz.yaml
|
|
224
|
+
start: 2026-09-01T00:00:00+02:00
|
|
225
|
+
end: 2027-01-31T23:59:59+01:00
|
|
226
|
+
tutors:
|
|
227
|
+
sorting:
|
|
228
|
+
url: https://novedu.at/api/files/sorting-tutor
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
npx @novedu/cli codes sync ddp-activities.yaml
|
|
233
|
+
# ddp-activities.yaml: 3 entries
|
|
234
|
+
# reused welcome cu4afwoa23 https://novedu.at/cu4afwoa23
|
|
235
|
+
# minted number-systems hb34gpvahn https://novedu.at/hb34gpvahn
|
|
236
|
+
# reused sorting nlc90ezf5z https://novedu.at/nlc90ezf5z
|
|
237
|
+
#
|
|
238
|
+
# 2 reused, 1 minted, 0 failed
|
|
239
|
+
# Lock file: ddp-activities.lock.yaml
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
```yaml
|
|
243
|
+
# ddp-activities.lock.yaml — generated; commit it, do not edit it
|
|
244
|
+
activity-codes:
|
|
245
|
+
number-systems: hb34gpvahn
|
|
246
|
+
sorting: nlc90ezf5z
|
|
247
|
+
welcome: cu4afwoa23
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
- **Groups decide the module:** `quizzes`, `tutors`, `writing`, `coding`. Each
|
|
251
|
+
entry gives either `file` (relative to `base-url`, which must end in `/`) or
|
|
252
|
+
an absolute `url`, plus any of `start`/`end` (ISO 8601 **with an offset or
|
|
253
|
+
`Z`**, whole seconds), `note`, and an `llm: {provider, model}` override.
|
|
254
|
+
- **Keys are yours and must be unique across all groups** — lowercase letters,
|
|
255
|
+
digits and hyphens. Your material references the key; the lock file maps it to
|
|
256
|
+
the code.
|
|
257
|
+
- **Re-runs are safe.** An entry whose activity, window and model override match
|
|
258
|
+
an existing code of yours **reuses** that code; only entries without a match
|
|
259
|
+
are minted. So `codes sync` after every edit is the normal workflow, and the
|
|
260
|
+
first run against already-minted codes should report all-reused.
|
|
261
|
+
- **Changing a window or override mints a NEW code.** The old one is not touched
|
|
262
|
+
(it keeps working) and is reported as superseded — delete it in the web app
|
|
263
|
+
when the class has moved on. Changing only the `note` never forks a code.
|
|
264
|
+
- `--dry-run` shows what would happen without minting or writing anything;
|
|
265
|
+
`--json` prints the machine-readable report; `--lock <path>` puts the lock file
|
|
266
|
+
somewhere else.
|
|
267
|
+
- One broken activity does not stop the run: it is reported as `failed`, the
|
|
268
|
+
other entries still sync, the lock keeps that entry's previous code, and the
|
|
269
|
+
command exits 1.
|
|
270
|
+
- **A key keeps its code.** Two keys may point at the same activity on purpose
|
|
271
|
+
(one quiz linked from two chapters, each with its own statistics); they get one
|
|
272
|
+
code each, and neither moves on a later run.
|
|
273
|
+
- Unknown extra keys are ignored, so you can annotate entries freely — but an
|
|
274
|
+
entry with nothing under it is an error, not an annotation, because that is
|
|
275
|
+
what a mis-indented entry looks like.
|
|
276
|
+
- The `# yaml-language-server:` line on top is optional: it gives editors with
|
|
277
|
+
YAML support field completion, hover help and a warning on a misspelled group
|
|
278
|
+
name. `codes sync` is still the authority — it checks things a schema cannot,
|
|
279
|
+
such as key uniqueness and whether `end` is after `start`.
|
|
280
|
+
|
|
281
|
+
Publications read the lock file offline. In a Quarto book, for example, add
|
|
282
|
+
`metadata-files: [ddp-activities.lock.yaml]` to `_quarto.yml` and let the
|
|
283
|
+
shortcode look the key up in `activity-codes` — the book then renders without
|
|
284
|
+
ever calling the app.
|
|
285
|
+
|
|
153
286
|
## Triaging student reports (teacher account required)
|
|
154
287
|
|
|
155
288
|
Students can flag an AI interaction — a chat or a graded quiz answer — with a
|