@mulmoclaude/google-plugin 1.2.0 → 1.2.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.
@@ -0,0 +1,14 @@
1
+ import { PluginRuntime } from 'gui-chat-protocol';
2
+ import { GoogleArgs } from '../args';
3
+ import type * as GoogleEngine from "@mulmoclaude/core/google";
4
+ /** The engine surface the router calls. Signatures are taken from
5
+ * `@mulmoclaude/core/google` itself, so a change there fails this file
6
+ * instead of drifting past a hand-written duplicate. */
7
+ export type GoogleApi = Pick<typeof GoogleEngine, "clearCalendarSyncToken" | "clientSecretPresence" | "completeTask" | "createCalendarEvent" | "createDriveFile" | "createTask" | "deleteCalendarEvent" | "deleteTask" | "getCalendarColors" | "getGoogleAccessToken" | "listCalendarEvents" | "listCalendars" | "listDriveFiles" | "listTaskLists" | "listTasks" | "loadCalendarSyncToken" | "loadGoogleTokens" | "readDriveFile" | "saveCalendarSyncToken" | "syncCalendarEvents" | "uncompleteTask" | "updateCalendarEvent" | "updateTask">;
8
+ export interface GoogleDispatchContext {
9
+ api: GoogleApi;
10
+ /** Narrowed to what the router actually writes, so a test stub stays small. */
11
+ log: Pick<PluginRuntime["log"], "info">;
12
+ }
13
+ export declare const SYNC_SAMPLE_LIMIT = 20;
14
+ export declare function executeGoogleDispatch(context: GoogleDispatchContext, args: GoogleArgs): Promise<unknown>;
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
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, uncompleteTask, updateCalendarEvent, updateTask } from "@mulmoclaude/core/google";
1
+ import * as googleApi from "@mulmoclaude/core/google";
2
+ import { DEFAULT_LIST_MAX_RESULTS, MAX_LIST_RESULTS, isIsoDateTimeWithOffset } from "@mulmoclaude/core/google";
2
3
  //#region ../../../node_modules/gui-chat-protocol/dist/index.js
