recess-cli 1.9.0 → 1.9.1
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 +4 -1
- package/dist/cli.js +59 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -197,13 +197,16 @@ recess --json students schedule --student <kid-id> --days 30
|
|
|
197
197
|
recess --json students xp-history --student <kid-id> --range month
|
|
198
198
|
recess --json goals list --student <kid-id>
|
|
199
199
|
recess --json todos create --student <kid-id> --title "Read chapter 4"
|
|
200
|
+
recess --json todos generate-applet <todo-id> --student <kid-id> [--due-date YYYY-MM-DD]
|
|
200
201
|
recess --json memories context --student <kid-id>
|
|
201
202
|
recess --json memories log --student <kid-id> --date 2026-08-12
|
|
202
203
|
recess --json rocky get --student <kid-id>
|
|
203
204
|
```
|
|
204
205
|
|
|
205
206
|
All family writes still preview first. Goal/todo/Rocky edits also carry the current server version
|
|
206
|
-
into the confirmed request.
|
|
207
|
+
into the confirmed request. Applet generation is staff-only: it resolves the todo's latest learning
|
|
208
|
+
analysis, defaults the generated todo to tomorrow in the student's timezone, and lets the server
|
|
209
|
+
select v1 or v2 for that student. A guardian cannot target another family, inspect frozen/deleted
|
|
207
210
|
template history, choose todo rewards/completion/internal fields, or use the ADMIN-only
|
|
208
211
|
device-authorization flow. `memories context` and `memories log` read only the tutor repository's
|
|
209
212
|
spine, rules, reminders, and session logs; private guide remarks are never returned. The CLI does
|
package/dist/cli.js
CHANGED
|
@@ -180,6 +180,8 @@ Usage:
|
|
|
180
180
|
[--due-date YYYY-MM-DD] [--estimated-minutes N] [--url URL] [--confirm]
|
|
181
181
|
recess [--json] todos edit <todo-id> --patch-file <path/patch.json>
|
|
182
182
|
[--confirm --approval-token TOKEN]
|
|
183
|
+
recess [--json] todos generate-applet <todo-id> --student <kid-id>
|
|
184
|
+
[--due-date YYYY-MM-DD] [--confirm --approval-token TOKEN]
|
|
183
185
|
recess [--json] memories context --student <kid-id>
|
|
184
186
|
recess [--json] memories log --student <kid-id> --date YYYY-MM-DD
|
|
185
187
|
recess [--json] rocky get --student <kid-id>
|
|
@@ -1175,6 +1177,20 @@ function flagItemDateMs(parsed) {
|
|
|
1175
1177
|
}
|
|
1176
1178
|
return ms;
|
|
1177
1179
|
}
|
|
1180
|
+
function flagDateOnly(parsed, name) {
|
|
1181
|
+
const raw = flagString(parsed, name);
|
|
1182
|
+
if (raw === undefined)
|
|
1183
|
+
return undefined;
|
|
1184
|
+
const parsedDate = /^\d{4}-\d{2}-\d{2}$/.test(raw)
|
|
1185
|
+
? new Date(`${raw}T00:00:00.000Z`)
|
|
1186
|
+
: null;
|
|
1187
|
+
if (!parsedDate ||
|
|
1188
|
+
Number.isNaN(parsedDate.getTime()) ||
|
|
1189
|
+
parsedDate.toISOString().slice(0, 10) !== raw) {
|
|
1190
|
+
throw new CliError("invalid_arguments", `--${name} must be a valid YYYY-MM-DD date.`);
|
|
1191
|
+
}
|
|
1192
|
+
return raw;
|
|
1193
|
+
}
|
|
1178
1194
|
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
1179
1195
|
// The cohort event routes take zoneless local wall-clock datetimes
|
|
1180
1196
|
// (interpreted in the cohort's timezone server-side).
|
|
@@ -3423,7 +3439,49 @@ export async function runCommand(argv) {
|
|
|
3423
3439
|
body,
|
|
3424
3440
|
}));
|
|
3425
3441
|
}
|
|
3426
|
-
|
|
3442
|
+
if (verb === "generate-applet") {
|
|
3443
|
+
const todoId = positional(parsed, 2, "todo ID");
|
|
3444
|
+
const studentId = flagString(parsed, "student", { required: true });
|
|
3445
|
+
const targetDueDateISO = flagDateOnly(parsed, "due-date");
|
|
3446
|
+
const [todo, learningAnalysis] = await Promise.all([
|
|
3447
|
+
api.client.GET("/tutor/browser/todos/{id}/", {
|
|
3448
|
+
params: { path: { id: todoId } },
|
|
3449
|
+
}),
|
|
3450
|
+
api.client.GET("/tutor/students/{studentId}/todos/{todoId}/learning-analysis", {
|
|
3451
|
+
params: { path: { studentId, todoId } },
|
|
3452
|
+
}),
|
|
3453
|
+
]);
|
|
3454
|
+
const currentTodo = unwrap(todo);
|
|
3455
|
+
if (currentTodo.userId !== studentId) {
|
|
3456
|
+
throw new CliError("not_found", "The todo does not belong to the requested student.");
|
|
3457
|
+
}
|
|
3458
|
+
const analysis = unwrap(learningAnalysis).analysis;
|
|
3459
|
+
if (!analysis) {
|
|
3460
|
+
throw new CliError("not_found", "This todo does not have a learning analysis to generate an applet from.");
|
|
3461
|
+
}
|
|
3462
|
+
const preview = {
|
|
3463
|
+
action: "generate an applet from a student's todo analysis",
|
|
3464
|
+
target: {
|
|
3465
|
+
studentUserId: studentId,
|
|
3466
|
+
todoId,
|
|
3467
|
+
todoTitle: currentTodo.title,
|
|
3468
|
+
analysisId: analysis.id,
|
|
3469
|
+
},
|
|
3470
|
+
request: {
|
|
3471
|
+
targetDueDateISO: targetDueDateISO ?? null,
|
|
3472
|
+
},
|
|
3473
|
+
details: {
|
|
3474
|
+
dueDate: targetDueDateISO ?? "tomorrow in the student's timezone",
|
|
3475
|
+
versionRouting: "The server evaluates applet-gen-v2 for this student and uses v1 when the flag is off or its evaluation fails.",
|
|
3476
|
+
},
|
|
3477
|
+
};
|
|
3478
|
+
requirePreviewBoundConfirmation(parsed, preview);
|
|
3479
|
+
return unwrap(await api.client.POST("/admin/learning-pipeline/{analysisId}/generate-applet/", {
|
|
3480
|
+
params: { path: { analysisId: analysis.id } },
|
|
3481
|
+
body: targetDueDateISO ? { targetDueDateISO } : {},
|
|
3482
|
+
}));
|
|
3483
|
+
}
|
|
3484
|
+
throw new CliError("invalid_arguments", "Use todos create|edit|generate-applet.");
|
|
3427
3485
|
}
|
|
3428
3486
|
if (noun === "memories") {
|
|
3429
3487
|
const studentId = flagString(parsed, "student", { required: true });
|