recess-cli 2.6.1 → 2.8.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 CHANGED
@@ -274,7 +274,10 @@ recess --json goals list --student <kid-id> --reason "Review the student's goals
274
274
  recess --json todos create --student <kid-id> --title "Read chapter 4" --reason "Add the assigned reading"
275
275
  recess --json todos complete <todo-id> --xp 35 --reason "Complete the todo with a 35 XP total reward"
276
276
  recess --json goals delete <goal-id> --student <kid-id> --reason "Remove this obsolete goal"
277
+ recess --json goals restore <goal-id> --student <kid-id> --reason "Restore this goal"
277
278
  recess --json todos delete <todo-id> --reason "Remove this disposable todo"
279
+ recess --json todos restore <todo-id> --reason "Restore this todo"
280
+ recess --json todos generate-learning-analysis <todo-id> --reason "Backfill this todo's missing learning analysis"
278
281
  recess --json todos generate-applet <todo-id> --student <kid-id> --reason "Generate this todo's applet"
279
282
  recess --json memories context --student <kid-id> --reason "Review durable tutor context"
280
283
  recess --json memories log --student <kid-id> --date 2026-08-12 --reason "Review the learning log for this date"
@@ -286,7 +289,12 @@ into the confirmed request. `todos complete` is staff-only; `--xp` is the target
286
289
  todo, so its preview reports prior credit and the new delta before the normal completion and reward
287
290
  side effects run. Applet generation is also staff-only: it resolves the todo's latest learning
288
291
  analysis, defaults the generated todo to tomorrow in the student's timezone, and lets the server
289
- select v1 or v2 for that student. A guardian cannot target another family, inspect frozen/deleted
292
+ select v1 or v2 for that student. Learning-analysis generation is ADMIN-only and queues the
293
+ idempotent forensic pipeline from the latest completed Gemini analysis without rerunning completion
294
+ or rewards. Goal and todo deletion is soft-only. Restoring a goal retains its Mesa workspace,
295
+ rechecks open-goal capacity, and restores only linked todos sharing that deletion's tombstone;
296
+ standalone todo restore uses the same preview-bound tombstone check. A guardian cannot target
297
+ another family, inspect frozen/deleted
290
298
  template history, choose todo rewards/completion/internal fields, or use the ADMIN-only
291
299
  device-authorization flow. `memories context` and `memories log` read only the tutor repository's
292
300
  spine, rules, reminders, and session logs; private guide remarks are never returned. The CLI does
package/dist/api.js CHANGED
@@ -19,16 +19,19 @@ export class RecessAdminApi {
19
19
  clientTag;
20
20
  client;
21
21
  villageSessionPromise;
22
- constructor(config, reason, clientTag = RECESS_CLIENT_CLI) {
22
+ constructor(config, reason, clientTag = RECESS_CLIENT_CLI, clientOverride, fetchOverride) {
23
23
  this.config = config;
24
24
  this.reason = reason;
25
25
  this.clientTag = clientTag;
26
- this.client = createClient({
27
- baseUrl: config.apiOrigin,
28
- headers: config.sessionCookie
29
- ? { cookie: config.sessionCookie }
30
- : undefined,
31
- });
26
+ this.client =
27
+ clientOverride ??
28
+ createClient({
29
+ baseUrl: config.apiOrigin,
30
+ headers: config.sessionCookie
31
+ ? { cookie: config.sessionCookie }
32
+ : undefined,
33
+ ...(fetchOverride ? { fetch: fetchOverride } : {}),
34
+ });
32
35
  const requestReason = this.reason;
33
36
  const requestClientTag = this.clientTag;
34
37
  this.client.use({
@@ -162,7 +165,9 @@ export class RecessAdminApi {
162
165
  async uploadMapTestScores(studentId, pdf, fileName) {
163
166
  this.requireAuth();
164
167
  const formData = new FormData();
165
- formData.append("file", new Blob([pdf], { type: "application/pdf" }), fileName);
168
+ const pdfBody = new Uint8Array(pdf.byteLength);
169
+ pdfBody.set(pdf);
170
+ formData.append("file", new Blob([pdfBody.buffer], { type: "application/pdf" }), fileName);
166
171
  const headers = cliRequestHeaders({ cookie: this.config.sessionCookie }, this.reason, this.clientTag);
167
172
  applyIdempotencyHeaders(headers);
168
173
  const response = await fetch(new URL(`/tutor/students/${encodeURIComponent(studentId)}/map-test-scores/upload`, this.config.apiOrigin), {
package/dist/args.js CHANGED
@@ -32,7 +32,6 @@ const BOOLEAN_FLAGS = new Set([
32
32
  "starter-only",
33
33
  "unlink",
34
34
  "visual-only",
35
- "version",
36
35
  "wait",
37
36
  ]);
38
37
  export function parseArgs(args) {