@plotday/twister 0.26.0 → 0.27.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.
Files changed (92) hide show
  1. package/README.md +1 -1
  2. package/bin/commands/deploy.js +15 -7
  3. package/bin/commands/deploy.js.map +1 -1
  4. package/bin/templates/AGENTS.template.md +53 -29
  5. package/bin/utils/sse.js +19 -1
  6. package/bin/utils/sse.js.map +1 -1
  7. package/cli/templates/AGENTS.template.md +53 -29
  8. package/dist/common/calendar.d.ts +24 -9
  9. package/dist/common/calendar.d.ts.map +1 -1
  10. package/dist/common/messaging.d.ts +12 -6
  11. package/dist/common/messaging.d.ts.map +1 -1
  12. package/dist/common/projects.d.ts +12 -14
  13. package/dist/common/projects.d.ts.map +1 -1
  14. package/dist/docs/assets/hierarchy.js +1 -1
  15. package/dist/docs/assets/navigation.js +1 -1
  16. package/dist/docs/assets/search.js +1 -1
  17. package/dist/docs/classes/tools_ai.AI.html +1 -1
  18. package/dist/docs/classes/tools_callbacks.Callbacks.html +1 -1
  19. package/dist/docs/classes/tools_integrations.Integrations.html +1 -1
  20. package/dist/docs/classes/tools_network.Network.html +1 -1
  21. package/dist/docs/classes/tools_plot.Plot.html +1 -1
  22. package/dist/docs/classes/tools_store.Store.html +1 -1
  23. package/dist/docs/classes/tools_tasks.Tasks.html +1 -1
  24. package/dist/docs/classes/tools_twists.Twists.html +1 -1
  25. package/dist/docs/documents/Built-in_Tools.html +6 -6
  26. package/dist/docs/documents/Core_Concepts.html +3 -3
  27. package/dist/docs/documents/Getting_Started.html +1 -1
  28. package/dist/docs/documents/Runtime_Environment.html +1 -1
  29. package/dist/docs/enums/plot.ActivityLinkType.html +5 -5
  30. package/dist/docs/enums/plot.ActivityType.html +4 -4
  31. package/dist/docs/enums/plot.ActorType.html +4 -4
  32. package/dist/docs/enums/plot.ConferencingProvider.html +6 -6
  33. package/dist/docs/functions/index.Uuid.Generate.html +1 -0
  34. package/dist/docs/hierarchy.html +1 -1
  35. package/dist/docs/interfaces/common_calendar.CalendarTool.html +15 -13
  36. package/dist/docs/modules/index.Uuid.html +1 -0
  37. package/dist/docs/modules/index.html +1 -1
  38. package/dist/docs/modules/plot.html +1 -1
  39. package/dist/docs/types/index.Uuid.html +1 -0
  40. package/dist/docs/types/plot.Activity.html +2 -9
  41. package/dist/docs/types/plot.ActivityCommon.html +16 -16
  42. package/dist/docs/types/plot.ActivityLink.html +1 -1
  43. package/dist/docs/types/plot.ActivityMeta.html +5 -25
  44. package/dist/docs/types/plot.ActivityUpdate.html +3 -4
  45. package/dist/docs/types/plot.ActivityWithNotes.html +1 -1
  46. package/dist/docs/types/plot.Actor.html +5 -5
  47. package/dist/docs/types/plot.ActorId.html +1 -1
  48. package/dist/docs/types/plot.ContentType.html +1 -1
  49. package/dist/docs/types/plot.NewActivity.html +9 -5
  50. package/dist/docs/types/plot.NewActivityWithNotes.html +1 -1
  51. package/dist/docs/types/plot.NewActor.html +3 -0
  52. package/dist/docs/types/plot.NewContact.html +4 -4
  53. package/dist/docs/types/plot.NewNote.html +8 -3
  54. package/dist/docs/types/plot.NewPriority.html +1 -1
  55. package/dist/docs/types/plot.NewTags.html +2 -0
  56. package/dist/docs/types/plot.Note.html +2 -2
  57. package/dist/docs/types/plot.NoteUpdate.html +5 -5
  58. package/dist/docs/types/plot.PickPriorityConfig.html +2 -2
  59. package/dist/docs/types/plot.Priority.html +3 -3
  60. package/dist/docs/types/plot.SyncUpdate.html +15 -0
  61. package/dist/docs/types/plot.Tags.html +2 -1
  62. package/dist/llm-docs/common/calendar.d.ts +1 -1
  63. package/dist/llm-docs/common/calendar.d.ts.map +1 -1
  64. package/dist/llm-docs/common/calendar.js +1 -1
  65. package/dist/llm-docs/common/calendar.js.map +1 -1
  66. package/dist/llm-docs/common/messaging.d.ts +1 -1
  67. package/dist/llm-docs/common/messaging.d.ts.map +1 -1
  68. package/dist/llm-docs/common/messaging.js +1 -1
  69. package/dist/llm-docs/common/messaging.js.map +1 -1
  70. package/dist/llm-docs/common/projects.d.ts +1 -1
  71. package/dist/llm-docs/common/projects.d.ts.map +1 -1
  72. package/dist/llm-docs/common/projects.js +1 -1
  73. package/dist/llm-docs/common/projects.js.map +1 -1
  74. package/dist/llm-docs/plot.d.ts +1 -1
  75. package/dist/llm-docs/plot.d.ts.map +1 -1
  76. package/dist/llm-docs/plot.js +1 -1
  77. package/dist/llm-docs/plot.js.map +1 -1
  78. package/dist/llm-docs/twist-guide-template.d.ts +1 -1
  79. package/dist/llm-docs/twist-guide-template.d.ts.map +1 -1
  80. package/dist/llm-docs/twist-guide-template.js +1 -1
  81. package/dist/llm-docs/twist-guide-template.js.map +1 -1
  82. package/dist/plot.d.ts +127 -111
  83. package/dist/plot.d.ts.map +1 -1
  84. package/dist/plot.js +1 -0
  85. package/dist/plot.js.map +1 -1
  86. package/dist/twist-guide.d.ts +1 -1
  87. package/dist/twist-guide.d.ts.map +1 -1
  88. package/dist/utils/uuid.d.ts +7 -0
  89. package/dist/utils/uuid.d.ts.map +1 -0
  90. package/dist/utils/uuid.js +9 -0
  91. package/dist/utils/uuid.js.map +1 -0
  92. package/package.json +9 -2
package/dist/plot.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import { type Tag } from "./tag";
2
2
  import { type Callback } from "./tools/callbacks";
3
+ import { Uuid } from "./utils/uuid";
3
4
  export { Tag } from "./tag";
