@mulmoclaude/google-plugin 1.0.1 → 1.1.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
@@ -12,9 +12,17 @@ dispatch). Server-only — no Vue View.
12
12
  OAuth client secret Google requires and stores nothing; tokens stay on the
13
13
  user's machine. A `~/.secrets/client_secret_*.json` (advanced) keeps the
14
14
  whole flow local instead.
15
- - Kinds: `status`; Calendar (`calendarListEvents`, `calendarCreateEvent`);
16
- Tasks (`taskListsList`, `tasksList`, `tasksCreate`, `tasksComplete`);
15
+ - Kinds: `status`; Calendar (`calendarListCalendars`, `calendarColors`,
16
+ `calendarListEvents`, `calendarSync`, `calendarCreateEvent`,
17
+ `calendarUpdateEvent`, `calendarDeleteEvent`); Tasks (`taskListsList`,
18
+ `tasksList`, `tasksCreate`, `tasksUpdate`, `tasksComplete`, `tasksDelete`);
17
19
  Drive (`driveList`, `driveCreate`, `driveRead`).
20
+ - Editing is a **patch**: omitted fields keep their value, and `""` clears a
21
+ description / notes. Deletes are irreversible, so the tool tells the agent to
22
+ confirm with the user first.
23
+ - Date-times must carry a **timezone offset** (`2026-07-17T09:00:00+09:00`);
24
+ Calendar rejects date-only and offset-less values with an opaque 400, so the
25
+ schema rejects them first with an actionable message.
18
26
  - **Drive is `drive.file`-scoped** — the app only ever sees files it created,
19
27
  never the user's wider Drive. That's what keeps the scope non-sensitive.
20
28
  - Not linked yet? The tool's errors tell the LLM to guide the user to this
@@ -22,9 +30,28 @@ dispatch). Server-only — no Vue View.
22
30
  per host (MulmoClaude: Settings → Plugins → Google or `yarn google:auth`;
23
31
  MulmoTerminal: Settings → Google account or `npx mulmoterminal google login`).
24
32
 
