@theronap/agnoclast-mcp 0.9.251 → 0.9.252

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.
@@ -216,7 +216,7 @@ export const CREATE_EVENT_DESCRIPTION = 'Put an event on the person\'s calendar
216
216
 
217
217
  export const UPDATE_EVENT_DESCRIPTION = 'Fix, move or cancel ONE event the person made on their Agnoclast calendar — a new time, an end or length, a new name or place, or `cancel: true` to take it off the calendar (one meeting of a repeating event too, e.g. no class on a holiday) — when they ask. Pass `event_id` (create_event and upcoming print it) and ONLY what changes. Moving the start keeps the event\'s length unless you also give `end`; a time with no offset is read in their own timezone. Pass "" as `end` or `location` to remove it. `cancel: false` puts a cancelled event back. To change or remove EVERY meeting of a repeating event, use update_series. Only events made on the Agnoclast calendar can be changed — never Google or Outlook ones.'
218
218
 
219
- export const UPDATE_SERIES_DESCRIPTION = 'Change or delete a whole repeating event (a class or standing meeting made in Agnoclast) when the person asks. Name it with `series`: its exact title, its key, or its id; an unknown or ambiguous name answers with the choices. Pass ONLY what changes: `days` (MO TU WE TH FR SA SU), `start_time` / `end_time` (HH:MM, their local time), `from` / `until` (YYYY-MM-DD), `location` ("" removes it), `title`. Changes apply from today on: meetings that already happened keep their time, and a meeting cancelled on its own stays cancelled. `delete: true` removes the series and every upcoming meeting (past ones stay where they were filed). `container_type` changes what each meeting owes: meeting = a transcript or a note · work_block = a work session in the window · deadline = the artifact · appointment = nothing (a class, a visit). To change ONE meeting, use update_event instead.'
219
+ export const UPDATE_SERIES_DESCRIPTION = 'Change or delete a whole repeating event (a class or standing meeting made in Agnoclast) when the person asks. Name it with `series`: its exact title, its key, or its id; an unknown or ambiguous name answers with the choices. Pass ONLY what changes: `days` (MO TU WE TH FR SA SU), `start_time` / `end_time` (HH:MM, their local time), `from` / `until` (YYYY-MM-DD), `location` ("" removes it), `title`. Changes apply from today on: meetings that already happened keep their time, and a meeting cancelled on its own stays cancelled. EXCEPTIONS by date (YYYY-MM-DD): `cancel_dates` skips those meetings (a holiday), `restore_dates` puts them back, `add_dates` adds one extra meeting on that day at the series\' own time (e.g. a Tuesday that runs a Monday schedule); a meeting moved by hand with update_event keeps its new time through any later change. `delete: true` removes the series and every upcoming meeting (past ones stay where they were filed). `container_type` changes what each meeting owes: meeting = a transcript or a note · work_block = a work session in the window · deadline = the artifact · appointment = nothing (a class, a visit). To change ONE meeting, use update_event instead.'
220
220
 
221
221
  /** PATCH /api/series/<ref> body for update_series, or null when nothing would change (event_time.ts seriesPatchBody). */
222
222
  export function seriesPatchBody(args) {
@@ -231,6 +231,9 @@ export function seriesPatchBody(args) {
231
231
  if (str(args.from)) body.windowFrom = str(args.from)
232
232
  if (str(args.until)) body.windowUntil = str(args.until)
233
233
  if (args.location !== undefined) body.location = str(args.location) || null
234
+ if (Array.isArray(args.cancel_dates) && args.cancel_dates.length) body.cancelDates = args.cancel_dates
235
+ if (Array.isArray(args.restore_dates) && args.restore_dates.length) body.restoreDates = args.restore_dates
236
+ if (Array.isArray(args.add_dates) && args.add_dates.length) body.addDates = args.add_dates
234
237
  return Object.keys(body).length === 0 ? null : body
235
238
  }
236
239
 
@@ -251,7 +254,7 @@ export function renderSeriesCreated(title, when, tz, body) {
251
254
  }
252
255
  if (body?.page?.title) lines.push(`Filed to the page "${oneLine(body.page.title, 120)}", so anything from those meetings lands there.`)
253
256
  lines.push(`It shows on ${CONSOLE}/calendar and in upcoming. Nothing was added to Google or Outlook, and no one was invited.`)
254
- lines.push(`To move ONE meeting, use update_event with that meeting's event id from upcoming. Changing the whole series' days or times is not possible yet${body?.identifier ? ` (series ${body.identifier})` : ''}.`)
257
+ lines.push(`To change it later, use update_series${body?.identifier ? ` (series ${body.identifier})` : ''}: its days or times, cancel_dates for a holiday, add_dates for an extra meeting, or delete. update_event changes one meeting by its event id.`)
255
258
  return lines.join('\n')
256
259
  }