5
+ export { Uuid } from "./utils/uuid";
4
6
  /**
5
7
  * Represents a unique user, contact, or twist in Plot.
6
8
  *
@@ -161,110 +163,68 @@ export type ActivityLink = {
161
163
  /**
162
164
  * Represents metadata about an activity, typically from an external system.
163
165
  *
164
- * Activity metadata enables tracking where activities originated from,
165
- * which is useful for synchronization, deduplication, and linking
166
- * back to external systems.
167
- *
168
- * ## Source-Based Upsert
169
- *
170
- * When creating an activity with a `source` field, Plot automatically implements
171
- * **upsert behavior**. If an activity with the same source already exists (created
172
- * by the same twist definition), it will be **updated** instead of creating a duplicate.
173
- * This enables safe, idempotent sync operations.
174
- *
175
- * ### How Source Uniqueness Works
176
- *
177
- * - **Scoped to twist definition**: Sources are unique per twist, not per twist instance.
178
- * Different instances of the same twist (installed in different priorities) share
179
- * the same source namespace.
180
- * - **Independent twists**: Different twists can have activities with the same source value.
181
- * - **Archived activities**: Archived activities don't conflict with active ones - you can
182
- * create a new activity with the same source after archiving.
183
- * - **Optional**: Activities without sources are always created fresh - no deduplication.
184
- *
185
- * ### Upsert Behavior Details
186
- *
187
- * When an activity is upserted (updated instead of created):
188
- * - **All provided fields** are updated with new values
189
- * - **Tags** are merged (existing tags + new tags)
190
- * - **Notes** are appended (existing notes kept, new ones added)
191
- * - **Priority** is NOT changed (stays in original priority)
166
+ * Activity metadata enables storing additional information about activities,
167
+ * which is useful for synchronization, linking back to external systems,
168
+ * and storing tool-specific data.
192
169
  *
193
170
  * @example
194
171
  * ```typescript
195
- * // First call creates the activity
172
+ * // Calendar event metadata
196
173
  * await plot.createActivity({
197
174
  * type: ActivityType.Event,
198
175
  * title: "Team Meeting",
199
176
  * start: new Date("2024-01-15T10:00:00Z"),
200
- * source: "google-calendar:event-abc123",
201
177
  * meta: {
202
178
  * calendarId: "primary",
203
- * htmlLink: "https://calendar.google.com/event/abc123"
179
+ * htmlLink: "https://calendar.google.com/event/abc123",
180
+ * conferenceData: { ... }
204
181
  * }
205
182
  * });
206
183
  *
207
- * // Second call with same source updates the existing activity
184
+ * // Project issue metadata
208
185
  * await plot.createActivity({
209
- * type: ActivityType.Event,
210
- * title: "Team Meeting (Updated)", // Title will be updated
211
- * start: new Date("2024-01-15T14:00:00Z"), // Time will be updated
212
- * source: "google-calendar:event-abc123" // Same source = upsert
186
+ * type: ActivityType.Action,
187
+ * title: "Fix login bug",
188
+ * meta: {
189
+ * projectId: "TEAM",
190
+ * issueNumber: 123,
191
+ * url: "https://linear.app/team/issue/TEAM-123"
192
+ * }
213
193
  * });
214
- *
215
- * // Different twist, same source = creates new activity (independent)
216
- * // Different source = creates new activity
217
- * // No source = creates new activity (no deduplication)
218
194
  * ```
219
195
  */
220
196
  export type ActivityMeta = {
221
197
  /** Source-specific properties and metadata */
222
198
  [key: string]: any;
223
199
  };
200
+ /**
201
+ * Tags on an item, along with the actors who added each tag.
202
+ */
224
203
  export type Tags = {
225
204
  [K in Tag]?: ActorId[];
226
205
  };
227
206
  /**
228
- * Represents a complete activity within the Plot system.
229
- *
230
- * Activities are the core entities in Plot, representing anything from simple notes
231
- * to complex recurring events. They support rich metadata including scheduling,
232
- * recurrence patterns, links, and external source tracking.
233
- *
234
- * @example
235
- * ```typescript
236
- * // Simple note
237
- * const task: Activity = {
238
- * type: ActivityType.Note,
239
- * title: "New campaign brainstorming ideas",
240
- * content: "We could rent a bouncy castle...",
241
- * author: { id: "user-1", name: "John Doe", type: ActorType.User },
242
- * priority: { id: "work", title: "Work" },
243
- * // ... other fields
244
- * };
245
- *
246
- * // Simple action
247
- * const action: Activity = {
248
- * type: ActivityType.Action,
249
- * title: "Review budget proposal",
250
- * author: { id: "user-1", name: "John Doe", type: ActorType.User },
251
- * priority: { id: "work", title: "Work" },
252
- * // ... other fields
253
- * };
254
- *
255
- * // Recurring event
256
- * const meeting: Activity = {
257
- * type: ActivityType.Event,
258
- * title: "Weekly standup",
259
- * recurrenceRule: "FREQ=WEEKLY;BYDAY=MO",
260
- * recurrenceCount: 12,
261
- * // ... other fields
262
- * };
263
- * ```
207
+ * A set of tags to add to an item, along with the actors adding each tag.
208
+ */
209
+ export type NewTags = {
210
+ [K in Tag]?: NewActor[];
211
+ };
212
+ /**
213
+ * Common fields shared by both Activity and Note entities.
264
214
  */
