Commite96ab221Recorded22 Apr 2026Repositorybureau

Merge fix/folio-log-crash

Message

Validate required MCP args with require-arg helper.

Mirror the folio fix in email.sgl + calendar.sgl: undefaulted (dict-ref args KEY:) calls now raise 'Missing required argument: KEY'. Closes t-a06a (bureau email-read crashing on every call with 'dict-ref: key not found').

Rebuild against sigil master (8738c6f0) via committed dev-redirects.sgl until a sigil tag is cut.

Changed
 src/bureau/calendar.sgl | 24 ++++++++++++------------
 src/bureau/email.sgl    | 50 +++++++++++++++++++++++++++++++-------------------
 2 files changed, 43 insertions(+), 31 deletions(-)
Diff

A merge. Shown against its first parent, so this is the effect of merging rather than the work of the branch.

src/bureau/calendar.sglmodified
@@ -164,8 +164,8 @@
164
165
(define (tool-events args)
166
(let* ((client (ensure-caldav-client))
167
(start (parse-iso8601 (dict-ref args start:)))
168
(end (parse-iso8601 (dict-ref args end:)))
+167
(start (parse-iso8601 (require-arg args start: "start")))
+168
(end (parse-iso8601 (require-arg args end: "end")))
169
(calendar-name (dict-ref args calendar: #f))
170
(expand? (dict-ref args expand-recurring: #t))
171
(calendars (resolve-calendars client calendar-name))
@@ -178,7 +178,7 @@
178
179
(define (tool-event-details args)
180
(let* ((client (ensure-caldav-client))
181
(url (dict-ref args url:))
+181
(url (require-arg args url: "url"))
182
(event (caldav-event-get client url)))
183
(if event
184
(format-event-full event)
@@ -192,9 +192,9 @@
192
193
(define (tool-event-create args)
194
(let* ((client (ensure-caldav-client))
195
(summary (dict-ref args summary:))
196
(start (parse-iso8601 (dict-ref args start:)))
197
(end (parse-iso8601 (dict-ref args end:)))
+195
(summary (require-arg args summary: "summary"))
+196
(start (parse-iso8601 (require-arg args start: "start")))
+197
(end (parse-iso8601 (require-arg args end: "end")))
198
(calendar-name (dict-ref args calendar: #f))
199
(description (dict-ref args description: #f))
200
(location (dict-ref args location: #f))
@@ -231,7 +231,7 @@
231
232
(define (tool-event-update args)
233
(let* ((client (ensure-caldav-client))
234
(url (dict-ref args url:))
+234
(url (require-arg args url: "url"))
235
(event (caldav-event-get client url))
236
(_ (unless event (error (string-append "Event not found: " url))))
237
;; Apply updates
@@ -250,8 +250,8 @@
250
251
(define (tool-event-add-attendees args)
252
(let* ((client (ensure-caldav-client))
253
(url (dict-ref args url:))
254
(attendees-str (dict-ref args attendees:))
+253
(url (require-arg args url: "url"))
+254
(attendees-str (require-arg args attendees: "attendees"))
255
(new-attendees (parse-attendee-list attendees-str))
256
(event (caldav-event-get client url))
257
(_ (unless event (error (string-append "Event not found: " url))))
@@ -272,14 +272,14 @@
272
273
(define (tool-event-delete args)
274
(let* ((client (ensure-caldav-client))
275
(url (dict-ref args url:)))
+275
(url (require-arg args url: "url")))
276
(caldav-event-delete! client url)
277
(string-append "Event deleted: " url)))
278
279
(define (tool-free-slots args)
280
(let* ((client (ensure-caldav-client))
281
(start (parse-iso8601 (dict-ref args start:)))
282
(end (parse-iso8601 (dict-ref args end:)))
+281
(start (parse-iso8601 (require-arg args start: "start")))
+282
(end (parse-iso8601 (require-arg args end: "end")))
283
(calendar-name (dict-ref args calendar: #f))
284
(min-duration (* (dict-ref args min-duration: 30) 60)) ;; convert to seconds
285
(working-hours? (dict-ref args working-hours-only: #t))
src/bureau/email.sglmodified
@@ -16,6 +16,18 @@
16
normalize-utc-date)
17
(begin
18
+19
;; ============================================================
+20
;; Argument validation
+21
;; ============================================================
+22
+23
;; Look up a required argument in a tool's args dict. Raises a
+24
;; user-facing error naming the missing key instead of sigil's
+25
;; opaque `dict-ref: key not found`.
+26
(define (require-arg args key name)
+27
(if (dict-contains? args key)
+28
(dict-ref args key)
+29
(error (string-append "Missing required argument: " name))))
+30
31
;; ============================================================
32
;; Mailbox Resolution
33
;; ============================================================
@@ -273,7 +285,7 @@
285
286
(define (tool-email-read args)
287
(let* ((client (ensure-jmap-client))
276
(id (dict-ref args id:))
+288
(id (require-arg args id: "id"))
289
(email (jmap-email-get client id)))
290
(if email
291
(format-email-full email)
@@ -281,8 +293,8 @@
293
294
(define (tool-email-send args)
295
(let* ((client (ensure-jmap-client))
284
(to-str (dict-ref args to:))
285
(subject (dict-ref args subject:))
+296
(to-str (require-arg args to: "to"))
+297
(subject (require-arg args subject: "subject"))
298
(body (dict-ref args body: #f))
299
(html-body (dict-ref args html-body: #f))
300
(cc-str (dict-ref args cc: #f))
@@ -316,8 +328,8 @@
328
329
(define (tool-email-reply args)
330
(let* ((client (ensure-jmap-client))
319
(id (dict-ref args id:))
320
(body (dict-ref args body:))
+331
(id (require-arg args id: "id"))
+332
(body (require-arg args body: "body"))
333
(reply-all? (dict-ref args reply-all: #f))
334
(html-body (dict-ref args html-body: #f))
335
(identity-email (dict-ref args identity: #f))
@@ -403,8 +415,8 @@
415
416
(define (tool-email-move args)
417
(let* ((client (ensure-jmap-client))
406
(id (dict-ref args id:))
407
(mailbox-name (dict-ref args mailbox:))
+418
(id (require-arg args id: "id"))
+419
(mailbox-name (require-arg args mailbox: "mailbox"))
420
(mb (resolve-mailbox client mailbox-name))
421
(mb-id (dict-ref mb id:)))
422
(jmap-email-move! client id mb-id)
@@ -412,7 +424,7 @@
424
425
(define (tool-email-archive args)
426
(let* ((client (ensure-jmap-client))
415
(id (dict-ref args id:))
+427
(id (require-arg args id: "id"))
428
(archive (or (jmap-mailbox-by-role client "archive")
429
(error "Archive mailbox not found")))
430
(archive-id (dict-ref archive id:)))
@@ -421,7 +433,7 @@
433
434
(define (tool-email-trash args)
435
(let* ((client (ensure-jmap-client))
424
(id (dict-ref args id:))
+436
(id (require-arg args id: "id"))
437
(trash (or (jmap-mailbox-by-role client "trash")
438
(error "Trash mailbox not found")))
439
(trash-id (dict-ref trash id:)))
@@ -430,7 +442,7 @@
442
443
(define (tool-email-trash-batch args)
444
(let* ((client (ensure-jmap-client))
433
(ids-str (dict-ref args ids:))
+445
(ids-str (require-arg args ids: "ids"))
446
(ids (parse-id-list ids-str))
447
(trash (or (jmap-mailbox-by-role client "trash")
448
(error "Trash mailbox not found")))
@@ -440,7 +452,7 @@
452
453
(define (tool-email-archive-batch args)
454
(let* ((client (ensure-jmap-client))
443
(ids-str (dict-ref args ids:))
+455
(ids-str (require-arg args ids: "ids"))
456
(ids (parse-id-list ids-str))
457
(archive (or (jmap-mailbox-by-role client "archive")
458
(error "Archive mailbox not found")))
@@ -450,9 +462,9 @@
462
463
(define (tool-email-move-batch args)
464
(let* ((client (ensure-jmap-client))
453
(ids-str (dict-ref args ids:))
+465
(ids-str (require-arg args ids: "ids"))
466
(ids (parse-id-list ids-str))
455
(mailbox-name (dict-ref args mailbox:))
+467
(mailbox-name (require-arg args mailbox: "mailbox"))
468
(mb (resolve-mailbox client mailbox-name))
469
(mb-id (dict-ref mb id:)))
470
(jmap-email-move-many! client ids mb-id)
@@ -460,7 +472,7 @@
472
473
(define (tool-email-flag args)
474
(let* ((client (ensure-jmap-client))
463
(id (dict-ref args id:))
+475
(id (require-arg args id: "id"))
476
(unflag? (dict-ref args unflag: #f)))
477
(if unflag?
478
(begin (jmap-email-remove-keyword! client id "$flagged")
@@ -470,7 +482,7 @@
482
483
(define (tool-email-mark-read args)
484
(let* ((client (ensure-jmap-client))
473
(id (dict-ref args id:))
+485
(id (require-arg args id: "id"))
486
(unread? (dict-ref args unread: #f)))
487
(if unread?
488
(begin (jmap-email-remove-keyword! client id "$seen")
@@ -481,7 +493,7 @@
493
494
(define (tool-email-list-attachments args)
495
(let* ((client (ensure-jmap-client))
484
(id (dict-ref args id:))
+496
(id (require-arg args id: "id"))
497
(email (jmap-email-get client id)))
498
(unless email (error (string-append "Email not found: " id)))
499
(let ((attachments (dict-ref email attachments: #f)))
@@ -510,9 +522,9 @@
522
523
(define (tool-email-download-attachment args)
524
(let* ((client (ensure-jmap-client))
513
(id (dict-ref args id:))
514
(att-name (dict-ref args name:))
515
(dest-dir (dict-ref args path:))
+525
(id (require-arg args id: "id"))
+526
(att-name (require-arg args name: "name"))
+527
(dest-dir (require-arg args path: "path"))
528
(email (jmap-email-get client id)))
529
(unless email (error (string-append "Email not found: " id)))
530
(let ((attachments (dict-ref email attachments: #f)))