257
260
 
@@ -285,7 +288,13 @@ export function renderSeriesRevised(r) {
285
288
  `${r.upcoming ?? 0} upcoming meeting(s) on the calendar${r.firstStartsAt ? `; the next is ${dayLabel(new Date(r.firstStartsAt), tz)}, ${timeLabel(new Date(r.firstStartsAt), tz)}${r.firstEndsAt ? `–${timeLabel(new Date(r.firstEndsAt), tz)}` : ''}` : ''}.`,
286
289
  ]
287
290
  if (r.cancelled) lines.push(`${r.cancelled} meeting(s) no longer on the schedule were cancelled.`)
288
- lines.push('Meetings that already happened keep their time. A meeting cancelled on its own with update_event stays cancelled.')
291
+ const d = r.dates ?? {}
292
+ const day = (ymd) => allDayLabel(ymd)
293
+ if (d.cancelled?.length) lines.push(`Cancelled: ${d.cancelled.map(day).join('; ')}.`)
294
+ if (d.restored?.length) lines.push(`Back on the calendar: ${d.restored.map(day).join('; ')}.`)
295
+ if (d.added?.length) lines.push(`Extra meeting added: ${d.added.map(day).join('; ')}.`)
296
+ if (d.skipped?.length) lines.push(`Not changed: ${d.skipped.map((x) => `${day(x.date)} (${x.why})`).join('; ')}.`)
297
+ lines.push('Meetings that already happened keep their time. Your exceptions (a cancelled, moved or added meeting) stay through any later change.')
289
298
  return lines.join('\n')
290
299
  }
291
300
 
package/lib/server.mjs CHANGED
@@ -5523,13 +5523,16 @@ function renderNudge(payload) {
5523
5523
  until: z.string().optional().describe('new last date, YYYY-MM-DD'),
5524
5524
  location: z.string().optional().describe('new place; "" removes it'),
5525
5525
  container_type: z.enum(['meeting', 'work_block', 'deadline', 'appointment']).optional().describe('what each meeting owes'),
5526
+ cancel_dates: z.array(z.string()).optional().describe('skip the meeting on these dates (YYYY-MM-DD) — e.g. a holiday'),
5527
+ restore_dates: z.array(z.string()).optional().describe('put back a cancelled meeting on these dates'),
5528
+ add_dates: z.array(z.string()).optional().describe('one extra meeting on each of these dates, at the series\' own time'),
5526
5529
  },
5527
5530
  },
5528
5531
  async (args) => {
5529
5532
  const ref = String(args.series ?? '').trim().replace(/^series:/i, '')
5530
5533
  if (!ref) return toolError('series is required — its title, key or id.')
5531
5534
  const body = seriesPatchBody(args)
5532
- if (!body) return toolError('Say what to change: days, start_time, end_time, from, until, location, title, container_type — or delete: true.')
5535
+ if (!body) return toolError('Say what to change: days, start_time, end_time, from, until, location, title, container_type, cancel_dates, restore_dates, add_dates — or delete: true.')
5533
5536
  let res
5534
5537
  try {
5535
5538
  res = await fetchCortex(`${BASE}/api/series/${encodeURIComponent(ref)}`, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theronap/agnoclast-mcp",
3
- "version": "0.9.251",
3
+ "version": "0.9.252",
4
4
  "description": "Connect your AI assistant to Cortex — your org's projects, activity, gaps, and directives, scoped to you.",
5
5
  "type": "module",
6
6
  "bin": {