33
+ ## About MulmoClaude and MulmoTerminal
34
+
35
+ - **[MulmoClaude](https://github.com/receptron/mulmoclaude)** — an AI-native
36
+ application platform built on Claude Code. Chat summons the right GUI for each
37
+ task (documents, charts, forms, wikis, spreadsheets, 3D scenes), and
38
+ everything your assistant accumulates stays as plain files in your own
39
+ workspace, on your own machine.
40
+ - **[MulmoTerminal](https://github.com/receptron/mulmoterminal)** — run a whole
41
+ team of coding agents from your browser. Many Claude Code / Codex sessions at
42
+ once in a grid, colour-coded so you see which are working, which need you and
43
+ which are done, plus git worktrees, one-click PRs and cost readouts. One `npx`
44
+ command, no Electron, no config.
45
+
46
+ 📖 **User guide**: <https://receptron.github.io/mulmoterminal/> (日本語 / English)
47
+
25
48
  ## Dev loop
26
49
 
27
50
  ```bash
28
51
  yarn workspace @mulmoclaude/google-plugin run build
29
52
  yarn workspace @mulmoclaude/google-plugin run test
30
53
  ```
54
+
55
+ ## License
56
+
57
+ MIT
package/dist/args.d.ts CHANGED
@@ -22,6 +22,19 @@ export declare const GoogleArgs: z.ZodDiscriminatedUnion<[z.ZodObject<{
22
22
  description: z.ZodOptional<z.ZodString>;
23
23
  calendarId: z.ZodOptional<z.ZodString>;
24
24
  colorId: z.ZodOptional<z.ZodString>;
25
+ }, z.core.$strip>, z.ZodObject<{
26
+ kind: z.ZodLiteral<"calendarUpdateEvent">;
27
+ eventId: z.ZodString;
28
+ summary: z.ZodOptional<z.ZodString>;
29
+ start: z.ZodOptional<z.ZodString>;
30
+ end: z.ZodOptional<z.ZodString>;
31
+ description: z.ZodOptional<z.ZodString>;
32
+ calendarId: z.ZodOptional<z.ZodString>;
33
+ colorId: z.ZodOptional<z.ZodString>;
34
+ }, z.core.$strip>, z.ZodObject<{
35
+ kind: z.ZodLiteral<"calendarDeleteEvent">;
36
+ eventId: z.ZodString;
37
+ calendarId: z.ZodOptional<z.ZodString>;
25
38
  }, z.core.$strip>, z.ZodObject<{
26
39
  kind: z.ZodLiteral<"taskListsList">;
27
40
  }, z.core.$strip>, z.ZodObject<{
@@ -35,10 +48,21 @@ export declare const GoogleArgs: z.ZodDiscriminatedUnion<[z.ZodObject<{
35
48
  notes: z.ZodOptional<z.ZodString>;
36
49
  due: z.ZodOptional<z.ZodString>;
37
50
  taskListId: z.ZodOptional<z.ZodString>;
51
+ }, z.core.$strip>, z.ZodObject<{
52
+ kind: z.ZodLiteral<"tasksUpdate">;
53
+ taskId: z.ZodString;
54
+ title: z.ZodOptional<z.ZodString>;
55
+ notes: z.ZodOptional<z.ZodString>;
56
+ due: z.ZodOptional<z.ZodString>;
57
+ taskListId: z.ZodOptional<z.ZodString>;
38
58
  }, z.core.$strip>, z.ZodObject<{
39
59
  kind: z.ZodLiteral<"tasksComplete">;
40
60
  taskId: z.ZodString;
41
61
  taskListId: z.ZodOptional<z.ZodString>;
62
+ }, z.core.$strip>, z.ZodObject<{
63
+ kind: z.ZodLiteral<"tasksDelete">;
64
+ taskId: z.ZodString;
65
+ taskListId: z.ZodOptional<z.ZodString>;
42
66
  }, z.core.$strip>, z.ZodObject<{
43
67
  kind: z.ZodLiteral<"driveList">;
44
68
  maxResults: z.ZodOptional<z.ZodNumber>;
@@ -18,6 +18,10 @@ export declare const TOOL_DEFINITION: {
18
18
  type: string;
19
19
  description: string;
20
20
  };
21
+ eventId: {
22
+ type: string;
23
+ description: string;
24
+ };
21
25
  timeMin: {
22
26
  type: string;
23
27
  description: string;
package/dist/index.d.ts CHANGED
@@ -21,6 +21,10 @@ declare const _default: (runtime: import('gui-chat-protocol').PluginRuntime) =>
21
21
  type: string;
22
22
  description: string;
23
23
  };
24
+ eventId: {
25
+ type: string;
26
+ description: string;
27
+ };
24
28
  timeMin: {
25
29
  type: string;
26
30
  description: string;
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { DEFAULT_LIST_MAX_RESULTS, MAX_LIST_RESULTS, clearCalendarSyncToken, clientSecretPresence, completeTask, createCalendarEvent, createDriveFile, createTask, getCalendarColors, getGoogleAccessToken, isIsoDateTimeWithOffset, listCalendarEvents, listCalendars, listDriveFiles, listTaskLists, listTasks, loadCalendarSyncToken, loadGoogleTokens, readDriveFile, saveCalendarSyncToken, syncCalendarEvents } from "@mulmoclaude/core/google";
1
+ import { DEFAULT_LIST_MAX_RESULTS, MAX_LIST_RESULTS, clearCalendarSyncToken, clientSecretPresence, completeTask, createCalendarEvent, createDriveFile, createTask, deleteCalendarEvent, deleteTask, getCalendarColors, getGoogleAccessToken, isIsoDateTimeWithOffset, listCalendarEvents, listCalendars, listDriveFiles, listTaskLists, listTasks, loadCalendarSyncToken, loadGoogleTokens, readDriveFile, saveCalendarSyncToken, syncCalendarEvents, updateCalendarEvent, updateTask } from "@mulmoclaude/core/google";
2
2
  //#region ../../../node_modules/gui-chat-protocol/dist/index.js
3
3
  /**
4
4
  * Identity function for type inference. Same philosophy as
@@ -4165,6 +4165,18 @@ var IsoDateTimeWithOffset = string().refine(isIsoDateTimeWithOffset, { error: "m
4165
4165
  var MaxResults = number().int().min(1).max(MAX_LIST_RESULTS).optional();
4166
4166
  var NonEmpty = string().min(1);
4167
4167
  var OptionalNonEmpty = string().trim().min(1).optional();
4168
+ var EDITABLE_EVENT_FIELDS = [
4169
+ "summary",
4170
+ "start",
4171
+ "end",
4172
+ "description",
4173
+ "colorId"
4174
+ ];
4175
+ var EDITABLE_TASK_FIELDS = [
4176
+ "title",
4177
+ "notes",
4178
+ "due"
4179
+ ];
4168
4180
  var GoogleArgs = discriminatedUnion("kind", [
4169
4181
  object({ kind: literal("status") }),
4170
4182
  object({ kind: literal("calendarListCalendars") }),
@@ -4189,10 +4201,25 @@ var GoogleArgs = discriminatedUnion("kind", [
4189
4201
  calendarId: OptionalNonEmpty,
4190
4202
  colorId: OptionalNonEmpty
4191
4203
  }),
4204
+ object({
4205
+ kind: literal("calendarUpdateEvent"),
4206
+ eventId: NonEmpty,
4207
+ summary: NonEmpty.optional(),
4208
+ start: IsoDateTimeWithOffset.optional(),
4209
+ end: IsoDateTimeWithOffset.optional(),
4210
+ description: string().optional(),
4211
+ calendarId: OptionalNonEmpty,
4212
+ colorId: OptionalNonEmpty
4213
+ }).refine((args) => EDITABLE_EVENT_FIELDS.some((field) => args[field] !== void 0), { error: `pass at least one field to change (${EDITABLE_EVENT_FIELDS.join(", ")})` }),
4214
+ object({
4215
+ kind: literal("calendarDeleteEvent"),
4216
+ eventId: NonEmpty,
4217
+ calendarId: OptionalNonEmpty
4218
+ }),
4192
4219
  object({ kind: literal("taskListsList") }),
4193
4220
  object({
4194
4221
  kind: literal("tasksList"),
4195
- taskListId: string().optional(),
4222
+ taskListId: OptionalNonEmpty,
4196
4223
  maxResults: MaxResults,
4197
4224
  showCompleted: boolean().optional()
4198
4225
  }),
@@ -4201,12 +4228,25 @@ var GoogleArgs = discriminatedUnion("kind", [
4201
4228
  title: NonEmpty,
4202
4229
  notes: string().optional(),
4203
4230
  due: IsoDateTimeWithOffset.optional(),
4204
- taskListId: string().optional()
4231
+ taskListId: OptionalNonEmpty
4205
4232
  }),
4233
+ object({
4234
+ kind: literal("tasksUpdate"),
4235
+ taskId: NonEmpty,
4236
+ title: NonEmpty.optional(),
4237
+ notes: string().optional(),
4238
+ due: IsoDateTimeWithOffset.optional(),
4239
+ taskListId: OptionalNonEmpty
4240
+ }).refine((args) => EDITABLE_TASK_FIELDS.some((field) => args[field] !== void 0), { error: `pass at least one field to change (${EDITABLE_TASK_FIELDS.join(", ")})` }),
4206
4241
  object({
4207
4242
  kind: literal("tasksComplete"),
4208
4243
  taskId: NonEmpty,
4209
- taskListId: string().optional()
4244
+ taskListId: OptionalNonEmpty
4245
+ }),
4246
+ object({
4247
+ kind: literal("tasksDelete"),
4248
+ taskId: NonEmpty,
4249
+ taskListId: OptionalNonEmpty
4210
4250
  }),
4211
4251
  object({
4212
4252
  kind: literal("driveList"),
@@ -4228,8 +4268,8 @@ var GoogleArgs = discriminatedUnion("kind", [
4228
4268
  var TOOL_DEFINITION = {
4229
4269
  type: "function",
4230
4270
  name: "google",
4231
- prompt: "The user's Google account is linked LOCALLY on this machine — the refresh token lives in ~/.config/mulmo/ and never reaches any cloud. This is independent of claude.ai Google connectors; the tool works without them. If a call fails with 'Google account not linked', ask the user to link their Google account in this app's settings, then retry the original call.",
4232
- description: "Operate the user's Google services through the locally linked Google account: Calendar, Tasks, and Drive. Supported kinds:\n - `status`: report whether the Google account is linked on this machine — call this first when unsure.\n\nCalendar (events default to the primary calendar; pass `calendarId` — from `calendarListCalendars` — to target another):\n - `calendarListCalendars`: list the calendars the user has added/subscribed to (`id`, `summary`, `primary`, `backgroundColor`/`foregroundColor` hex, `colorId`, `accessRole`). Call this to work with a non-primary calendar.\n - `calendarColors`: palettes that map an event/calendar `colorId` to hex — `event` for per-event colours, `calendar` for calendar colours.\n - `calendarListEvents`: list upcoming events (each carries `colorId`, empty when it inherits the calendar colour). Optional `calendarId`, `timeMin` (ISO 8601 date-time with timezone offset; default now), `maxResults` (1-50, default 10).\n - `calendarSync`: fetch only what CHANGED since the last sync of this calendar, using a stored sync token. Use this for repeated/periodic syncing — it does not re-fetch the whole calendar, so it stays cheap. The FIRST call (or after `fullResync: true`) walks the entire calendar to establish the token. Returns counts (`changed`, `cancelled`) plus a capped `events` sample — never the full list, so it will not flood the conversation; `truncated: true` means more changed than are shown. Deletions are reported as the `cancelled` count. Optional `calendarId`, `fullResync` (discard the stored token and start over).\n - `calendarCreateEvent`: create an event. Requires `summary`, `start`, `end` — ISO 8601 date-times WITH a timezone offset (e.g. 2026-07-17T09:00:00+09:00); optional `description`, `calendarId`, `colorId` (event palette id \"1\"-\"11\").\n\nTasks:\n - `taskListsList`: list the user's task lists (`id`, `title`). Only needed when the user means a list other than their default one.\n - `tasksList`: list tasks. Optional `taskListId` (default: the user's default list), `maxResults` (1-50, default 10), `showCompleted` (default false).\n - `tasksCreate`: add a task. Requires `title`; optional `notes`, `due` (ISO 8601 with offset — Google keeps the DATE only, so do not promise a time of day), `taskListId`.\n - `tasksComplete`: mark a task done. Requires `taskId` (from `tasksList`); optional `taskListId`.\n\nDrive — IMPORTANT: this app can only see files IT created, never the user's wider Drive. Never claim you searched their whole Drive:\n - `driveList`: list files this app created. Optional `maxResults` (1-50, default 10).\n - `driveCreate`: create a text file. Requires `name` and `content`; optional `mimeType` (default text/plain).\n - `driveRead`: read one of this app's files. Requires `fileId` (from `driveList` or `driveCreate`). Text files only.",
4271
+ prompt: "The user's Google account is linked LOCALLY on this machine — the refresh token is stored in ~/.config/mulmo/ and goes only to Google to mint access tokens, never to claude.ai or any other service. This is independent of claude.ai Google connectors; the tool works without them. If a call fails with 'Google account not linked', ask the user to link their Google account in this app's settings, then retry the original call.",
4272
+ description: "Operate the user's Google services through the locally linked Google account: Calendar, Tasks, and Drive. Supported kinds:\n - `status`: report whether the Google account is linked on this machine — call this first when unsure.\n\nCalendar (events default to the primary calendar; pass `calendarId` — from `calendarListCalendars` — to target another):\n - `calendarListCalendars`: list the calendars the user has added/subscribed to (`id`, `summary`, `primary`, `backgroundColor`/`foregroundColor` hex, `colorId`, `accessRole`). Call this to work with a non-primary calendar.\n - `calendarColors`: palettes that map an event/calendar `colorId` to hex — `event` for per-event colours, `calendar` for calendar colours.\n - `calendarListEvents`: list upcoming events (each carries `colorId`, empty when it inherits the calendar colour). Optional `calendarId`, `timeMin` (ISO 8601 date-time with timezone offset; default now), `maxResults` (1-50, default 10).\n - `calendarSync`: fetch only what CHANGED since the last sync of this calendar, using a stored sync token. Use this for repeated/periodic syncing — it does not re-fetch the whole calendar, so it stays cheap. The FIRST call (or after `fullResync: true`) walks the entire calendar to establish the token. Returns counts (`changed`, `cancelled`) plus a capped `events` sample — never the full list, so it will not flood the conversation; `truncated: true` means more changed than are shown. Deletions are reported as the `cancelled` count. Optional `calendarId`, `fullResync` (discard the stored token and start over).\n - `calendarCreateEvent`: create an event. Requires `summary`, `start`, `end` — ISO 8601 date-times WITH a timezone offset (e.g. 2026-07-17T09:00:00+09:00); optional `description`, `calendarId`, `colorId` (event palette id \"1\"-\"11\").\n - `calendarUpdateEvent`: edit an existing event. Requires `eventId` (from `calendarListEvents` / `calendarSync`) plus AT LEAST ONE of `summary`, `start`, `end`, `description`, `colorId`; fields you omit keep their current value, and `description: \"\"` clears the body. Optional `calendarId`. Moving only one end of the event still has to leave start before end, or Calendar rejects it.\n - `calendarDeleteEvent`: delete an event. Requires `eventId`; optional `calendarId`. This removes it for every attendee and cannot be undone — confirm with the user before calling. For a recurring event, an instance id (as returned by the list kinds) deletes that single occurrence.\n\nTasks:\n - `taskListsList`: list the user's task lists (`id`, `title`). Only needed when the user means a list other than their default one.\n - `tasksList`: list tasks. Optional `taskListId` (default: the user's default list), `maxResults` (1-50, default 10), `showCompleted` (default false).\n - `tasksCreate`: add a task. Requires `title`; optional `notes`, `due` (ISO 8601 with offset — Google keeps the DATE only, so do not promise a time of day), `taskListId`.\n - `tasksUpdate`: edit a task. Requires `taskId` (from `tasksList`) plus AT LEAST ONE of `title`, `notes`, `due`; omitted fields keep their value and `notes: \"\"` clears them. Use `tasksComplete` to mark it done — this kind does not change status. Optional `taskListId`.\n - `tasksComplete`: mark a task done. Requires `taskId` (from `tasksList`); optional `taskListId`.\n - `tasksDelete`: delete a task. Requires `taskId`; optional `taskListId`. Cannot be undone — confirm with the user before calling.\n\nDrive — IMPORTANT: this app can only see files IT created, never the user's wider Drive. Never claim you searched their whole Drive:\n - `driveList`: list files this app created. Optional `maxResults` (1-50, default 10).\n - `driveCreate`: create a text file. Requires `name` and `content`; optional `mimeType` (default text/plain).\n - `driveRead`: read one of this app's files. Requires `fileId` (from `driveList` or `driveCreate`). Text files only.",
4233
4273
  parameters: {
4234
4274
  type: "object",
4235
4275
  properties: {
@@ -4242,10 +4282,14 @@ var TOOL_DEFINITION = {
4242
4282
  "calendarListEvents",
4243
4283
  "calendarSync",
4244
4284
  "calendarCreateEvent",
4285
+ "calendarUpdateEvent",
4286
+ "calendarDeleteEvent",
4245
4287
  "taskListsList",
4246
4288
  "tasksList",
4247
4289
  "tasksCreate",
4290
+ "tasksUpdate",
4248
4291
  "tasksComplete",
4292
+ "tasksDelete",
4249
4293
  "driveList",
4250
4294
  "driveCreate",
4251
4295
  "driveRead"
@@ -4257,7 +4301,11 @@ var TOOL_DEFINITION = {
4257
4301
  },
4258
4302
  colorId: {
4259
4303
  type: "string",
4260
- description: "calendarCreateEvent: optional event palette colour id \"1\"-\"11\""
4304
+ description: "calendarCreateEvent / calendarUpdateEvent: optional event palette colour id \"1\"-\"11\""
4305
+ },
4306
+ eventId: {
4307
+ type: "string",
4308
+ description: "calendarUpdateEvent / calendarDeleteEvent: id of the event, from calendarListEvents or calendarSync"
4261
4309
  },
4262
4310
  timeMin: {
4263
4311
  type: "string",
@@ -4273,19 +4321,19 @@ var TOOL_DEFINITION = {
4273
4321
  },
4274
4322
  summary: {
4275
4323
  type: "string",
4276
- description: "calendarCreateEvent: event title"
4324
+ description: "calendarCreateEvent / calendarUpdateEvent: event title"
4277
4325
  },
4278
4326
  start: {
4279
4327
  type: "string",
4280
- description: "calendarCreateEvent: start, ISO 8601 with timezone offset"
4328
+ description: "calendarCreateEvent / calendarUpdateEvent: start, ISO 8601 with timezone offset"
4281
4329
  },
4282
4330
  end: {
4283
4331
  type: "string",
4284
- description: "calendarCreateEvent: end, ISO 8601 with timezone offset"
4332
+ description: "calendarCreateEvent / calendarUpdateEvent: end, ISO 8601 with timezone offset"
4285
4333
  },
4286
4334
  description: {
4287
4335
  type: "string",
4288
- description: "calendarCreateEvent: optional event body"
4336
+ description: "calendarCreateEvent / calendarUpdateEvent: event body (\"\" on update clears it)"
4289
4337
  },
4290
4338
  taskListId: {
4291
4339
  type: "string",
@@ -4297,19 +4345,19 @@ var TOOL_DEFINITION = {
4297
4345
  },
4298
4346
  title: {
4299
4347
  type: "string",
4300
- description: "tasksCreate: task title"
4348
+ description: "tasksCreate / tasksUpdate: task title"
4301
4349
  },
4302
4350
  notes: {
4303
4351
  type: "string",
4304
- description: "tasksCreate: optional task notes"
4352
+ description: "tasksCreate / tasksUpdate: task notes (\"\" on update clears them)"
4305
4353
  },
4306
4354
  due: {
4307
4355
  type: "string",
4308
- description: "tasksCreate: optional due date, ISO 8601 with offset (Google keeps the date only)"
4356
+ description: "tasksCreate / tasksUpdate: due date, ISO 8601 with offset (Google keeps the date only)"
4309
4357
  },
4310
4358
  taskId: {
4311
4359
  type: "string",
4312
- description: "tasksComplete: id of the task to mark done"
4360
+ description: "tasksUpdate / tasksComplete / tasksDelete: id of the task, from tasksList"
4313
4361
  },
4314
4362
  name: {
4315
4363
  type: "string",
@@ -4411,6 +4459,32 @@ var src_default = definePlugin(({ log }) => {
4411
4459
  event
4412
4460
  };
4413
4461
  }
4462
+ case "calendarUpdateEvent": {
4463
+ const event = await updateCalendarEvent(await getGoogleAccessToken(), {
4464
+ eventId: args.eventId,
4465
+ summary: args.summary,
4466
+ startDateTime: args.start,
4467
+ endDateTime: args.end,
4468
+ description: args.description,
4469
+ calendarId: args.calendarId,
4470
+ colorId: args.colorId
4471
+ });
4472
+ log.info("calendar event updated", { id: event.id });
4473
+ return {
4474
+ ok: true,
4475
+ event
4476
+ };
4477
+ }
4478
+ case "calendarDeleteEvent":
4479
+ await deleteCalendarEvent(await getGoogleAccessToken(), {
4480
+ eventId: args.eventId,
4481
+ calendarId: args.calendarId
4482
+ });
4483
+ log.info("calendar event deleted", { id: args.eventId });
4484
+ return {
4485
+ ok: true,
4486
+ deleted: args.eventId
4487
+ };
4414
4488
  case "taskListsList": return {
4415
4489
  ok: true,
4416
4490
  taskLists: await listTaskLists(await getGoogleAccessToken())
@@ -4436,6 +4510,20 @@ var src_default = definePlugin(({ log }) => {
4436
4510
  task
4437
4511
  };
4438
4512
  }
4513
+ case "tasksUpdate": {
4514
+ const task = await updateTask(await getGoogleAccessToken(), {
4515
+ taskId: args.taskId,
4516
+ title: args.title,
4517
+ notes: args.notes,
4518
+ due: args.due,
4519
+ taskListId: args.taskListId
4520
+ });
4521
+ log.info("task updated", { id: task.id });
4522
+ return {
4523
+ ok: true,
4524
+ task
4525
+ };
4526
+ }
4439
4527
  case "tasksComplete": return {
4440
4528
  ok: true,
4441
4529
  task: await completeTask(await getGoogleAccessToken(), {
@@ -4443,6 +4531,16 @@ var src_default = definePlugin(({ log }) => {
4443
4531
  taskListId: args.taskListId
4444
4532
  })
4445
4533
  };
4534
+ case "tasksDelete":
4535
+ await deleteTask(await getGoogleAccessToken(), {
4536
+ taskId: args.taskId,
4537
+ taskListId: args.taskListId
4538
+ });
4539
+ log.info("task deleted", { id: args.taskId });
4540
+ return {
4541
+ ok: true,
4542
+ deleted: args.taskId
4543
+ };
4446
4544
  case "driveList": return {
4447
4545
  ok: true,
4448
4546
  files: await listDriveFiles(await getGoogleAccessToken(), { maxResults: args.maxResults ?? DEFAULT_LIST_MAX_RESULTS })