3
4
  /**
4
5
  * Identity function for type inference. Same philosophy as
@@ -4269,6 +4270,230 @@ var GoogleArgs = discriminatedUnion("kind", [
4269
4270
  })
4270
4271
  ]);
4271
4272
  //#endregion
4273
+ //#region src/core/dispatch.ts
4274
+ var LINK_GUIDANCE = "Ask the user to link their Google account in this app's settings, then retry.";
4275
+ var summarizeSync = (result, incremental) => {
4276
+ const active = result.events.filter((event) => event.status !== "cancelled");
4277
+ const cancelled = result.events.length - active.length;
4278
+ return {
4279
+ ok: true,
4280
+ incremental,
4281
+ changed: active.length,
4282
+ cancelled,
4283
+ events: active.slice(0, 20),
4284
+ truncated: active.length > 20
4285
+ };
4286
+ };
4287
+ async function restartFullSync(api, accessToken, calendarId) {
4288
+ await api.clearCalendarSyncToken(calendarId);
4289
+ return await api.syncCalendarEvents(accessToken, { calendarId });
4290
+ }
4291
+ async function runCalendarSync(api, calendarId, fullResync) {
4292
+ const accessToken = await api.getGoogleAccessToken();
4293
+ if (fullResync) await api.clearCalendarSyncToken(calendarId);
4294
+ const storedToken = fullResync ? null : await api.loadCalendarSyncToken(calendarId);
4295
+ const first = await api.syncCalendarEvents(accessToken, {
4296
+ calendarId,
4297
+ syncToken: storedToken ?? void 0
4298
+ });
4299
+ const result = first.fullResyncRequired ? await restartFullSync(api, accessToken, calendarId) : first;
4300
+ if (result.nextSyncToken) await api.saveCalendarSyncToken(calendarId, result.nextSyncToken);
4301
+ return {
4302
+ ...summarizeSync(result, Boolean(storedToken) && !first.fullResyncRequired),
4303
+ expiredToken: first.fullResyncRequired
4304
+ };
4305
+ }
4306
+ var status = async ({ api }) => {
4307
+ const [tokens, clientSecret] = await Promise.all([api.loadGoogleTokens(), api.clientSecretPresence()]);
4308
+ const linked = Boolean(tokens?.refresh_token);
4309
+ return {
4310
+ ok: true,
4311
+ linked,
4312
+ clientSecret,
4313
+ ...linked ? {} : { guidance: LINK_GUIDANCE }
4314
+ };
4315
+ };
4316
+ var calendarListCalendars = async ({ api }) => ({
4317
+ ok: true,
4318
+ calendars: await api.listCalendars(await api.getGoogleAccessToken())
4319
+ });
4320
+ var calendarColors = async ({ api }) => ({
4321
+ ok: true,
4322
+ colors: await api.getCalendarColors(await api.getGoogleAccessToken())
4323
+ });
4324
+ var calendarListEvents = async ({ api }, args) => {
4325
+ return {
4326
+ ok: true,
4327
+ events: await api.listCalendarEvents(await api.getGoogleAccessToken(), {
4328
+ calendarId: args.calendarId,
4329
+ timeMin: args.timeMin,
4330
+ maxResults: args.maxResults ?? DEFAULT_LIST_MAX_RESULTS
4331
+ })
4332
+ };
4333
+ };
4334
+ var calendarSync = async ({ api }, args) => await runCalendarSync(api, args.calendarId, args.fullResync ?? false);
4335
+ var calendarCreateEvent = async ({ api, log }, args) => {
4336
+ const event = await api.createCalendarEvent(await api.getGoogleAccessToken(), {
4337
+ summary: args.summary,
4338
+ startDateTime: args.start,
4339
+ endDateTime: args.end,
4340
+ description: args.description,
4341
+ calendarId: args.calendarId,
4342
+ colorId: args.colorId
4343
+ });
4344
+ log.info("calendar event created", { id: event.id });
4345
+ return {
4346
+ ok: true,
4347
+ event
4348
+ };
4349
+ };
4350
+ var calendarUpdateEvent = async ({ api, log }, args) => {
4351
+ const event = await api.updateCalendarEvent(await api.getGoogleAccessToken(), {
4352
+ eventId: args.eventId,
4353
+ summary: args.summary,
4354
+ startDateTime: args.start,
4355
+ endDateTime: args.end,
4356
+ description: args.description,
4357
+ calendarId: args.calendarId,
4358
+ colorId: args.colorId
4359
+ });
4360
+ log.info("calendar event updated", { id: event.id });
4361
+ return {
4362
+ ok: true,
4363
+ event
4364
+ };
4365
+ };
4366
+ var calendarDeleteEvent = async ({ api, log }, args) => {
4367
+ await api.deleteCalendarEvent(await api.getGoogleAccessToken(), {
4368
+ eventId: args.eventId,
4369
+ calendarId: args.calendarId
4370
+ });
4371
+ log.info("calendar event deleted", { id: args.eventId });
4372
+ return {
4373
+ ok: true,
4374
+ deleted: args.eventId
4375
+ };
4376
+ };
4377
+ var taskListsList = async ({ api }) => ({
4378
+ ok: true,
4379
+ taskLists: await api.listTaskLists(await api.getGoogleAccessToken())
4380
+ });
4381
+ var tasksList = async ({ api }, args) => {
4382
+ return {
4383
+ ok: true,
4384
+ tasks: await api.listTasks(await api.getGoogleAccessToken(), {
4385
+ taskListId: args.taskListId,
4386
+ maxResults: args.maxResults ?? DEFAULT_LIST_MAX_RESULTS,
4387
+ showCompleted: args.showCompleted
4388
+ })
4389
+ };
4390
+ };
4391
+ var tasksCreate = async ({ api, log }, args) => {
4392
+ const task = await api.createTask(await api.getGoogleAccessToken(), {
4393
+ title: args.title,
4394
+ notes: args.notes,
4395
+ due: args.due,
4396
+ taskListId: args.taskListId
4397
+ });
4398
+ log.info("task created", { id: task.id });
4399
+ return {
4400
+ ok: true,
4401
+ task
4402
+ };
4403
+ };
4404
+ var tasksUpdate = async ({ api, log }, args) => {
4405
+ const task = await api.updateTask(await api.getGoogleAccessToken(), {
4406
+ taskId: args.taskId,
4407
+ title: args.title,
4408
+ notes: args.notes,
4409
+ due: args.due,
4410
+ taskListId: args.taskListId
4411
+ });
4412
+ log.info("task updated", { id: task.id });
4413
+ return {
4414
+ ok: true,
4415
+ task
4416
+ };
4417
+ };
4418
+ var tasksComplete = async ({ api }, args) => {
4419
+ return {
4420
+ ok: true,
4421
+ task: await api.completeTask(await api.getGoogleAccessToken(), {
4422
+ taskId: args.taskId,
4423
+ taskListId: args.taskListId
4424
+ })
4425
+ };
4426
+ };
4427
+ var tasksUncomplete = async ({ api }, args) => {
4428
+ return {
4429
+ ok: true,
4430
+ task: await api.uncompleteTask(await api.getGoogleAccessToken(), {
4431
+ taskId: args.taskId,
4432
+ taskListId: args.taskListId
4433
+ })
4434
+ };
4435
+ };
4436
+ var tasksDelete = async ({ api, log }, args) => {
4437
+ await api.deleteTask(await api.getGoogleAccessToken(), {
4438
+ taskId: args.taskId,
4439
+ taskListId: args.taskListId
4440
+ });
4441
+ log.info("task deleted", { id: args.taskId });
4442
+ return {
4443
+ ok: true,
4444
+ deleted: args.taskId
4445
+ };
4446
+ };
4447
+ var driveList = async ({ api }, args) => {
4448
+ return {
4449
+ ok: true,
4450
+ files: await api.listDriveFiles(await api.getGoogleAccessToken(), { maxResults: args.maxResults ?? DEFAULT_LIST_MAX_RESULTS })
4451
+ };
4452
+ };
4453
+ var driveCreate = async ({ api, log }, args) => {
4454
+ const file = await api.createDriveFile(await api.getGoogleAccessToken(), {
4455
+ name: args.name,
4456
+ content: args.content,
4457
+ mimeType: args.mimeType
4458
+ });
4459
+ log.info("drive file created", { id: file.id });
4460
+ return {
4461
+ ok: true,
4462
+ file
4463
+ };
4464
+ };
4465
+ var driveRead = async ({ api }, args) => {
4466
+ const { file, content } = await api.readDriveFile(await api.getGoogleAccessToken(), { fileId: args.fileId });
4467
+ return {
4468
+ ok: true,
4469
+ file,
4470
+ content
4471
+ };
4472
+ };
4473
+ async function executeGoogleDispatch(context, args) {
4474
+ switch (args.kind) {
4475
+ case "status": return await status(context);
4476
+ case "calendarListCalendars": return await calendarListCalendars(context);
4477
+ case "calendarColors": return await calendarColors(context);
4478
+ case "calendarListEvents": return await calendarListEvents(context, args);
4479
+ case "calendarSync": return await calendarSync(context, args);
4480
+ case "calendarCreateEvent": return await calendarCreateEvent(context, args);
4481
+ case "calendarUpdateEvent": return await calendarUpdateEvent(context, args);
4482
+ case "calendarDeleteEvent": return await calendarDeleteEvent(context, args);
4483
+ case "taskListsList": return await taskListsList(context);
4484
+ case "tasksList": return await tasksList(context, args);
4485
+ case "tasksCreate": return await tasksCreate(context, args);
4486
+ case "tasksUpdate": return await tasksUpdate(context, args);
4487
+ case "tasksComplete": return await tasksComplete(context, args);
4488
+ case "tasksUncomplete": return await tasksUncomplete(context, args);
4489
+ case "tasksDelete": return await tasksDelete(context, args);
4490
+ case "driveList": return await driveList(context, args);
4491
+ case "driveCreate": return await driveCreate(context, args);
4492
+ case "driveRead": return await driveRead(context, args);
4493
+ default: throw new Error(`unknown kind: ${JSON.stringify(args)}`);
4494
+ }
4495
+ }
4496
+ //#endregion
4272
4497
  //#region src/definition.ts
4273
4498
  var TOOL_DEFINITION = {
4274
4499
  type: "function",
@@ -4387,207 +4612,15 @@ var TOOL_DEFINITION = {
4387
4612
  };
4388
4613
  //#endregion
4389
4614
  //#region src/index.ts
4390
- var LINK_GUIDANCE = "Ask the user to link their Google account in this app's settings, then retry.";
4391
- var SYNC_SAMPLE_LIMIT = 20;
4392
- var summarizeSync = (result, incremental) => {
4393
- const active = result.events.filter((event) => event.status !== "cancelled");
4394
- const cancelled = result.events.length - active.length;
4395
- return {
4396
- ok: true,
4397
- incremental,
4398
- changed: active.length,
4399
- cancelled,
4400
- events: active.slice(0, SYNC_SAMPLE_LIMIT),
4401
- truncated: active.length > SYNC_SAMPLE_LIMIT
4402
- };
4403
- };
4404
- async function restartFullSync(accessToken, calendarId) {
4405
- await clearCalendarSyncToken(calendarId);
4406
- return await syncCalendarEvents(accessToken, { calendarId });
4407
- }
4408
- async function runCalendarSync(calendarId, fullResync) {
4409
- const accessToken = await getGoogleAccessToken();
4410
- if (fullResync) await clearCalendarSyncToken(calendarId);
4411
- const storedToken = fullResync ? null : await loadCalendarSyncToken(calendarId);
4412
- const first = await syncCalendarEvents(accessToken, {
4413
- calendarId,
4414
- syncToken: storedToken ?? void 0
4415
- });
4416
- const result = first.fullResyncRequired ? await restartFullSync(accessToken, calendarId) : first;
4417
- if (result.nextSyncToken) await saveCalendarSyncToken(calendarId, result.nextSyncToken);
4418
- return {
4419
- ...summarizeSync(result, Boolean(storedToken) && !first.fullResyncRequired),
4420
- expiredToken: first.fullResyncRequired
4421
- };
4422
- }
4423
- var src_default = definePlugin(({ log }) => {
4424
- const dispatch = async (args) => {
4425
- switch (args.kind) {
4426
- case "status": {
4427
- const [tokens, clientSecret] = await Promise.all([loadGoogleTokens(), clientSecretPresence()]);
4428
- const linked = Boolean(tokens?.refresh_token);
4429
- return {
4430
- ok: true,
4431
- linked,
4432
- clientSecret,
4433
- ...linked ? {} : { guidance: LINK_GUIDANCE }
4434
- };
4435
- }
4436
- case "calendarListCalendars": return {
4437
- ok: true,
4438
- calendars: await listCalendars(await getGoogleAccessToken())
4439
- };
4440
- case "calendarColors": return {
4441
- ok: true,
4442
- colors: await getCalendarColors(await getGoogleAccessToken())
4443
- };
4444
- case "calendarListEvents": return {
4445
- ok: true,
4446
- events: await listCalendarEvents(await getGoogleAccessToken(), {
4447
- calendarId: args.calendarId,
4448
- timeMin: args.timeMin,
4449
- maxResults: args.maxResults ?? DEFAULT_LIST_MAX_RESULTS
4450
- })
4451
- };
4452
- case "calendarSync": return await runCalendarSync(args.calendarId, args.fullResync ?? false);
4453
- case "calendarCreateEvent": {
4454
- const event = await createCalendarEvent(await getGoogleAccessToken(), {
4455
- summary: args.summary,
4456
- startDateTime: args.start,
4457
- endDateTime: args.end,
4458
- description: args.description,
4459
- calendarId: args.calendarId,
4460
- colorId: args.colorId
4461
- });
4462
- log.info("calendar event created", { id: event.id });
4463
- return {
4464
- ok: true,
4465
- event
4466
- };
4467
- }
4468
- case "calendarUpdateEvent": {
4469
- const event = await updateCalendarEvent(await getGoogleAccessToken(), {
4470
- eventId: args.eventId,
4471
- summary: args.summary,
4472
- startDateTime: args.start,
4473
- endDateTime: args.end,
4474
- description: args.description,
4475
- calendarId: args.calendarId,
4476
- colorId: args.colorId
4477
- });
4478
- log.info("calendar event updated", { id: event.id });
4479
- return {
4480
- ok: true,
4481
- event
4482
- };
4483
- }
4484
- case "calendarDeleteEvent":
4485
- await deleteCalendarEvent(await getGoogleAccessToken(), {
4486
- eventId: args.eventId,
4487
- calendarId: args.calendarId
4488
- });
4489
- log.info("calendar event deleted", { id: args.eventId });
4490
- return {
4491
- ok: true,
4492
- deleted: args.eventId
4493
- };
4494
- case "taskListsList": return {
4495
- ok: true,
4496
- taskLists: await listTaskLists(await getGoogleAccessToken())
4497
- };
4498
- case "tasksList": return {
4499
- ok: true,
4500
- tasks: await listTasks(await getGoogleAccessToken(), {
4501
- taskListId: args.taskListId,
4502
- maxResults: args.maxResults ?? DEFAULT_LIST_MAX_RESULTS,
4503
- showCompleted: args.showCompleted
4504
- })
4505
- };
4506
- case "tasksCreate": {
4507
- const task = await createTask(await getGoogleAccessToken(), {
4508
- title: args.title,
4509
- notes: args.notes,
4510
- due: args.due,
4511
- taskListId: args.taskListId
4512
- });
4513
- log.info("task created", { id: task.id });
4514
- return {
4515
- ok: true,
4516
- task
4517
- };
4518
- }
4519
- case "tasksUpdate": {
4520
- const task = await updateTask(await getGoogleAccessToken(), {
4521
- taskId: args.taskId,
4522
- title: args.title,
4523
- notes: args.notes,
4524
- due: args.due,
4525
- taskListId: args.taskListId
4526
- });
4527
- log.info("task updated", { id: task.id });
4528
- return {
4529
- ok: true,
4530
- task
4531
- };
4532
- }
4533
- case "tasksComplete": return {
4534
- ok: true,
4535
- task: await completeTask(await getGoogleAccessToken(), {
4536
- taskId: args.taskId,
4537
- taskListId: args.taskListId
4538
- })
4539
- };
4540
- case "tasksUncomplete": return {
4541
- ok: true,
4542
- task: await uncompleteTask(await getGoogleAccessToken(), {
4543
- taskId: args.taskId,
4544
- taskListId: args.taskListId
4545
- })
4546
- };
4547
- case "tasksDelete":
4548
- await deleteTask(await getGoogleAccessToken(), {
4549
- taskId: args.taskId,
4550
- taskListId: args.taskListId
4551
- });
4552
- log.info("task deleted", { id: args.taskId });
4553
- return {
4554
- ok: true,
4555
- deleted: args.taskId
4556
- };
4557
- case "driveList": return {
4558
- ok: true,
4559
- files: await listDriveFiles(await getGoogleAccessToken(), { maxResults: args.maxResults ?? DEFAULT_LIST_MAX_RESULTS })
4560
- };
4561
- case "driveCreate": {
4562
- const file = await createDriveFile(await getGoogleAccessToken(), {
4563
- name: args.name,
4564
- content: args.content,
4565
- mimeType: args.mimeType
4566
- });
4567
- log.info("drive file created", { id: file.id });
4568
- return {
4569
- ok: true,
4570
- file
4571
- };
4572
- }
4573
- case "driveRead": {
4574
- const { file, content } = await readDriveFile(await getGoogleAccessToken(), { fileId: args.fileId });
4575
- return {
4576
- ok: true,
4577
- file,
4578
- content
4579
- };
4580
- }
4581
- default: throw new Error(`unknown kind: ${JSON.stringify(args)}`);
4582
- }
4583
- };
4584
- return {
4585
- TOOL_DEFINITION,
4586
- async google(rawArgs) {
4587
- return await dispatch(GoogleArgs.parse(rawArgs));
4588
- }
4589
- };
4590
- });
4615
+ var src_default = definePlugin(({ log }) => ({
4616
+ TOOL_DEFINITION,
4617
+ async google(rawArgs) {
4618
+ return await executeGoogleDispatch({
4619
+ api: googleApi,
4620
+ log
4621
+ }, GoogleArgs.parse(rawArgs));
4622
+ }
4623
+ }));
4591
4624
  //#endregion
4592
4625
  export { TOOL_DEFINITION, src_default as default };
4593
4626