265
215
  export type ActivityCommon = {
266
216
  /** Unique identifier for the activity */
267
- id: string;
217
+ id: Uuid;
218
+ /**
219
+ * When this activity was originally created in its source system.
220
+ *
221
+ * For activities created in Plot, this is when the user created it.
222
+ * For activities synced from external systems (GitHub issues, emails, calendar events),
223
+ * this is the original creation time in that system.
224
+ *
225
+ * Defaults to the current time when creating new activities.
226
+ */
227
+ createdAt: Date;
268
228
  /** Information about who created the activity */
269
229
  author: Actor;
270
230
  /** Whether this activity is in draft state (not shown in do now view) */
@@ -274,13 +234,13 @@ export type ActivityCommon = {
274
234
  /** Whether this activity has been archived */
275
235
  archived: boolean;
276
236
  /** Tags attached to this activity. Maps tag ID to array of actor IDs who added that tag. */
277
- tags: Tags | null;
237
+ tags: Tags;
278
238
  /** Array of actor IDs (users, contacts, or twists) mentioned in this activity via @-mentions */
279
- mentions: ActorId[] | null;
239
+ mentions: ActorId[];
280
240
  };
281
241
  export type Activity = ActivityCommon & {
282
242
  /** The display title/summary of the activity */
283
- title: string | null;
243
+ title: string;
284
244
  /** The type of activity (Note, Task, or Event) */
285
245
  type: ActivityType;
286
246
  /**
@@ -393,18 +353,6 @@ export type Activity = ActivityCommon & {
393
353
  * Used to identify which occurrence of a recurring event this exception replaces.
394
354
  */
395
355
  occurrence: Date | null;
396
- /**
397
- * Unique identifier for this activity in the source system.
398
- *
399
- * Used for deduplication - activities with the same source are upserted instead
400
- * of creating duplicates. Format is typically "source-name:external-id"
401
- * (e.g., "google-calendar:event-123", "outlook:message-456").
402
- *
403
- * When provided, enables idempotent sync operations - calling createActivity()
404
- * multiple times with the same source will update the existing activity rather
405
- * than creating duplicates.
406
- */
407
- source: string | null;
408
356
  /** Metadata about the activity, typically from an external system that created it */
409
357
  meta: ActivityMeta | null;
410
358
  };
@@ -452,8 +400,9 @@ export type PickPriorityConfig = {
452
400
  * Type for creating new activities.
453
401
  *
454
402
  * Requires only the activity type, with all other fields optional.
455
- * The ID and author will be automatically assigned by the Plot system
456
- * based on the current execution context.
403
+ * The author will be automatically assigned by the Plot system based on
404
+ * the current execution context. The ID can be optionally provided by
405
+ * tools for tracking and update detection purposes.
457
406
  *
458
407
  * **Important: Scheduling Defaults for Actions**
459
408
  *
@@ -510,13 +459,25 @@ export type PickPriorityConfig = {
510
459
  * };
511
460
  * ```
512
461
  */
513
- export type NewActivity = Pick<Activity, "type"> & Partial<Omit<Activity, "id" | "author" | "type" | "priority" | "mentions">> & ({
462
+ export type NewActivity = Pick<Activity, "type"> & Partial<Omit<Activity, "author" | "assignee" | "type" | "priority" | "tags" | "mentions">> & ({
514
463
  /** Explicit priority (required when specified) - disables automatic priority matching */
515
464
  priority: Pick<Priority, "id">;
516
465
  } | {
517
466
  /** Configuration for automatic priority selection based on similarity */
518
467
  pickPriority?: PickPriorityConfig;
519
468
  } | {}) & {
469
+ /**
470
+ * The person that created the item. By default, it will be the twist itself.
471
+ */
472
+ author?: NewActor;
473
+ /**
474
+ * The person that assigned to the item.
475
+ */
476
+ assignee?: NewActor | null;
477
+ /**
478
+ * All tags to set on the new activity.
479
+ */
480
+ tags?: NewTags;
520
481
  /**
521
482
  * Whether the activity should be marked as unread for users.
522
483
  * - true (default): Activity is unread for all users in the priority
@@ -526,15 +487,12 @@ export type NewActivity = Pick<Activity, "type"> & Partial<Omit<Activity, "id" |
526
487
  */
527
488
  unread?: boolean;
528
489
  };
529
- export type ActivityUpdate = Pick<Activity, "id"> & Partial<Pick<Activity, "type" | "start" | "end" | "doneAt" | "title" | "assignee" | "draft" | "private" | "source" | "meta" | "recurrenceRule" | "recurrenceDates" | "recurrenceExdates" | "recurrenceUntil" | "recurrenceCount" | "occurrence">> & {
490
+ export type ActivityUpdate = Pick<Activity, "id"> & Partial<Pick<Activity, "type" | "start" | "end" | "doneAt" | "title" | "assignee" | "draft" | "private" | "meta" | "recurrenceRule" | "recurrenceDates" | "recurrenceExdates" | "recurrenceUntil" | "recurrenceCount" | "occurrence">> & {
530
491
  /**
531
- * Full tags object from Activity. Maps tag ID to array of actor IDs who added that tag.
532
- * Only allowed for activities created by the twist.
533
- * Use twistTags instead for adding/removing the twist's tags on other activities.
492
+ * Tags to change on the activity. Use an empty array of NewActor to remove a tag.
493
+ * Use twistTags to add/remove the twist from tags to avoid clearing other actors' tags.
534
494
  */
535
- tags?: {
536
- [K in Tag]?: ActorId[];
537
- };
495
+ tags?: NewTags;
538
496
  /**
539
497
  * Add or remove the twist's tags.
540
498
  * Maps tag ID to boolean: true = add tag, false = remove tag.
@@ -542,13 +500,49 @@ export type ActivityUpdate = Pick<Activity, "id"> & Partial<Pick<Activity, "type
542
500
  */
543
501
  twistTags?: Partial<Record<Tag, boolean>>;
544
502
  };
503
+ /**
504
+ * Represents a sync update from a tool.
505
+ *
506
+ * Tools that sync from external sources can send either:
507
+ * - A new activity with notes (for newly discovered items)
508
+ * - An update to an existing activity with optional new notes (for changed items)
509
+ *
510
+ * This allows tools to manage their own update detection logic locally,
511
+ * providing Plot with the appropriate operation to perform.
512
+ *
513
+ * @example
514
+ * ```typescript
515
+ * // Send a new activity
516
+ * const newItem: SyncUpdate = {
517
+ * type: ActivityType.Event,
518
+ * title: "New Meeting",
519
+ * id: Uuid.Generate(), // Tool-generated ID
520
+ * notes: [{ id: Uuid.Generate(), content: "Description" }]
521
+ * };
522
+ *
523
+ * // Send an update to existing activity
524
+ * const update: SyncUpdate = {
525
+ * activityId: existingActivityId,
526
+ * update: { title: "Updated Meeting Title" },
527
+ * notes: [{ id: Uuid.Generate(), content: "New comment" }]
528
+ * };
529
+ * ```
530
+ */
531
+ export type SyncUpdate = NewActivityWithNotes | {
532
+ /** ID of the activity to update */
533
+ activityId: string;
534
+ /** Optional updates to the activity itself */
535
+ update?: ActivityUpdate;
536
+ /** Optional new notes to add to the activity */
537
+ notes?: NewNote[];
538
+ };
545
539
  /**
546
540
  * Represents a note within an activity.
547
541
  *
548
542
  * Notes contain the detailed content (note text, links) associated with an activity.
549
543
  * They are always ordered by creation time within their parent activity.
550
544
  */
551
- export type Note = Omit<ActivityCommon, "type"> & {
545
+ export type Note = ActivityCommon & {
552
546
  /** The parent activity this note belongs to */
553
547
  activity: Activity;
554
548
  /** Primary content for the note (markdown) */
@@ -560,10 +554,15 @@ export type Note = Omit<ActivityCommon, "type"> & {
560
554
  * Type for creating new notes.
561
555
  *
562
556
  * Requires the activity reference, with all other fields optional.
557
+ * The id field can be optionally provided by tools for tracking purposes.
563
558
  */
564
- export type NewNote = Partial<Omit<Note, "id" | "author" | "activity">> & {
559
+ export type NewNote = Partial<Omit<Note, "author" | "activity" | "tags" | "mentions">> & {
565
560
  /** Reference to the parent activity (required) */
566
561
  activity: Pick<Activity, "id">;
562
+ /**
563
+ * The person that created the item, or leave undefined to use the twist as author.
564
+ */
565
+ author?: NewActor;
567
566
  /**
568
567
  * Format of the note content. Determines how the note is processed:
569
568
  * - 'text': Plain text that will be converted to markdown (auto-links URLs, preserves line breaks)
@@ -571,6 +570,15 @@ export type NewNote = Partial<Omit<Note, "id" | "author" | "activity">> & {
571
570
  * - 'html': HTML content that will be converted to markdown
572
571
  */
573
572
  contentType?: ContentType;
573
+ /**
574
+ * Tags to change on the activity. Use an empty array of NewActor to remove a tag.
575
+ * Use twistTags to add/remove the twist from tags to avoid clearing other actors' tags.
576
+ */
577
+ tags?: NewTags;
578
+ /**
579
+ * Change the mentions on the note.
580
+ */
581
+ mentions?: NewActor[];
574
582
  /**
575
583
  * Whether the note should mark the parent activity as unread for users.
576
584
  * - true (default): Activity becomes unread for users who haven't authored the note
@@ -583,7 +591,7 @@ export type NewNote = Partial<Omit<Note, "id" | "author" | "activity">> & {
583
591
  /**
584
592
  * Type for updating existing notes.
585
593
  */
586
- export type NoteUpdate = Pick<Note, "id"> & Partial<Pick<Note, "draft" | "private" | "content" | "links" | "mentions">> & {
594
+ export type NoteUpdate = Pick<Note, "id"> & Partial<Pick<Note, "draft" | "private" | "content" | "links">> & {
587
595
  /**
588
596
  * Format of the note content. Determines how the note is processed:
589
597
  * - 'text': Plain text that will be converted to markdown (auto-links URLs, preserves line breaks)
@@ -592,19 +600,20 @@ export type NoteUpdate = Pick<Note, "id"> & Partial<Pick<Note, "draft" | "privat
592
600
  */
593
601
  contentType?: ContentType;
594
602
  /**
595
- * Full tags object from Note. Maps tag ID to array of actor IDs who added that tag.
596
- * Only allowed for notes created by the twist.
597
- * Use twistTags instead for adding/removing the twist's tags on other notes.
603
+ * Tags to change on the note. Use an empty array of NewActor to remove a tag.
604
+ * Use twistTags to add/remove the twist from tags to avoid clearing other actors' tags.
598
605
  */
599
- tags?: {
600
- [K in Tag]?: ActorId[];
601
- };
606
+ tags?: NewTags;
602
607
  /**
603
608
  * Add or remove the twist's tags.
604
609
  * Maps tag ID to boolean: true = add tag, false = remove tag.
605
610
  * This is allowed on all notes the twist has access to.
606
611
  */
607
612
  twistTags?: Partial<Record<Tag, boolean>>;
613
+ /**
614
+ * Change the mentions on the note.
615
+ */
616
+ mentions?: NewActor[];
608
617
  };
609
618
  /**
610
619
  * Represents an actor in Plot - a user, contact, or twist.
@@ -632,6 +641,13 @@ export type Actor = {
632
641
  /** Display name (undefined if not included due to permissions, null if not set) */
633
642
  name?: string | null;
634
643
  };
644
+ /**
645
+ * An existing or new contact.
646
+ */
647
+ export type NewActor = {
648
+ /** Unique identifier for the actor */
649
+ id: ActorId;
650
+ } | NewContact;
635
651
  /**
636
652
  * Enumeration of author types that can create activities.
637
653
  *
@@ -1 +1 @@
1
- {"version":3,"file":"plot.d.ts","sourceRoot":"","sources":["../src/plot.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"plot.d.ts","sourceRoot":"","sources":["../src/plot.ts"],"names":[],"mappings":"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"}
package/dist/plot.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export { Tag } from "./tag";
2
+ export { Uuid } from "./utils/uuid";
2
3
  /**
3
4
  * Enumeration of supported activity types in Plot.
4
5
  *
package/dist/plot.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"plot.js","sourceRoot":"","sources":["../src/plot.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAqC5B;;;;;GAKG;AACH,MAAM,CAAN,IAAY,YAOX;AAPD,WAAY,YAAY;IACtB,qEAAqE;IACrE,+CAAI,CAAA;IACJ,+CAA+C;IAC/C,mDAAM,CAAA;IACN,8DAA8D;IAC9D,iDAAK,CAAA;AACP,CAAC,EAPW,YAAY,KAAZ,YAAY,QAOvB;AAED;;;;;GAKG;AACH,MAAM,CAAN,IAAY,gBASX;AATD,WAAY,gBAAgB;IAC1B,8CAA8C;IAC9C,yCAAqB,CAAA;IACrB,mDAAmD;IACnD,iCAAa,CAAA;IACb,6DAA6D;IAC7D,yCAAqB,CAAA;IACrB,+DAA+D;IAC/D,iDAA6B,CAAA;AAC/B,CAAC,EATW,gBAAgB,KAAhB,gBAAgB,QAS3B;AAED;;;;;GAKG;AACH,MAAM,CAAN,IAAY,oBAWX;AAXD,WAAY,oBAAoB;IAC9B,kBAAkB;IAClB,iDAAyB,CAAA;IACzB,WAAW;IACX,qCAAa,CAAA;IACb,sBAAsB;IACtB,yDAAiC,CAAA;IACjC,kBAAkB;IAClB,uCAAe,CAAA;IACf,6CAA6C;IAC7C,uCAAe,CAAA;AACjB,CAAC,EAXW,oBAAoB,KAApB,oBAAoB,QAW/B;AAslBD;;;;;GAKG;AACH,MAAM,CAAN,IAAY,SAOX;AAPD,WAAY,SAAS;IACnB,wCAAwC;IACxC,yCAAI,CAAA;IACJ,8CAA8C;IAC9C,+CAAO,CAAA;IACP,6CAA6C;IAC7C,2CAAK,CAAA;AACP,CAAC,EAPW,SAAS,KAAT,SAAS,QAOpB"}
1
+ {"version":3,"file":"plot.js","sourceRoot":"","sources":["../src/plot.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAqCpC;;;;;GAKG;AACH,MAAM,CAAN,IAAY,YAOX;AAPD,WAAY,YAAY;IACtB,qEAAqE;IACrE,+CAAI,CAAA;IACJ,+CAA+C;IAC/C,mDAAM,CAAA;IACN,8DAA8D;IAC9D,iDAAK,CAAA;AACP,CAAC,EAPW,YAAY,KAAZ,YAAY,QAOvB;AAED;;;;;GAKG;AACH,MAAM,CAAN,IAAY,gBASX;AATD,WAAY,gBAAgB;IAC1B,8CAA8C;IAC9C,yCAAqB,CAAA;IACrB,mDAAmD;IACnD,iCAAa,CAAA;IACb,6DAA6D;IAC7D,yCAAqB,CAAA;IACrB,+DAA+D;IAC/D,iDAA6B,CAAA;AAC/B,CAAC,EATW,gBAAgB,KAAhB,gBAAgB,QAS3B;AAED;;;;;GAKG;AACH,MAAM,CAAN,IAAY,oBAWX;AAXD,WAAY,oBAAoB;IAC9B,kBAAkB;IAClB,iDAAyB,CAAA;IACzB,WAAW;IACX,qCAAa,CAAA;IACb,sBAAsB;IACtB,yDAAiC,CAAA;IACjC,kBAAkB;IAClB,uCAAe,CAAA;IACf,6CAA6C;IAC7C,uCAAe,CAAA;AACjB,CAAC,EAXW,oBAAoB,KAApB,oBAAoB,QAW/B;AAwnBD;;;;;GAKG;AACH,MAAM,CAAN,IAAY,SAOX;AAPD,WAAY,SAAS;IACnB,wCAAwC;IACxC,yCAAI,CAAA;IACJ,8CAA8C;IAC9C,+CAAO,CAAA;IACP,6CAA6C;IAC7C,2CAAK,CAAA;AACP,CAAC,EAPW,SAAS,KAAT,SAAS,QAOpB"}
@@ -1,2 +1,2 @@
1
- export declare const TWIST_GUIDE = "# Twist Implementation Guide for LLMs\n\nThis document provides context for AI assistants generating or modifying twists.\n\n## Architecture Overview\n\nPlot Twists are TypeScript classes that extend the `Twist` base class. Twists interact with external services and Plot's core functionality through a tool-based architecture.\n\n### Runtime Environment\n\n**Critical**: All Twists and tool functions are executed in a sandboxed, ephemeral environment with limited resources:\n\n- **Memory is temporary**: Anything stored in memory (e.g. as a variable in the twist/tool object) is lost after the function completes. Use the Store tool instead. Only use memory for temporary caching.\n- **Limited CPU time**: Each execution has limited CPU time (typically 10 seconds) and memory (128MB)\n- **Use the Run tool**: Queue separate chunks of work with `run.now(functionName, context)`\n- **Break long operations**: Split large operations into smaller batches that can be processed independently\n- **Store intermediate state**: Use the Store tool to persist state between batches\n- **Examples**: Syncing large datasets, processing many API calls, or performing batch operations\n\n## Understanding Activities and Notes\n\n**CRITICAL CONCEPT**: An **Activity** represents something done or to be done (a task, event, or conversation), while **Notes** represent the updates and details on that activity.\n\n**Think of an Activity as a thread** on a messaging platform, and **Notes as the messages in that thread**.\n\n### Key Guidelines\n\n1. **Always create Activities with an initial Note** - The title is just a summary; detailed content goes in Notes\n2. **Add Notes to existing Activities for updates** - Don't create a new Activity for each related message\n3. **Use `source` field for deduplication** - Enables safe, idempotent sync from external systems\n4. **Most Activities should be `ActivityType.Note`** - Use `Action` only for tasks with `doneAt`, use `Event` only for items with `start`/`end`\n\n### Decision Tree\n\n```\nNew event/task/conversation?\n \u251C\u2500 Yes \u2192 Create new Activity with initial Note\n \u2502 Include `source` field for deduplication\n \u2502\n \u2514\u2500 No (update/reply/comment) \u2192 Check for existing Activity\n \u251C\u2500 Found \u2192 Add Note to existing Activity\n \u2514\u2500 Not found \u2192 Create new Activity with initial Note\n```\n\n## Twist Structure Pattern\n\n```typescript\nimport {\n type Activity,\n type Priority,\n type ToolBuilder,\n twist,\n} from \"@plotday/twister\";\nimport { Plot } from \"@plotday/twister/tools/plot\";\n\nexport default class MyTwist extends Twist<MyTwist> {\n build(build: ToolBuilder) {\n return {\n plot: build(Plot),\n };\n }\n\n async activate(priority: Pick<Priority, \"id\">) {\n // Called when twist is enabled for a priority\n // Common actions: request auth, create setup activities\n }\n\n async activity(activity: Activity) {\n // Called when an activity is routed to this twist\n // Common actions: process external events, update activities\n }\n}\n```\n\n## Tool System\n\n### Accessing Tools\n\nAll tools are declared in the `build` method:\n\n```typescript\nbuild(build: ToolBuilder) {\n return {\n toolName: build(ToolClass),\n };\n}\n```\n\nAll `build()` calls must occur in the `build` method as they are used for dependency analysis.\n\nIMPORTANT: HTTP access is restricted to URLs requested via `build(Network, { urls: [url1, url2, ...] })` in the `build` method. Wildcards are supported. Use `build(Network, { urls: ['*'] })` if full access is needed.\n\n### Built-in Tools (Always Available)\n\nFor complete API documentation of built-in tools including all methods, types, and detailed examples, see the TypeScript definitions in your installed package at `node_modules/@plotday/twister/src/tools/*.ts`. Each tool file contains comprehensive JSDoc documentation.\n\n**Quick reference - Available tools:**\n\n- `@plotday/twister/tools/plot` - Core data layer (create/update activities, priorities, contacts)\n- `@plotday/twister/tools/ai` - LLM integration (text generation, structured output, reasoning)\n - Use ModelPreferences to specify `speed` (fast/balanced/capable) and `cost` (low/medium/high)\n- `@plotday/twister/tools/store` - Persistent key-value storage (also via `this.set()`, `this.get()`)\n- `@plotday/twister/tools/tasks` - Queue batched work (also via `this.run()`)\n- `@plotday/twister/tools/callbacks` - Persistent function references (also via `this.callback()`)\n- `@plotday/twister/tools/integrations` - OAuth2 authentication flows\n- `@plotday/twister/tools/network` - HTTP access permissions and webhook management\n- `@plotday/twister/tools/twists` - Manage other Twists\n\n**Critical**: Never use instance variables for state. They are lost after function execution. Always use Store methods.\n\n### External Tools (Add to package.json)\n\nAdd tool dependencies to `package.json`:\n\n```json\n{\n \"dependencies\": {\n \"@plotday/twister\": \"workspace:^\",\n \"@plotday/tool-google-calendar\": \"workspace:^\"\n }\n}\n```\n\n#### Common External Tools\n\n- `@plotday/tool-google-calendar`: Google Calendar integration\n- `@plotday/tool-outlook-calendar`: Outlook Calendar integration\n- `@plotday/tool-google-contacts`: Google Contacts integration\n\n## Lifecycle Methods\n\n### activate(priority: Pick<Priority, \"id\">)\n\nCalled when the twist is enabled for a priority. Common patterns:\n\n**Request Authentication:**\n\n```typescript\nasync activate(_priority: Pick<Priority, \"id\">) {\n const authLink = await this.tools.externalTool.requestAuth(\n this.onAuthComplete,\n \"google\"\n );\n\n await this.tools.plot.createActivity({\n type: ActivityType.Note,\n title: \"Connect your account\",\n notes: [\n {\n content: \"Click the link below to connect your account and start syncing.\",\n links: [authLink],\n },\n ],\n });\n}\n```\n\n**Store Parent Activity for Later:**\n\n```typescript\nconst activity = await this.tools.plot.createActivity({\n type: ActivityType.Note,\n title: \"Setup\",\n notes: [\n {\n content: \"Your twist is being set up. Configuration steps will appear here.\",\n },\n ],\n});\n\nawait this.set(\"setup_activity_id\", activity.id);\n```\n\n### activity(activity: Activity)\n\nCalled when an activity is routed to the twist. Common patterns:\n\n**Create Activities from External Events:**\n\n```typescript\nasync activity(activity: Activity) {\n await this.tools.plot.createActivity(activity);\n}\n```\n\n**Update Based on User Action:**\n\n```typescript\nasync activity(activity: Activity) {\n if (activity.completed) {\n await this.handleCompletion(activity);\n }\n}\n```\n\n## Activity Links\n\nActivity links enable user interaction:\n\n```typescript\nimport { type ActivityLink, ActivityLinkType } from \"@plotday/twister\";\n\n// URL link\nconst urlLink: ActivityLink = {\n title: \"Open website\",\n type: ActivityLinkType.url,\n url: \"https://example.com\",\n};\n\n// Callback link (uses Callbacks tool)\nconst token = await this.callback(this.onLinkClicked, \"context\");\nconst callbackLink: ActivityLink = {\n title: \"Click me\",\n type: ActivityLinkType.callback,\n token: token,\n};\n\n// Add to activity note\nawait this.tools.plot.createActivity({\n type: ActivityType.Note,\n title: \"Task with links\",\n notes: [\n {\n content: \"Click the links below to take action.\",\n links: [urlLink, callbackLink],\n },\n ],\n});\n```\n\n## Authentication Pattern\n\nCommon pattern for OAuth authentication:\n\n```typescript\nasync activate(_priority: Pick<Priority, \"id\">) {\n // Request auth link from tool with callback\n const authLink = await this.tools.googleTool.requestAuth(\n this.onAuthComplete,\n \"google\"\n );\n\n // Create activity with auth link\n const activity = await this.tools.plot.createActivity({\n type: ActivityType.Note,\n title: \"Connect Google account\",\n notes: [\n {\n content: \"Click below to connect your Google account and start syncing.\",\n links: [authLink],\n },\n ],\n });\n\n // Store for later use\n await this.set(\"auth_activity_id\", activity.id);\n}\n\nasync onAuthComplete(authResult: { authToken: string }, provider: string) {\n // Store auth token\n await this.set(`${provider}_auth`, authResult.authToken);\n\n // Continue setup flow\n await this.setupSyncOptions(authResult.authToken);\n}\n```\n\n## Sync Pattern\n\nPattern for syncing external data - demonstrates adding Notes to existing Activities:\n\n```typescript\nasync startSync(calendarId: string): Promise<void> {\n const authToken = await this.get<string>(\"auth_token\");\n\n await this.tools.calendarTool.startSync(\n authToken,\n calendarId,\n this.handleEvent,\n calendarId\n );\n}\n\nasync handleEvent(\n incomingActivity: NewActivityWithNotes,\n calendarId: string\n): Promise<void> {\n // Check if this activity already exists (using source for deduplication)\n if (incomingActivity.source) {\n const existing = await this.tools.plot.getActivityBySource(\n incomingActivity.source\n );\n\n if (existing) {\n // Add update as a Note to existing Activity (add message to thread)\n if (incomingActivity.notes?.[0]?.content) {\n await this.tools.plot.createNote({\n activity: { id: existing.id },\n content: incomingActivity.notes[0].content,\n });\n }\n return;\n }\n }\n\n // Create new Activity with initial Note (new thread with first message)\n await this.tools.plot.createActivity(incomingActivity);\n}\n\nasync stopSync(calendarId: string): Promise<void> {\n const authToken = await this.get<string>(\"auth_token\");\n await this.tools.calendarTool.stopSync(authToken, calendarId);\n}\n```\n\n## Calendar Selection Pattern\n\nPattern for letting users select from multiple calendars/accounts:\n\n```typescript\nprivate async createCalendarSelectionActivity(\n provider: string,\n calendars: Calendar[],\n authToken: string\n): Promise<void> {\n const links: ActivityLink[] = [];\n\n for (const calendar of calendars) {\n const token = await this.callback(\n this.onCalendarSelected,\n provider,\n calendar.id,\n calendar.name,\n authToken\n );\n\n links.push({\n title: `\uD83D\uDCC5 ${calendar.name}${calendar.primary ? \" (Primary)\" : \"\"}`,\n type: ActivityLinkType.callback,\n token: token,\n });\n }\n\n await this.tools.plot.createActivity({\n type: ActivityType.Note,\n title: \"Which calendars would you like to connect?\",\n notes: [\n {\n content: \"Select the calendars you want to sync:\",\n links,\n },\n ],\n });\n}\n\nasync onCalendarSelected(\n link: ActivityLink,\n provider: string,\n calendarId: string,\n calendarName: string,\n authToken: string\n): Promise<void> {\n // Start sync for selected calendar\n await this.tools.tool.startSync(\n authToken,\n calendarId,\n this.handleEvent,\n provider,\n calendarId\n );\n}\n```\n\n## Batch Processing Pattern\n\n**Important**: Because Twists run in an ephemeral environment with limited execution time, you must break long operations into batches. Each batch runs independently in a new execution context.\n\n### Key Principles\n\n1. **Store state between batches**: Use the Store tool to persist progress\n2. **Queue next batch**: Use the Run tool to schedule the next chunk\n3. **Clean up when done**: Delete stored state after completion\n4. **Handle failures**: Store enough state to resume if a batch fails\n\n### Example Implementation\n\n```typescript\nasync startSync(resourceId: string): Promise<void> {\n // Initialize state in Store (persists between executions)\n await this.set(`sync_state_${resourceId}`, {\n nextPageToken: null,\n batchNumber: 1,\n itemsProcessed: 0,\n });\n\n // Queue first batch using runTask method\n const callback = await this.callback(this.syncBatch, resourceId);\n await this.runTask(callback);\n}\n\nasync syncBatch(args: any, resourceId: string): Promise<void> {\n // Load state from Store (set by previous execution)\n const state = await this.get(`sync_state_${resourceId}`);\n\n // Process one batch (keep under time limit)\n const result = await this.fetchBatch(state.nextPageToken);\n\n // Process results (create activities with Notes)\n for (const item of result.items) {\n await this.tools.plot.createActivity({\n type: ActivityType.Note,\n title: item.title,\n source: `external:${item.id}`, // For deduplication\n notes: [{ content: item.description }],\n });\n }\n\n if (result.nextPageToken) {\n // Update state in Store for next batch\n await this.set(`sync_state_${resourceId}`, {\n nextPageToken: result.nextPageToken,\n batchNumber: state.batchNumber + 1,\n itemsProcessed: state.itemsProcessed + result.items.length,\n });\n\n // Queue next batch (runs in new execution context)\n const nextCallback = await this.callback(this.syncBatch, resourceId);\n await this.runTask(nextCallback);\n } else {\n // Cleanup when complete\n await this.clear(`sync_state_${resourceId}`);\n\n // Optionally notify user of completion\n await this.tools.plot.createActivity({\n type: ActivityType.Note,\n title: \"Sync complete\",\n notes: [\n {\n content: `Successfully processed ${state.itemsProcessed + result.items.length} items.`,\n },\n ],\n });\n }\n}\n```\n\n## Error Handling\n\nAlways handle errors gracefully and communicate them to users:\n\n```typescript\ntry {\n await this.externalOperation();\n} catch (error) {\n console.error(\"Operation failed:\", error);\n\n await this.tools.plot.createActivity({\n type: ActivityType.Note,\n title: \"Operation failed\",\n notes: [\n {\n content: `Failed to complete operation: ${error.message}`,\n },\n ],\n });\n}\n```\n\n## Common Pitfalls\n\n- **Don't use instance variables for state** - Anything stored in memory is lost after function execution. Always use the Store tool for data that needs to persist.\n- **Processing self-created activities** - Other users may change an Activity created by the twist, resulting in an \\`activity\\` call. Be sure to check the \\`changes === null\\` and/or \\`activity.author.id !== this.id\\` to avoid re-processing.\n- **Always create Activities with Notes** - See \"Understanding Activities and Notes\" section above for the thread/message pattern and decision tree.\n- **Use correct Activity types** - Most should be `ActivityType.Note`. Only use `Action` for tasks with `doneAt`, and `Event` for items with `start`/`end`.\n- **Use `source` field for deduplication** - Always include `source` when syncing external data to enable safe, idempotent operations.\n- **Add Notes to existing Activities** - Check for existing Activities with `getActivityBySource()` before creating new ones. Think thread replies, not new threads.\n- Tools are declared in the `build` method and accessed via `this.tools.toolName` in twist methods.\n- **Don't forget runtime limits** - Each execution has ~10 seconds. Break long operations into batches with the Tasks tool. Process enough items per batch to be efficient, but few enough to stay under time limits.\n- **Always use Callbacks tool for persistent references** - Direct function references don't survive worker restarts.\n- **Store auth tokens** - Don't re-request authentication unnecessarily.\n- **Clean up callbacks and stored state** - Delete callbacks and Store entries when no longer needed.\n- **Handle missing auth gracefully** - Check for stored auth before operations.\n\n## Testing\n\nBefore deploying, verify:\n\n1. Linting passes: `{{packageManager}} lint`\n2. All dependencies are in package.json\n3. Authentication flow works end-to-end\n4. Batch operations handle pagination correctly\n5. Error cases are handled gracefully\n";
1
+ export declare const TWIST_GUIDE = "# Twist Implementation Guide for LLMs\n\nThis document provides context for AI assistants generating or modifying twists.\n\n## Architecture Overview\n\nPlot Twists are TypeScript classes that extend the `Twist` base class. Twists interact with external services and Plot's core functionality through a tool-based architecture.\n\n### Runtime Environment\n\n**Critical**: All Twists and tool functions are executed in a sandboxed, ephemeral environment with limited resources:\n\n- **Memory is temporary**: Anything stored in memory (e.g. as a variable in the twist/tool object) is lost after the function completes. Use the Store tool instead. Only use memory for temporary caching.\n- **Limited CPU time**: Each execution has limited CPU time (typically 10 seconds) and memory (128MB)\n- **Use the Run tool**: Queue separate chunks of work with `run.now(functionName, context)`\n- **Break long operations**: Split large operations into smaller batches that can be processed independently\n- **Store intermediate state**: Use the Store tool to persist state between batches\n- **Examples**: Syncing large datasets, processing many API calls, or performing batch operations\n\n## Understanding Activities and Notes\n\n**CRITICAL CONCEPT**: An **Activity** represents something done or to be done (a task, event, or conversation), while **Notes** represent the updates and details on that activity.\n\n**Think of an Activity as a thread** on a messaging platform, and **Notes as the messages in that thread**.\n\n### Key Guidelines\n\n1. **Always create Activities with an initial Note** - The title is just a summary; detailed content goes in Notes\n2. **Add Notes to existing Activities for updates** - Don't create a new Activity for each related message\n3. **Track external items using generated UUIDs** - Store mappings between external IDs and Plot UUIDs for deduplication\n4. **Most Activities should be `ActivityType.Note`** - Use `Action` only for tasks with `doneAt`, use `Event` only for items with `start`/`end`\n\n### Decision Tree\n\n```\nNew event/task/conversation?\n \u251C\u2500 Yes \u2192 Generate UUID with Uuid.Generate()\n \u2502 Create new Activity with that UUID\n \u2502 Store mapping: external_id \u2192 activity_uuid\n \u2502\n \u2514\u2500 No (update/reply/comment) \u2192 Look up mapping by external_id\n \u251C\u2500 Found \u2192 Add Note to existing Activity using stored UUID\n \u2514\u2500 Not found \u2192 Create new Activity with UUID + store mapping\n```\n\n## Twist Structure Pattern\n\n```typescript\nimport {\n type Activity,\n type Priority,\n type ToolBuilder,\n twist,\n} from \"@plotday/twister\";\nimport { Plot } from \"@plotday/twister/tools/plot\";\nimport { Uuid } from \"@plotday/twister/utils/uuid\";\n\nexport default class MyTwist extends Twist<MyTwist> {\n build(build: ToolBuilder) {\n return {\n plot: build(Plot),\n };\n }\n\n async activate(priority: Pick<Priority, \"id\">) {\n // Called when twist is enabled for a priority\n // Common actions: request auth, create setup activities\n }\n\n async activity(activity: Activity) {\n // Called when an activity is routed to this twist\n // Common actions: process external events, update activities\n }\n}\n```\n\n## Tool System\n\n### Accessing Tools\n\nAll tools are declared in the `build` method:\n\n```typescript\nbuild(build: ToolBuilder) {\n return {\n toolName: build(ToolClass),\n };\n}\n```\n\nAll `build()` calls must occur in the `build` method as they are used for dependency analysis.\n\nIMPORTANT: HTTP access is restricted to URLs requested via `build(Network, { urls: [url1, url2, ...] })` in the `build` method. Wildcards are supported. Use `build(Network, { urls: ['*'] })` if full access is needed.\n\n### Built-in Tools (Always Available)\n\nFor complete API documentation of built-in tools including all methods, types, and detailed examples, see the TypeScript definitions in your installed package at `node_modules/@plotday/twister/src/tools/*.ts`. Each tool file contains comprehensive JSDoc documentation.\n\n**Quick reference - Available tools:**\n\n- `@plotday/twister/tools/plot` - Core data layer (create/update activities, priorities, contacts)\n- `@plotday/twister/tools/ai` - LLM integration (text generation, structured output, reasoning)\n - Use ModelPreferences to specify `speed` (fast/balanced/capable) and `cost` (low/medium/high)\n- `@plotday/twister/tools/store` - Persistent key-value storage (also via `this.set()`, `this.get()`)\n- `@plotday/twister/tools/tasks` - Queue batched work (also via `this.run()`)\n- `@plotday/twister/tools/callbacks` - Persistent function references (also via `this.callback()`)\n- `@plotday/twister/tools/integrations` - OAuth2 authentication flows\n- `@plotday/twister/tools/network` - HTTP access permissions and webhook management\n- `@plotday/twister/tools/twists` - Manage other Twists\n\n**Critical**: Never use instance variables for state. They are lost after function execution. Always use Store methods.\n\n### External Tools (Add to package.json)\n\nAdd tool dependencies to `package.json`:\n\n```json\n{\n \"dependencies\": {\n \"@plotday/twister\": \"workspace:^\",\n \"@plotday/tool-google-calendar\": \"workspace:^\"\n }\n}\n```\n\n#### Common External Tools\n\n- `@plotday/tool-google-calendar`: Google Calendar integration\n- `@plotday/tool-outlook-calendar`: Outlook Calendar integration\n- `@plotday/tool-google-contacts`: Google Contacts integration\n\n## Lifecycle Methods\n\n### activate(priority: Pick<Priority, \"id\">)\n\nCalled when the twist is enabled for a priority. Common patterns:\n\n**Request Authentication:**\n\n```typescript\nasync activate(_priority: Pick<Priority, \"id\">) {\n const authLink = await this.tools.externalTool.requestAuth(\n this.onAuthComplete,\n \"google\"\n );\n\n await this.tools.plot.createActivity({\n type: ActivityType.Note,\n title: \"Connect your account\",\n notes: [\n {\n content: \"Click the link below to connect your account and start syncing.\",\n links: [authLink],\n },\n ],\n });\n}\n```\n\n**Store Parent Activity for Later:**\n\n```typescript\nconst activity = await this.tools.plot.createActivity({\n type: ActivityType.Note,\n title: \"Setup\",\n notes: [\n {\n content: \"Your twist is being set up. Configuration steps will appear here.\",\n },\n ],\n});\n\nawait this.set(\"setup_activity_id\", activity.id);\n```\n\n### activity(activity: Activity)\n\nCalled when an activity is routed to the twist. Common patterns:\n\n**Create Activities from External Events:**\n\n```typescript\nasync activity(activity: Activity) {\n await this.tools.plot.createActivity(activity);\n}\n```\n\n**Update Based on User Action:**\n\n```typescript\nasync activity(activity: Activity) {\n if (activity.completed) {\n await this.handleCompletion(activity);\n }\n}\n```\n\n## Activity Links\n\nActivity links enable user interaction:\n\n```typescript\nimport { type ActivityLink, ActivityLinkType } from \"@plotday/twister\";\n\n// URL link\nconst urlLink: ActivityLink = {\n title: \"Open website\",\n type: ActivityLinkType.url,\n url: \"https://example.com\",\n};\n\n// Callback link (uses Callbacks tool)\nconst token = await this.callback(this.onLinkClicked, \"context\");\nconst callbackLink: ActivityLink = {\n title: \"Click me\",\n type: ActivityLinkType.callback,\n token: token,\n};\n\n// Add to activity note\nawait this.tools.plot.createActivity({\n type: ActivityType.Note,\n title: \"Task with links\",\n notes: [\n {\n content: \"Click the links below to take action.\",\n links: [urlLink, callbackLink],\n },\n ],\n});\n```\n\n## Authentication Pattern\n\nCommon pattern for OAuth authentication:\n\n```typescript\nasync activate(_priority: Pick<Priority, \"id\">) {\n // Request auth link from tool with callback\n const authLink = await this.tools.googleTool.requestAuth(\n this.onAuthComplete,\n \"google\"\n );\n\n // Create activity with auth link\n const activity = await this.tools.plot.createActivity({\n type: ActivityType.Note,\n title: \"Connect Google account\",\n notes: [\n {\n content: \"Click below to connect your Google account and start syncing.\",\n links: [authLink],\n },\n ],\n });\n\n // Store for later use\n await this.set(\"auth_activity_id\", activity.id);\n}\n\nasync onAuthComplete(authResult: { authToken: string }, provider: string) {\n // Store auth token\n await this.set(`${provider}_auth`, authResult.authToken);\n\n // Continue setup flow\n await this.setupSyncOptions(authResult.authToken);\n}\n```\n\n## Sync Pattern\n\nPattern for syncing external data - demonstrates adding Notes to existing Activities:\n\n```typescript\nasync startSync(calendarId: string): Promise<void> {\n const authToken = await this.get<string>(\"auth_token\");\n\n await this.tools.calendarTool.startSync(\n authToken,\n calendarId,\n this.handleEvent,\n calendarId\n );\n}\n\nasync handleEvent(\n incomingActivity: NewActivityWithNotes,\n calendarId: string\n): Promise<void> {\n // Extract external event ID from meta (adapt based on your tool's data)\n const externalId = incomingActivity.meta?.eventId;\n\n if (!externalId) {\n console.error(\"Event missing external ID\");\n return;\n }\n\n // Check if we've already synced this event\n const mappingKey = `event_mapping:${calendarId}:${externalId}`;\n const existingActivityId = await this.get<Uuid>(mappingKey);\n\n if (existingActivityId) {\n // Event already exists - add update as a Note (add message to thread)\n if (incomingActivity.notes?.[0]?.content) {\n await this.tools.plot.createNote({\n activity: { id: existingActivityId },\n content: incomingActivity.notes[0].content,\n });\n }\n return;\n }\n\n // New event - generate UUID and store mapping\n const activityId = Uuid.Generate();\n await this.set(mappingKey, activityId);\n\n // Create new Activity with initial Note (new thread with first message)\n await this.tools.plot.createActivity({\n ...incomingActivity,\n id: activityId,\n });\n}\n\nasync stopSync(calendarId: string): Promise<void> {\n const authToken = await this.get<string>(\"auth_token\");\n await this.tools.calendarTool.stopSync(authToken, calendarId);\n}\n```\n\n## Calendar Selection Pattern\n\nPattern for letting users select from multiple calendars/accounts:\n\n```typescript\nprivate async createCalendarSelectionActivity(\n provider: string,\n calendars: Calendar[],\n authToken: string\n): Promise<void> {\n const links: ActivityLink[] = [];\n\n for (const calendar of calendars) {\n const token = await this.callback(\n this.onCalendarSelected,\n provider,\n calendar.id,\n calendar.name,\n authToken\n );\n\n links.push({\n title: `\uD83D\uDCC5 ${calendar.name}${calendar.primary ? \" (Primary)\" : \"\"}`,\n type: ActivityLinkType.callback,\n token: token,\n });\n }\n\n await this.tools.plot.createActivity({\n type: ActivityType.Note,\n title: \"Which calendars would you like to connect?\",\n notes: [\n {\n content: \"Select the calendars you want to sync:\",\n links,\n },\n ],\n });\n}\n\nasync onCalendarSelected(\n link: ActivityLink,\n provider: string,\n calendarId: string,\n calendarName: string,\n authToken: string\n): Promise<void> {\n // Start sync for selected calendar\n await this.tools.tool.startSync(\n authToken,\n calendarId,\n this.handleEvent,\n provider,\n calendarId\n );\n}\n```\n\n## Batch Processing Pattern\n\n**Important**: Because Twists run in an ephemeral environment with limited execution time, you must break long operations into batches. Each batch runs independently in a new execution context.\n\n### Key Principles\n\n1. **Store state between batches**: Use the Store tool to persist progress\n2. **Queue next batch**: Use the Run tool to schedule the next chunk\n3. **Clean up when done**: Delete stored state after completion\n4. **Handle failures**: Store enough state to resume if a batch fails\n\n### Example Implementation\n\n```typescript\nasync startSync(resourceId: string): Promise<void> {\n // Initialize state in Store (persists between executions)\n await this.set(`sync_state_${resourceId}`, {\n nextPageToken: null,\n batchNumber: 1,\n itemsProcessed: 0,\n });\n\n // Queue first batch using runTask method\n const callback = await this.callback(this.syncBatch, resourceId);\n await this.runTask(callback);\n}\n\nasync syncBatch(args: any, resourceId: string): Promise<void> {\n // Load state from Store (set by previous execution)\n const state = await this.get(`sync_state_${resourceId}`);\n\n // Process one batch (keep under time limit)\n const result = await this.fetchBatch(state.nextPageToken);\n\n // Process results (create activities with Notes)\n for (const item of result.items) {\n // Check if already synced\n const mappingKey = `item_mapping:${resourceId}:${item.id}`;\n const existingId = await this.get<Uuid>(mappingKey);\n\n if (!existingId) {\n // New item - generate UUID and store mapping\n const activityId = Uuid.Generate();\n await this.set(mappingKey, activityId);\n\n await this.tools.plot.createActivity({\n id: activityId,\n type: ActivityType.Note,\n title: item.title,\n notes: [{ id: Uuid.Generate(), content: item.description }],\n });\n }\n }\n\n if (result.nextPageToken) {\n // Update state in Store for next batch\n await this.set(`sync_state_${resourceId}`, {\n nextPageToken: result.nextPageToken,\n batchNumber: state.batchNumber + 1,\n itemsProcessed: state.itemsProcessed + result.items.length,\n });\n\n // Queue next batch (runs in new execution context)\n const nextCallback = await this.callback(this.syncBatch, resourceId);\n await this.runTask(nextCallback);\n } else {\n // Cleanup when complete\n await this.clear(`sync_state_${resourceId}`);\n\n // Optionally notify user of completion\n await this.tools.plot.createActivity({\n type: ActivityType.Note,\n title: \"Sync complete\",\n notes: [\n {\n content: `Successfully processed ${state.itemsProcessed + result.items.length} items.`,\n },\n ],\n });\n }\n}\n```\n\n## Error Handling\n\nAlways handle errors gracefully and communicate them to users:\n\n```typescript\ntry {\n await this.externalOperation();\n} catch (error) {\n console.error(\"Operation failed:\", error);\n\n await this.tools.plot.createActivity({\n type: ActivityType.Note,\n title: \"Operation failed\",\n notes: [\n {\n content: `Failed to complete operation: ${error.message}`,\n },\n ],\n });\n}\n```\n\n## Common Pitfalls\n\n- **Don't use instance variables for state** - Anything stored in memory is lost after function execution. Always use the Store tool for data that needs to persist.\n- **Processing self-created activities** - Other users may change an Activity created by the twist, resulting in an \\`activity\\` call. Be sure to check the \\`changes === null\\` and/or \\`activity.author.id !== this.id\\` to avoid re-processing.\n- **Always create Activities with Notes** - See \"Understanding Activities and Notes\" section above for the thread/message pattern and decision tree.\n- **Use correct Activity types** - Most should be `ActivityType.Note`. Only use `Action` for tasks with `doneAt`, and `Event` for items with `start`/`end`.\n- **Track external items with UUID mappings** - Generate UUIDs with `Uuid.Generate()` and store mappings (`external_id \u2192 uuid`) for deduplication. Never rely on the `source` field.\n- **Add Notes to existing Activities** - Look up stored UUID mappings before creating new Activities. Think thread replies, not new threads.\n- Tools are declared in the `build` method and accessed via `this.tools.toolName` in twist methods.\n- **Don't forget runtime limits** - Each execution has ~10 seconds. Break long operations into batches with the Tasks tool. Process enough items per batch to be efficient, but few enough to stay under time limits.\n- **Always use Callbacks tool for persistent references** - Direct function references don't survive worker restarts.\n- **Store auth tokens** - Don't re-request authentication unnecessarily.\n- **Clean up callbacks and stored state** - Delete callbacks and Store entries when no longer needed.\n- **Handle missing auth gracefully** - Check for stored auth before operations.\n\n## Testing\n\nBefore deploying, verify:\n\n1. Linting passes: `{{packageManager}} lint`\n2. All dependencies are in package.json\n3. Authentication flow works end-to-end\n4. Batch operations handle pagination correctly\n5. Error cases are handled gracefully\n";
2
2
  //# sourceMappingURL=twist-guide.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"twist-guide.d.ts","sourceRoot":"","sources":["../src/twist-guide.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,WAAW,mvfAAsB,CAAC"}
1
+ {"version":3,"file":"twist-guide.d.ts","sourceRoot":"","sources":["../src/twist-guide.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,WAAW,6lhBAAsB,CAAC"}
@@ -0,0 +1,7 @@
1
+ export type Uuid = string & {
2
+ readonly __brand: "UuidV7";
3
+ };
4
+ export declare namespace Uuid {
5
+ function Generate(): Uuid;
6
+ }
7
+ //# sourceMappingURL=uuid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uuid.d.ts","sourceRoot":"","sources":["../../src/utils/uuid.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAA;CAAE,CAAC;AAE3D,yBAAiB,IAAI,CAAC;IACpB,SAAgB,QAAQ,IAAI,IAAI,CAE/B;CACF"}
@@ -0,0 +1,9 @@
1
+ import { v7 as uuidv7 } from "uuid";
2
+ export var Uuid;
3
+ (function (Uuid) {
4
+ function Generate() {
5
+ return uuidv7();
6
+ }
7
+ Uuid.Generate = Generate;
8
+ })(Uuid || (Uuid = {}));
9
+ //# sourceMappingURL=uuid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uuid.js","sourceRoot":"","sources":["../../src/utils/uuid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,MAAM,CAAC;AAIpC,MAAM,KAAW,IAAI,CAIpB;AAJD,WAAiB,IAAI;IACnB,SAAgB,QAAQ;QACtB,OAAO,MAAM,EAAU,CAAC;IAC1B,CAAC;IAFe,aAAQ,WAEvB,CAAA;AACH,CAAC,EAJgB,IAAI,KAAJ,IAAI,QAIpB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plotday/twister",
3
- "version": "0.26.0",
3
+ "version": "0.27.0",
4
4
  "description": "Plot Twist Creator - Build intelligent extensions that integrate and automate",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -84,6 +84,11 @@
84
84
  "types": "./dist/utils/hash.d.ts",
85
85
  "default": "./dist/utils/hash.js"
86
86
  },
87
+ "./utils/uuid": {
88
+ "@plotday/source": "./src/utils/uuid.ts",
89
+ "types": "./dist/utils/uuid.d.ts",
90
+ "default": "./dist/utils/uuid.js"
91
+ },
87
92
  "./common/calendar": {
88
93
  "@plotday/source": "./src/common/calendar.ts",
89
94
  "types": "./dist/common/calendar.d.ts",
@@ -206,12 +211,14 @@
206
211
  "dotenv": "^16.4.5",
207
212
  "esbuild": "^0.24.0",
208
213
  "prompts": "^2.4.2",
209
- "typebox": "^1.0.35"
214
+ "typebox": "^1.0.35",
215
+ "uuid": "^11.0.5"
210
216
  },
211
217
  "devDependencies": {
212
218
  "@types/asana": "^0.18.17",
213
219
  "@types/node": "^25.0.3",
214
220
  "@types/prompts": "^2.4.9",
221
+ "@types/uuid": "^10.0.0",
215
222
  "tsx": "^4.19.2",
216
223
  "typedoc": "^0.28.14",
217
224
  "typedoc-plugin-missing-exports": "^4.1.2",