@plotday/twister 0.36.0 → 0.38.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 (243) hide show
  1. package/README.md +4 -2
  2. package/bin/commands/create.js +37 -3
  3. package/bin/commands/create.js.map +1 -1
  4. package/bin/commands/deploy.js +4 -0
  5. package/bin/commands/deploy.js.map +1 -1
  6. package/bin/index.js +1 -0
  7. package/bin/index.js.map +1 -1
  8. package/bin/templates/AGENTS.template.md +101 -189
  9. package/bin/templates/README.template.md +2 -23
  10. package/cli/templates/AGENTS.template.md +101 -189
  11. package/cli/templates/README.template.md +2 -23
  12. package/dist/docs/assets/hierarchy.js +1 -1
  13. package/dist/docs/assets/navigation.js +1 -1
  14. package/dist/docs/assets/search.js +1 -1
  15. package/dist/docs/classes/index.Options.html +1 -1
  16. package/dist/docs/classes/index.Source.html +200 -0
  17. package/dist/docs/classes/tool.ITool.html +1 -1
  18. package/dist/docs/classes/tool.Tool.html +21 -21
  19. package/dist/docs/classes/tools_ai.AI.html +1 -1
  20. package/dist/docs/classes/tools_callbacks.Callbacks.html +2 -2
  21. package/dist/docs/classes/tools_integrations.Integrations.html +45 -16
  22. package/dist/docs/classes/tools_network.Network.html +1 -1
  23. package/dist/docs/classes/tools_plot.Plot.html +93 -60
  24. package/dist/docs/classes/tools_store.Store.html +1 -1
  25. package/dist/docs/classes/tools_tasks.Tasks.html +1 -1
  26. package/dist/docs/classes/tools_twists.Twists.html +1 -1
  27. package/dist/docs/classes/twist.Twist.html +42 -10
  28. package/dist/docs/documents/Building_Sources.html +137 -0
  29. package/dist/docs/documents/Built-in_Tools.html +11 -2
  30. package/dist/docs/documents/Core_Concepts.html +5 -10
  31. package/dist/docs/documents/Getting_Started.html +1 -1
  32. package/dist/docs/enums/{plot.ActivityLinkType.html → plot.ActionType.html} +10 -8
  33. package/dist/docs/enums/plot.ActorType.html +7 -7
  34. package/dist/docs/enums/plot.ConferencingProvider.html +6 -6
  35. package/dist/docs/enums/plot.ThemeColor.html +9 -9
  36. package/dist/docs/enums/tag.Tag.html +3 -10
  37. package/dist/docs/enums/tools_integrations.AuthProvider.html +11 -11
  38. package/dist/docs/enums/tools_plot.ContactAccess.html +3 -3
  39. package/dist/docs/enums/tools_plot.PriorityAccess.html +3 -3
  40. package/dist/docs/enums/{tools_plot.ActivityAccess.html → tools_plot.ThreadAccess.html} +6 -6
  41. package/dist/docs/hierarchy.html +1 -1
  42. package/dist/docs/index.html +5 -6
  43. package/dist/docs/media/AGENTS.md +910 -0
  44. package/dist/docs/media/MULTI_USER_AUTH.md +111 -0
  45. package/dist/docs/media/SYNC_STRATEGIES.md +7 -7
  46. package/dist/docs/modules/index.html +1 -1
  47. package/dist/docs/modules/plot.html +1 -1
  48. package/dist/docs/modules/tool.html +1 -1
  49. package/dist/docs/modules/tools_integrations.html +1 -1
  50. package/dist/docs/modules/tools_plot.html +1 -1
  51. package/dist/docs/modules.html +1 -1
  52. package/dist/docs/types/index.NewSchedule.html +33 -0
  53. package/dist/docs/types/index.NewScheduleContact.html +5 -0
  54. package/dist/docs/types/index.NewScheduleOccurrence.html +6 -0
  55. package/dist/docs/types/index.Schedule.html +37 -0
  56. package/dist/docs/types/index.ScheduleContact.html +5 -0
  57. package/dist/docs/types/index.ScheduleContactRole.html +1 -0
  58. package/dist/docs/types/index.ScheduleContactStatus.html +1 -0
  59. package/dist/docs/types/index.ScheduleOccurrence.html +17 -0
  60. package/dist/docs/types/index.ScheduleOccurrenceUpdate.html +2 -0
  61. package/dist/docs/types/plot.Action.html +28 -0
  62. package/dist/docs/types/plot.Actor.html +6 -6
  63. package/dist/docs/types/plot.ActorId.html +1 -1
  64. package/dist/docs/types/plot.ContentType.html +1 -1
  65. package/dist/docs/types/plot.Link.html +36 -0
  66. package/dist/docs/types/plot.NewActor.html +1 -1
  67. package/dist/docs/types/plot.NewContact.html +5 -5
  68. package/dist/docs/types/plot.NewLink.html +26 -0
  69. package/dist/docs/types/plot.NewLinkWithNotes.html +7 -0
  70. package/dist/docs/types/plot.NewNote.html +10 -10
  71. package/dist/docs/types/plot.NewPriority.html +1 -1
  72. package/dist/docs/types/plot.NewTags.html +1 -1
  73. package/dist/docs/types/plot.NewThread.html +27 -0
  74. package/dist/docs/types/plot.NewThreadWithNotes.html +1 -0
  75. package/dist/docs/types/plot.Note.html +9 -8
  76. package/dist/docs/types/plot.NoteUpdate.html +2 -2
  77. package/dist/docs/types/plot.PickPriorityConfig.html +8 -10
  78. package/dist/docs/types/plot.Priority.html +6 -6
  79. package/dist/docs/types/plot.PriorityUpdate.html +1 -1
  80. package/dist/docs/types/plot.Tags.html +1 -1
  81. package/dist/docs/types/plot.Thread.html +1 -0
  82. package/dist/docs/types/plot.ThreadCommon.html +17 -0
  83. package/dist/docs/types/plot.ThreadFilter.html +2 -0
  84. package/dist/docs/types/plot.ThreadMeta.html +11 -0
  85. package/dist/docs/types/plot.ThreadUpdate.html +3 -0
  86. package/dist/docs/types/plot.ThreadWithNotes.html +1 -0
  87. package/dist/docs/types/tools_integrations.ArchiveLinkFilter.html +11 -0
  88. package/dist/docs/types/tools_integrations.AuthToken.html +4 -4
  89. package/dist/docs/types/tools_integrations.Authorization.html +4 -4
  90. package/dist/docs/types/tools_integrations.Channel.html +11 -0
  91. package/dist/docs/types/tools_integrations.LinkTypeConfig.html +17 -0
  92. package/dist/docs/types/tools_plot.LinkFilter.html +10 -0
  93. package/dist/docs/types/tools_plot.LinkSearchResult.html +1 -0
  94. package/dist/docs/types/tools_plot.NoteIntentHandler.html +6 -6
  95. package/dist/docs/types/tools_plot.NoteSearchResult.html +1 -0
  96. package/dist/docs/types/tools_plot.SearchOptions.html +7 -0
  97. package/dist/docs/types/tools_plot.SearchResult.html +1 -0
  98. package/dist/docs/types/tools_twists.TwistPermissions.html +1 -1
  99. package/dist/docs/variables/tools_plot.SEARCH_DEFAULT_LIMIT.html +2 -0
  100. package/dist/docs/variables/tools_plot.SEARCH_MAX_LIMIT.html +2 -0
  101. package/dist/index.d.ts +2 -0
  102. package/dist/index.d.ts.map +1 -1
  103. package/dist/index.js +2 -0
  104. package/dist/index.js.map +1 -1
  105. package/dist/llm-docs/index.d.ts.map +1 -1
  106. package/dist/llm-docs/index.js +4 -8
  107. package/dist/llm-docs/index.js.map +1 -1
  108. package/dist/llm-docs/plot.d.ts +1 -1
  109. package/dist/llm-docs/plot.d.ts.map +1 -1
  110. package/dist/llm-docs/plot.js +1 -1
  111. package/dist/llm-docs/plot.js.map +1 -1
  112. package/dist/llm-docs/schedule.d.ts +9 -0
  113. package/dist/llm-docs/schedule.d.ts.map +1 -0
  114. package/dist/llm-docs/schedule.js +8 -0
  115. package/dist/llm-docs/schedule.js.map +1 -0
  116. package/dist/llm-docs/source.d.ts +9 -0
  117. package/dist/llm-docs/source.d.ts.map +1 -0
  118. package/dist/llm-docs/source.js +8 -0
  119. package/dist/llm-docs/source.js.map +1 -0
  120. package/dist/llm-docs/tag.d.ts +1 -1
  121. package/dist/llm-docs/tag.d.ts.map +1 -1
  122. package/dist/llm-docs/tag.js +1 -1
  123. package/dist/llm-docs/tag.js.map +1 -1
  124. package/dist/llm-docs/tool.d.ts +1 -1
  125. package/dist/llm-docs/tool.d.ts.map +1 -1
  126. package/dist/llm-docs/tool.js +1 -1
  127. package/dist/llm-docs/tool.js.map +1 -1
  128. package/dist/llm-docs/tools/callbacks.d.ts +1 -1
  129. package/dist/llm-docs/tools/callbacks.d.ts.map +1 -1
  130. package/dist/llm-docs/tools/callbacks.js +1 -1
  131. package/dist/llm-docs/tools/callbacks.js.map +1 -1
  132. package/dist/llm-docs/tools/integrations.d.ts +1 -1
  133. package/dist/llm-docs/tools/integrations.d.ts.map +1 -1
  134. package/dist/llm-docs/tools/integrations.js +1 -1
  135. package/dist/llm-docs/tools/integrations.js.map +1 -1
  136. package/dist/llm-docs/tools/plot.d.ts +1 -1
  137. package/dist/llm-docs/tools/plot.d.ts.map +1 -1
  138. package/dist/llm-docs/tools/plot.js +1 -1
  139. package/dist/llm-docs/tools/plot.js.map +1 -1
  140. package/dist/llm-docs/tools/twists.d.ts +1 -1
  141. package/dist/llm-docs/tools/twists.d.ts.map +1 -1
  142. package/dist/llm-docs/tools/twists.js +1 -1
  143. package/dist/llm-docs/tools/twists.js.map +1 -1
  144. package/dist/llm-docs/twist-guide-template.d.ts +1 -1
  145. package/dist/llm-docs/twist-guide-template.d.ts.map +1 -1
  146. package/dist/llm-docs/twist-guide-template.js +1 -1
  147. package/dist/llm-docs/twist-guide-template.js.map +1 -1
  148. package/dist/llm-docs/twist.d.ts +1 -1
  149. package/dist/llm-docs/twist.d.ts.map +1 -1
  150. package/dist/llm-docs/twist.js +1 -1
  151. package/dist/llm-docs/twist.js.map +1 -1
  152. package/dist/plot.d.ts +264 -589
  153. package/dist/plot.d.ts.map +1 -1
  154. package/dist/plot.js +18 -49
  155. package/dist/plot.js.map +1 -1
  156. package/dist/schedule.d.ts +172 -0
  157. package/dist/schedule.d.ts.map +1 -0
  158. package/dist/schedule.js +2 -0
  159. package/dist/schedule.js.map +1 -0
  160. package/dist/source.d.ts +158 -0
  161. package/dist/source.d.ts.map +1 -0
  162. package/dist/source.js +144 -0
  163. package/dist/source.js.map +1 -0
  164. package/dist/tag.d.ts +3 -10
  165. package/dist/tag.d.ts.map +1 -1
  166. package/dist/tag.js +2 -11
  167. package/dist/tag.js.map +1 -1
  168. package/dist/tool.d.ts +1 -15
  169. package/dist/tool.d.ts.map +1 -1
  170. package/dist/tool.js.map +1 -1
  171. package/dist/tools/callbacks.d.ts +1 -1
  172. package/dist/tools/callbacks.js +1 -1
  173. package/dist/tools/integrations.d.ts +119 -52
  174. package/dist/tools/integrations.d.ts.map +1 -1
  175. package/dist/tools/integrations.js +23 -22
  176. package/dist/tools/integrations.js.map +1 -1
  177. package/dist/tools/plot.d.ts +182 -117
  178. package/dist/tools/plot.d.ts.map +1 -1
  179. package/dist/tools/plot.js +23 -21
  180. package/dist/tools/plot.js.map +1 -1
  181. package/dist/tools/twists.d.ts +1 -1
  182. package/dist/twist-guide.d.ts +1 -1
  183. package/dist/twist-guide.d.ts.map +1 -1
  184. package/dist/twist.d.ts +66 -11
  185. package/dist/twist.d.ts.map +1 -1
  186. package/dist/twist.js +79 -10
  187. package/dist/twist.js.map +1 -1
  188. package/package.json +11 -41
  189. package/dist/common/calendar.d.ts +0 -135
  190. package/dist/common/calendar.d.ts.map +0 -1
  191. package/dist/common/calendar.js +0 -2
  192. package/dist/common/calendar.js.map +0 -1
  193. package/dist/common/documents.d.ts +0 -122
  194. package/dist/common/documents.d.ts.map +0 -1
  195. package/dist/common/documents.js +0 -2
  196. package/dist/common/documents.js.map +0 -1
  197. package/dist/common/messaging.d.ts +0 -84
  198. package/dist/common/messaging.d.ts.map +0 -1
  199. package/dist/common/messaging.js +0 -2
  200. package/dist/common/messaging.js.map +0 -1
  201. package/dist/common/projects.d.ts +0 -112
  202. package/dist/common/projects.d.ts.map +0 -1
  203. package/dist/common/projects.js +0 -2
  204. package/dist/common/projects.js.map +0 -1
  205. package/dist/docs/documents/Building_Custom_Tools.html +0 -215
  206. package/dist/docs/enums/plot.ActivityKind.html +0 -14
  207. package/dist/docs/enums/plot.ActivityType.html +0 -10
  208. package/dist/docs/modules/common_calendar.html +0 -1
  209. package/dist/docs/types/common_calendar.Calendar.html +0 -13
  210. package/dist/docs/types/common_calendar.CalendarTool.html +0 -81
  211. package/dist/docs/types/common_calendar.SyncOptions.html +0 -24
  212. package/dist/docs/types/plot.Activity.html +0 -2
  213. package/dist/docs/types/plot.ActivityCommon.html +0 -20
  214. package/dist/docs/types/plot.ActivityFilter.html +0 -3
  215. package/dist/docs/types/plot.ActivityLink.html +0 -26
  216. package/dist/docs/types/plot.ActivityMeta.html +0 -11
  217. package/dist/docs/types/plot.ActivityOccurrence.html +0 -22
  218. package/dist/docs/types/plot.ActivityOccurrenceUpdate.html +0 -3
  219. package/dist/docs/types/plot.ActivityUpdate.html +0 -3
  220. package/dist/docs/types/plot.ActivityWithNotes.html +0 -1
  221. package/dist/docs/types/plot.NewActivity.html +0 -81
  222. package/dist/docs/types/plot.NewActivityOccurrence.html +0 -24
  223. package/dist/docs/types/plot.NewActivityWithNotes.html +0 -1
  224. package/dist/docs/types/tool.SyncToolOptions.html +0 -9
  225. package/dist/docs/types/tools_integrations.IntegrationOptions.html +0 -4
  226. package/dist/docs/types/tools_integrations.IntegrationProviderConfig.html +0 -13
  227. package/dist/docs/types/tools_integrations.Syncable.html +0 -9
  228. package/dist/llm-docs/common/calendar.d.ts +0 -9
  229. package/dist/llm-docs/common/calendar.d.ts.map +0 -1
  230. package/dist/llm-docs/common/calendar.js +0 -8
  231. package/dist/llm-docs/common/calendar.js.map +0 -1
  232. package/dist/llm-docs/common/documents.d.ts +0 -9
  233. package/dist/llm-docs/common/documents.d.ts.map +0 -1
  234. package/dist/llm-docs/common/documents.js +0 -8
  235. package/dist/llm-docs/common/documents.js.map +0 -1
  236. package/dist/llm-docs/common/messaging.d.ts +0 -9
  237. package/dist/llm-docs/common/messaging.d.ts.map +0 -1
  238. package/dist/llm-docs/common/messaging.js +0 -8
  239. package/dist/llm-docs/common/messaging.js.map +0 -1
  240. package/dist/llm-docs/common/projects.d.ts +0 -9
  241. package/dist/llm-docs/common/projects.d.ts.map +0 -1
  242. package/dist/llm-docs/common/projects.js +0 -8
  243. package/dist/llm-docs/common/projects.js.map +0 -1
@@ -4,6 +4,6 @@
4
4
  * This file is auto-generated during build. Do not edit manually.
5
5
  * Generated from: prebuild.ts
6
6
  */
7
- declare const _default: "import { type Tag } from \"./tag\";\nimport { type Callback } from \"./tools/callbacks\";\nimport { type AuthProvider } from \"./tools/integrations\";\nimport { type JSONValue } from \"./utils/types\";\nimport { Uuid } from \"./utils/uuid\";\n\nexport { Tag } from \"./tag\";\nexport { Uuid } from \"./utils/uuid\";\nexport { type JSONValue } from \"./utils/types\";\nexport { type AuthProvider } from \"./tools/integrations\";\n\n/**\n * @fileoverview\n * Core Plot entity types for working with activities, notes, priorities, and contacts.\n *\n * ## Type Pattern: Null vs Undefined Semantics\n *\n * Plot entity types use a consistent pattern to distinguish between missing, unset, and explicitly cleared values:\n *\n * ### Entity Types (Activity, Priority, Note, Actor)\n * - **Required fields**: No `?`, cannot be `undefined`\n * - Example: `id: Uuid`, `type: ActivityType`\n * - **Nullable fields**: Use `| null` to allow explicit clearing\n * - Example: `assignee: ActorId | null`, `done: Date | null`\n * - `null` = field is explicitly unset/cleared\n * - Non-null value = field has a value\n * - **Optional nullable fields**: Use `?` with `| null` for permission-based access\n * - Example: `email?: string | null`, `name?: string | null`\n * - `undefined` = field not included (e.g., no permission to access)\n * - `null` = field included but not set\n * - Value = field has a value\n *\n * ### New* Types (NewActivity, NewNote, NewPriority)\n * Used for creating or updating entities. Support partial updates by distinguishing omitted vs cleared fields:\n * - **Required fields**: Must be provided (no `?`)\n * - Example: `type: ActivityType` in NewActivity\n * - **Optional fields**: Use `?` to make them optional\n * - Example: `title?: string`, `author?: NewActor`\n * - `undefined` (omitted) = don't set/update this field\n * - Provided value = set/update this field\n * - **Optional nullable fields**: Use `?` with `| null` to support clearing\n * - Example: `assignee?: NewActor | null`\n * - `undefined` (omitted) = don't change assignee\n * - `null` = clear the assignee\n * - NewActor = set/update the assignee\n *\n * This pattern allows API consumers to:\n * 1. Omit fields they don't want to change (undefined)\n * 2. Explicitly clear fields by setting to null\n * 3. Set or update fields by providing values\n *\n * @example\n * ```typescript\n * // Creating a new activity\n * const newActivity: NewActivity = {\n * type: ActivityType.Action, // Required\n * title: \"Review PR\", // Optional, provided\n * assignee: null, // Optional nullable, explicitly clearing\n * // priority is omitted (undefined), will auto-select or use default\n * };\n *\n * // Updating an activity - only change what's specified\n * const update: ActivityUpdate = {\n * id: activityId,\n * done: new Date(), // Mark as done\n * assignee: null, // Clear assignee\n * // title is omitted, won't be changed\n * };\n * ```\n */\n\n/**\n * Represents a unique user, contact, or twist in Plot.\n *\n * ActorIds are used throughout Plot for:\n * - Activity authors and assignees\n * - Tag creators (actor_id in activity_tag/note_tag)\n * - Mentions in activities and notes\n * - Any entity that can perform actions in Plot\n */\nexport type ActorId = string & { readonly __brand: \"ActorId\" };\n\n/**\n * Theme colors for priorities.\n */\nexport enum ThemeColor {\n /** Catalyst - Green */\n Catalyst = 0,\n /** Call to Adventure - Blue */\n CallToAdventure = 1,\n /** Rising Action - Purple */\n RisingAction = 2,\n /** Momentum - Pink-Purple */\n Momentum = 3,\n /** Turning Point - Pink */\n TurningPoint = 4,\n /** Breakthrough - Orange */\n Breakthrough = 5,\n /** Climax - Olive */\n Climax = 6,\n /** Resolution - Blue-Gray */\n Resolution = 7,\n}\n\n/**\n * Represents a priority context within Plot.\n *\n * Priorities are similar to projects in other apps. All Activity is in a Priority.\n * Priorities can be nested.\n */\nexport type Priority = {\n /** Unique identifier for the priority */\n id: Uuid;\n /** Human-readable title for the priority */\n title: string;\n /** Whether this priority has been archived */\n archived: boolean;\n /**\n * Optional key for referencing this priority.\n * Keys are unique per priority tree (a user's personal priorities or the root of a shared priority).\n */\n key: string | null;\n /** Optional theme color for the priority (0-7). If not set, inherits from parent or defaults to 7 (Resolution). */\n color: ThemeColor | null;\n};\n\n/**\n * Type for creating new priorities.\n *\n * Supports multiple creation patterns:\n * - Provide a specific UUID for the priority\n * - Provide a key for upsert within the user's priorities\n * - Omit both to auto-generate a new UUID\n *\n * Optionally specify a parent priority by ID or key for hierarchical structures.\n */\nexport type NewPriority = Pick<Priority, \"title\"> &\n Partial<Omit<Priority, \"id\" | \"title\">> &\n (\n | {\n /**\n * Unique identifier for the priority, generated by Uuid.Generate().\n * Specifying an ID allows tools to track and upsert priorities.\n */\n id: Uuid;\n }\n | {\n /**\n * Unique key for the priority within the user's priorities.\n * Can be used to upsert without knowing the UUID.\n * For example, \"@plot\" identifies the Plot priority.\n */\n key: string;\n }\n | {\n /* Neither id nor key is required. An id will be generated and returned. */\n }\n ) & {\n /** Add the new priority as the child of another priority */\n parent?: { id: Uuid } | { key: string };\n };\n\n/**\n * Type for updating existing priorities.\n * Must provide either id or key to identify the priority to update.\n */\nexport type PriorityUpdate = ({ id: Uuid } | { key: string }) &\n Partial<Pick<Priority, \"title\" | \"archived\">>;\n\n/**\n * Enumeration of supported activity types in Plot.\n *\n * Each activity type has different behaviors and rendering characteristics\n * within the Plot application.\n */\nexport enum ActivityType {\n /** A note or piece of information without actionable requirements */\n Note,\n /** An actionable item that can be completed */\n Action,\n /** A scheduled occurrence with start and optional end time */\n Event,\n}\n\n/**\n * Kinds of activities. Used only for visual categorization (icon).\n */\nexport enum ActivityKind {\n document = \"document\", // any external document or item in an external system\n messages = \"messages\", // emails and chat threads\n meeting = \"meeting\", // in-person meeting\n videoconference = \"videoconference\",\n phone = \"phone\",\n focus = \"focus\",\n meal = \"meal\",\n exercise = \"exercise\",\n family = \"family\",\n travel = \"travel\",\n social = \"social\",\n entertainment = \"entertainment\",\n}\n\n/**\n * Enumeration of supported activity link types.\n *\n * Different link types have different behaviors when clicked by users\n * and may require different rendering approaches.\n */\nexport enum ActivityLinkType {\n /** External web links that open in browser */\n external = \"external\",\n /** Authentication flows for connecting services */\n auth = \"auth\",\n /** Callback links that trigger twist methods when clicked */\n callback = \"callback\",\n /** Video conferencing links with provider-specific handling */\n conferencing = \"conferencing\",\n /** File attachment links stored in R2 */\n file = \"file\",\n}\n\n/**\n * Video conferencing providers for conferencing links.\n *\n * Used to identify the conferencing platform and provide\n * provider-specific UI elements (titles, icons, etc.).\n */\nexport enum ConferencingProvider {\n /** Google Meet */\n googleMeet = \"googleMeet\",\n /** Zoom */\n zoom = \"zoom\",\n /** Microsoft Teams */\n microsoftTeams = \"microsoftTeams\",\n /** Cisco Webex */\n webex = \"webex\",\n /** Other or unknown conferencing provider */\n other = \"other\",\n}\n\n/**\n * Represents a clickable link attached to an activity.\n *\n * Activity links are rendered as buttons that enable user interaction with activities.\n * Different link types have specific behaviors and required fields for proper functionality.\n *\n * @example\n * ```typescript\n * // External link - opens URL in browser\n * const externalLink: ActivityLink = {\n * type: ActivityLinkType.external,\n * title: \"Open in Google Calendar\",\n * url: \"https://calendar.google.com/event/123\",\n * };\n *\n * // Conferencing link - opens video conference with provider info\n * const conferencingLink: ActivityLink = {\n * type: ActivityLinkType.conferencing,\n * url: \"https://meet.google.com/abc-defg-hij\",\n * provider: ConferencingProvider.googleMeet,\n * };\n *\n * // Integrations link - initiates OAuth flow\n * const authLink: ActivityLink = {\n * type: ActivityLinkType.auth,\n * title: \"Continue with Google\",\n * provider: AuthProvider.Google,\n * scopes: [\"https://www.googleapis.com/auth/calendar.readonly\"],\n * callback: \"callback-token-for-auth-completion\"\n * };\n *\n * // Callback link - triggers a twist method\n * const callbackLink: ActivityLink = {\n * type: ActivityLinkType.callback,\n * title: \"\uD83D\uDCC5 Primary Calendar\",\n * token: \"callback-token-here\"\n * };\n * ```\n */\nexport type ActivityLink =\n | {\n /** External web link that opens in browser */\n type: ActivityLinkType.external;\n /** Display text for the link button */\n title: string;\n /** URL to open when clicked */\n url: string;\n }\n | {\n /** Video conferencing link with provider-specific handling */\n type: ActivityLinkType.conferencing;\n /** URL to join the conference */\n url: string;\n /** Conferencing provider for UI customization */\n provider: ConferencingProvider;\n }\n | {\n /** Authentication link that initiates an OAuth flow */\n type: ActivityLinkType.auth;\n /** Display text for the auth button */\n title: string;\n /** OAuth provider (e.g., \"google\", \"microsoft\") */\n provider: string;\n /** Array of OAuth scopes to request */\n scopes: string[];\n /** Callback token for auth completion notification */\n callback: Callback;\n }\n | {\n /** Callback link that triggers a twist method when clicked */\n type: ActivityLinkType.callback;\n /** Display text for the callback button */\n title: string;\n /** Token identifying the callback to execute */\n callback: Callback;\n }\n | {\n /** File attachment link stored in R2 */\n type: ActivityLinkType.file;\n /** Unique identifier for the stored file */\n fileId: string;\n /** Original filename */\n fileName: string;\n /** File size in bytes */\n fileSize: number;\n /** MIME type of the file */\n mimeType: string;\n };\n\n/**\n * Represents metadata about an activity, typically from an external system.\n *\n * Activity metadata enables storing additional information about activities,\n * which is useful for synchronization, linking back to external systems,\n * and storing tool-specific data.\n *\n * Must be valid JSON data (strings, numbers, booleans, null, objects, arrays).\n * Functions and other non-JSON values are not supported.\n *\n * @example\n * ```typescript\n * // Calendar event metadata\n * await plot.createActivity({\n * type: ActivityType.Event,\n * title: \"Team Meeting\",\n * start: new Date(\"2024-01-15T10:00:00Z\"),\n * meta: {\n * calendarId: \"primary\",\n * htmlLink: \"https://calendar.google.com/event/abc123\",\n * conferenceData: { ... }\n * }\n * });\n *\n * // Project issue metadata\n * await plot.createActivity({\n * type: ActivityType.Action,\n * title: \"Fix login bug\",\n * meta: {\n * projectId: \"TEAM\",\n * issueNumber: 123,\n * url: \"https://linear.app/team/issue/TEAM-123\"\n * }\n * });\n * ```\n */\nexport type ActivityMeta = {\n /** Source-specific properties and metadata */\n [key: string]: JSONValue;\n};\n\n/**\n * Tags on an item, along with the actors who added each tag.\n */\nexport type Tags = { [K in Tag]?: ActorId[] };\n\n/**\n * A set of tags to add to an item, along with the actors adding each tag.\n */\nexport type NewTags = { [K in Tag]?: NewActor[] };\n\n/**\n * Common fields shared by both Activity and Note entities.\n */\nexport type ActivityCommon = {\n /** Unique identifier for the activity */\n id: Uuid;\n /**\n * When this activity was originally created in its source system.\n *\n * For activities created in Plot, this is when the user created it.\n * For activities synced from external systems (GitHub issues, emails, calendar events),\n * this is the original creation time in that system.\n *\n * Defaults to the current time when creating new activities.\n */\n created: Date;\n /** Information about who created the activity */\n author: Actor;\n /** Whether this activity is private (only visible to author) */\n private: boolean;\n /** Whether this activity has been archived */\n archived: boolean;\n /** Tags attached to this activity. Maps tag ID to array of actor IDs who added that tag. */\n tags: Tags;\n /** Array of actor IDs (users, contacts, or twists) mentioned in this activity via @-mentions */\n mentions: ActorId[];\n};\n\n/**\n * Common fields shared by all activity types (Note, Action, Event).\n * Does not include the discriminant `type` field or type-specific fields like `done`.\n */\ntype ActivityFields = ActivityCommon & {\n /**\n * Globally unique, stable identifier for the item in an external system.\n * MUST use immutable system-generated IDs, not human-readable slugs or titles.\n *\n * Recommended format: `${domain}:${type}:${id}`\n *\n * Examples:\n * - `linear:issue:549dd8bd-2bc9-43d1-95d5-4b4af0c5af1b` (Linear issue by UUID)\n * - `jira:10001:issue:12345` (Jira issue by numeric ID with cloud ID)\n * - `gmail:thread:18d4e5f2a3b1c9d7` (Gmail thread by system ID)\n *\n * \u26A0\uFE0F AVOID: URLs with mutable components like team names or issue keys\n * - Bad: `https://linear.app/team/issue/TEAM-123/title` (team and title can change)\n * - Bad: `jira:issue:PROJECT-42` (issue key can change)\n *\n * When set, uniquely identifies the activity within a priority tree for upsert operations.\n */\n source: string | null;\n /** The display title/summary of the activity */\n title: string;\n /** Optional kind for additional categorization within the activity */\n kind: ActivityKind | null;\n /**\n * The actor assigned to this activity.\n *\n * **For actions (tasks):**\n * - If not provided (undefined), defaults to the user who installed the twist (twist owner)\n * - To create an **unassigned action**, explicitly set `assignee: null`\n * - For synced tasks from external systems, typically set `assignee: null` for unassigned items\n *\n * **For notes and events:** Assignee is optional and typically null.\n * When marking an activity as done, it becomes an Action; if no assignee is set,\n * the twist owner is assigned automatically.\n *\n * @example\n * ```typescript\n * // Create action assigned to twist owner (default behavior)\n * const task: NewActivity = {\n * type: ActivityType.Action,\n * title: \"Follow up on email\"\n * // assignee omitted \u2192 defaults to twist owner\n * };\n *\n * // Create UNASSIGNED action (for backlog items)\n * const backlogTask: NewActivity = {\n * type: ActivityType.Action,\n * title: \"Review PR #123\",\n * assignee: null // Explicitly set to null\n * };\n *\n * // Create action with explicit assignee\n * const assignedTask: NewActivity = {\n * type: ActivityType.Action,\n * title: \"Deploy to production\",\n * assignee: {\n * id: userId as ActorId,\n * type: ActorType.User,\n * name: \"Alice\"\n * }\n * };\n * ```\n */\n assignee: Actor | null;\n /**\n * Start time of a scheduled activity. Notes are not typically scheduled unless they're about specific times.\n * For recurring events, this represents the start of the first occurrence.\n * Can be a Date object for timed events or a date string in \"YYYY-MM-DD\" format for all-day events.\n *\n * **Activity Scheduling States** (for Actions):\n * - **Do Now** (current/actionable): When creating an Action, omitting `start` defaults to current time\n * - **Do Later** (future scheduled): Set `start` to a future Date or date string\n * - **Do Someday** (unscheduled backlog): Explicitly set `start: null`\n *\n * **Important for synced tasks**: When syncing unassigned backlog items from external systems,\n * set BOTH `start: null` AND `assignee: null` to create unscheduled, unassigned actions.\n *\n * @example\n * ```typescript\n * // \"Do Now\" - assigned to twist owner, actionable immediately\n * await this.tools.plot.createActivity({\n * type: ActivityType.Action,\n * title: \"Urgent task\"\n * // start omitted \u2192 defaults to now\n * // assignee omitted \u2192 defaults to twist owner\n * });\n *\n * // \"Do Later\" - scheduled for a specific time\n * await this.tools.plot.createActivity({\n * type: ActivityType.Action,\n * title: \"Future task\",\n * start: new Date(\"2025-02-01\")\n * });\n *\n * // \"Do Someday\" - unassigned backlog item (common for synced tasks)\n * await this.tools.plot.createActivity({\n * type: ActivityType.Action,\n * title: \"Backlog task\",\n * start: null, // Explicitly unscheduled\n * assignee: null // Explicitly unassigned\n * });\n * ```\n */\n start: Date | string | null;\n /**\n * End time of a scheduled activity. Notes are not typically scheduled unless they're about specific times.\n * For recurring events, this represents the end of the first occurrence.\n * Can be a Date object for timed events or a date string in \"YYYY-MM-DD\" format for all-day events.\n * Null for tasks or activities without defined end times.\n */\n end: Date | string | null;\n /**\n * For recurring activities, the last occurrence date (inclusive).\n * Can be a Date object, date string in \"YYYY-MM-DD\" format, or null if recurring indefinitely.\n * When both recurrenceCount and recurrenceUntil are provided, recurrenceCount takes precedence.\n */\n recurrenceUntil: Date | string | null;\n /**\n * For recurring activities, the number of occurrences to generate.\n * Takes precedence over recurrenceUntil if both are provided.\n * Null for non-recurring activities or indefinite recurrence.\n */\n recurrenceCount: number | null;\n /** The priority context this activity belongs to */\n priority: Priority;\n /** Recurrence rule in RFC 5545 RRULE format (e.g., \"FREQ=WEEKLY;BYDAY=MO,WE,FR\") */\n recurrenceRule: string | null;\n /** Array of dates to exclude from the recurrence pattern */\n recurrenceExdates: Date[] | null;\n /** Metadata about the activity, typically from an external system that created it */\n meta: ActivityMeta | null;\n /** Sort order for the activity (fractional positioning) */\n order: number;\n};\n\nexport type Activity = ActivityFields &\n (\n | { type: ActivityType.Note }\n | {\n type: ActivityType.Action;\n /**\n * Timestamp when the activity was marked as complete. Null if not completed.\n */\n done: Date | null;\n }\n | { type: ActivityType.Event }\n );\n\nexport type ActivityWithNotes = Activity & {\n notes: Note[];\n};\n\nexport type NewActivityWithNotes = NewActivity & {\n notes: Omit<NewNote, \"activity\">[];\n};\n\n/**\n * Represents a specific instance of a recurring activity.\n * All field values are computed by merging the recurring activity's\n * defaults with any occurrence-specific overrides.\n */\nexport type ActivityOccurrence = {\n /**\n * Original date/datetime of this occurrence.\n * Use start for the occurrence's current start time.\n * Format: Date object or \"YYYY-MM-DD\" for all-day events.\n */\n occurrence: Date | string;\n\n /**\n * The recurring activity of which this is an occurrence.\n */\n activity: Activity;\n\n /**\n * Effective values for this occurrence (series defaults + overrides).\n * These are the actual values that apply to this specific instance.\n */\n start: Date | string;\n end: Date | string | null;\n done: Date | null;\n title: string;\n /**\n * Meta is merged, with the occurrence's meta taking precedence.\n */\n meta: ActivityMeta | null;\n\n /**\n * Tags for this occurrence (merged with the recurring tags).\n */\n tags: Tags;\n\n /**\n * True if the occurrence is archived.\n */\n archived: boolean;\n};\n\n/**\n * Type for creating or updating activity occurrences.\n *\n * Follows the same pattern as Activity/NewActivity:\n * - Required fields: `occurrence` (key) and `start` (for scheduling)\n * - Optional fields: All others from ActivityOccurrence\n * - Additional fields: `twistTags` for add/remove, `unread` for notification control\n *\n * @example\n * ```typescript\n * const activity: NewActivity = {\n * type: ActivityType.Event,\n * recurrenceRule: \"FREQ=WEEKLY;BYDAY=MO\",\n * occurrences: [\n * {\n * occurrence: new Date(\"2025-01-27T14:00:00Z\"),\n * start: new Date(\"2025-01-27T14:00:00Z\"),\n * tags: { [Tag.Skip]: [user] }\n * }\n * ]\n * };\n * ```\n */\nexport type NewActivityOccurrence = Pick<\n ActivityOccurrence,\n \"occurrence\" | \"start\"\n> &\n Partial<\n Omit<ActivityOccurrence, \"occurrence\" | \"start\" | \"activity\" | \"tags\">\n > & {\n /**\n * Tags specific to this occurrence.\n * These replace any recurrence-level tags for this occurrence.\n */\n tags?: NewTags;\n\n /**\n * Add or remove the twist's tags on this occurrence.\n * Maps tag ID to boolean: true = add tag, false = remove tag.\n */\n twistTags?: Partial<Record<Tag, boolean>>;\n\n /**\n * Whether this occurrence should be marked as unread for users.\n * - undefined/omitted (default): Occurrence is unread for users, except auto-marked\n * as read for the author if they are the twist owner (user)\n * - true: Occurrence is explicitly unread for ALL users (use sparingly)\n * - false: Occurrence is marked as read for all users\n *\n * For the default behavior, omit this field entirely.\n * Use false for initial sync to avoid marking historical items as unread.\n */\n unread?: boolean;\n };\n\n/**\n * Inline type for creating/updating occurrences within NewActivity/ActivityUpdate.\n * Used to specify occurrence-specific overrides when creating or updating a recurring activity.\n */\nexport type ActivityOccurrenceUpdate = Pick<\n NewActivityOccurrence,\n \"occurrence\"\n> &\n Partial<Omit<NewActivityOccurrence, \"occurrence\" | \"activity\">>;\n\n/**\n * Configuration for automatic priority selection based on activity similarity.\n *\n * Maps activity fields to scoring weights or required exact matches:\n * - Number value: Maximum score for similarity matching on this field\n * - `true` value: Required exact match - activities must match exactly or be excluded\n *\n * Scoring rules:\n * - content: Uses vector similarity on activity embedding (cosine similarity)\n * - type: Exact match on ActivityType\n * - mentions: Percentage of existing activity's mentions that appear in new activity\n * - meta.field: Exact match on top-level meta fields (e.g., \"meta.sourceId\")\n *\n * When content is `true`, applies a strong similarity threshold to ensure only close matches.\n * Default (when neither priority nor pickPriority specified): `{content: true}`\n *\n * @example\n * ```typescript\n * // Require exact content match with strong similarity\n * pickPriority: { content: true }\n *\n * // Score based on content (max 100 points) and require exact type match\n * pickPriority: { content: 100, type: true }\n *\n * // Match on meta and score content\n * pickPriority: { \"meta.projectId\": true, content: 50 }\n * ```\n */\nexport type PickPriorityConfig = {\n content?: number | true;\n type?: number | true;\n mentions?: number | true;\n [key: `meta.${string}`]: number | true;\n};\n\n/**\n * Type for creating new activities.\n *\n * Requires only the activity type, with all other fields optional.\n * The author will be automatically assigned by the Plot system based on\n * the current execution context. The ID can be optionally provided by\n * tools for tracking and update detection purposes.\n *\n * **Important: Defaults for Actions**\n *\n * When creating an Activity of type `Action`:\n * - **`start` omitted** \u2192 Defaults to current time (now) \u2192 \"Do Now\"\n * - **`assignee` omitted** \u2192 Defaults to twist owner \u2192 Assigned action\n *\n * To create unassigned backlog items (common for synced tasks), you MUST explicitly set BOTH:\n * - `start: null` \u2192 \"Do Someday\" (unscheduled)\n * - `assignee: null` \u2192 Unassigned\n *\n * **Scheduling States**:\n * - **\"Do Now\"** (actionable today): Omit `start` or set to current time\n * - **\"Do Later\"** (scheduled): Set `start` to a future Date\n * - **\"Do Someday\"** (backlog): Set `start: null`\n *\n * Priority can be specified in three ways:\n * 1. Explicit priority: `priority: { id: \"...\" }` - Use specific priority (disables pickPriority)\n * 2. Pick priority config: `pickPriority: { ... }` - Auto-select based on similarity\n * 3. Neither: Defaults to `pickPriority: { content: true }` for automatic matching\n *\n * @example\n * ```typescript\n * // \"Do Now\" - Assigned to twist owner, actionable immediately\n * const urgentTask: NewActivity = {\n * type: ActivityType.Action,\n * title: \"Review pull request\"\n * // start omitted \u2192 defaults to now\n * // assignee omitted \u2192 defaults to twist owner\n * };\n *\n * // \"Do Someday\" - UNASSIGNED backlog item (for synced tasks)\n * const backlogTask: NewActivity = {\n * type: ActivityType.Action,\n * title: \"Refactor user service\",\n * start: null, // Must explicitly set to null\n * assignee: null // Must explicitly set to null\n * };\n *\n * // \"Do Later\" - Scheduled for specific date\n * const futureTask: NewActivity = {\n * type: ActivityType.Action,\n * title: \"Prepare Q1 review\",\n * start: new Date(\"2025-03-15\")\n * };\n *\n * // Note (typically unscheduled)\n * const note: NewActivity = {\n * type: ActivityType.Note,\n * title: \"Meeting notes\",\n * content: \"Discussed Q4 roadmap...\",\n * start: null // Notes typically don't have scheduled times\n * };\n *\n * // Event (always has explicit start/end times)\n * const event: NewActivity = {\n * type: ActivityType.Event,\n * title: \"Team standup\",\n * start: new Date(\"2025-01-15T10:00:00\"),\n * end: new Date(\"2025-01-15T10:30:00\")\n * };\n * ```\n */\nexport type NewActivity = (\n | { type: ActivityType.Note; done?: never }\n | { type: ActivityType.Action; done?: Date | null }\n | { type: ActivityType.Event; done?: never }\n) &\n Partial<\n Omit<\n ActivityFields,\n \"author\" | \"assignee\" | \"priority\" | \"tags\" | \"mentions\" | \"id\" | \"source\"\n >\n > &\n (\n | {\n /**\n * Unique identifier for the activity, generated by Uuid.Generate().\n * Specifying an ID allows tools to track and upsert activities.\n */\n id: Uuid;\n }\n | {\n /**\n * Canonical URL for the item in an external system.\n * For example, https://acme.atlassian.net/browse/PROJ-42 could represent a Jira issue.\n * When set, it uniquely identifies the activity within a priority tree. This performs\n * an upsert.\n */\n source: string;\n }\n | {\n /* Neither id nor source is required. An id will be generated and returned. */\n }\n ) &\n (\n | {\n /** Explicit priority (required when specified) - disables automatic priority matching */\n priority: Pick<Priority, \"id\">;\n }\n | {\n /** Configuration for automatic priority selection based on similarity */\n pickPriority?: PickPriorityConfig;\n }\n ) & {\n /**\n * The person that created the item. By default, it will be the twist itself.\n */\n author?: NewActor;\n\n /**\n * The person that assigned to the item.\n */\n assignee?: NewActor | null;\n\n /**\n * All tags to set on the new activity.\n */\n tags?: NewTags;\n\n /**\n * Whether the activity should be marked as unread for users.\n * - undefined/omitted (default): Activity is unread for users, except auto-marked\n * as read for the author if they are the twist owner (user)\n * - true: Activity is explicitly unread for ALL users (use sparingly)\n * - false: Activity is marked as read for all users in the priority at creation time\n *\n * For the default behavior, omit this field entirely.\n * Use false for initial sync to avoid marking historical items as unread.\n */\n unread?: boolean;\n\n /**\n * Whether the activity is archived.\n * - true: Archive the activity\n * - false: Unarchive the activity\n * - undefined (default): Preserve current archive state\n *\n * Best practice: Set to false during initial syncs to ensure activities\n * are unarchived. Omit during incremental syncs to preserve user's choice.\n */\n archived?: boolean;\n\n /**\n * Optional preview content for the activity. Can be Markdown formatted.\n * The preview will be automatically generated from this content (truncated to 100 chars).\n *\n * - string: Use this content for preview generation\n * - null: Explicitly disable preview (no preview will be shown)\n * - undefined (default): Fall back to legacy behavior (generate from first note with content)\n *\n * This field is write-only and won't be returned when reading activities.\n */\n preview?: string | null;\n\n /**\n * Create or update specific occurrences of a recurring activity.\n * Each entry specifies overrides for a specific occurrence.\n *\n * When occurrence matches the recurrence rule but only tags are specified,\n * the occurrence is created with just tags in activity_tag.occurrence (no activity_exception).\n *\n * When any other field is specified, creates/updates an activity_exception row.\n *\n * @example\n * ```typescript\n * // Create recurring event with per-occurrence RSVPs\n * const meeting: NewActivity = {\n * type: ActivityType.Event,\n * recurrenceRule: \"FREQ=WEEKLY;BYDAY=MO\",\n * start: new Date(\"2025-01-20T14:00:00Z\"),\n * duration: 1800000, // 30 minutes\n * occurrences: [\n * {\n * occurrence: new Date(\"2025-01-27T14:00:00Z\"),\n * tags: { [Tag.Skip]: [{ email: \"user@example.com\" }] }\n * },\n * {\n * occurrence: new Date(\"2025-02-03T14:00:00Z\"),\n * start: new Date(\"2025-02-03T15:00:00Z\"), // Reschedule this one\n * tags: { [Tag.Attend]: [{ email: \"user@example.com\" }] }\n * }\n * ]\n * };\n * ```\n */\n occurrences?: NewActivityOccurrence[];\n\n /**\n * Dates to add to the recurrence exclusion list.\n * These are merged with existing exdates. Use this for incremental updates\n * (e.g., cancelling a single occurrence) instead of replacing the full list.\n */\n addRecurrenceExdates?: Date[];\n\n /**\n * Dates to remove from the recurrence exclusion list.\n * Use this to \"uncancel\" a previously excluded occurrence.\n */\n removeRecurrenceExdates?: Date[];\n };\n\nexport type ActivityFilter = {\n type?: ActorType;\n meta?: {\n [key: string]: JSONValue;\n };\n};\n\n/**\n * Fields supported by bulk updates via `match`. Only simple scalar fields\n * that can be applied uniformly across many activities are included.\n */\ntype ActivityBulkUpdateFields = Partial<\n Pick<ActivityFields, \"kind\" | \"title\" | \"private\" | \"archived\" | \"meta\" | \"order\">\n> & {\n /** Update the type of all matching activities. */\n type?: ActivityType;\n /**\n * Timestamp when the activities were marked as complete. Null to clear.\n * Setting done will automatically set the type to Action if not already.\n */\n done?: Date | null;\n};\n\n/**\n * Fields supported by single-activity updates via `id` or `source`.\n * Includes all bulk fields plus scheduling, recurrence, tags, and occurrences.\n */\ntype ActivitySingleUpdateFields = ActivityBulkUpdateFields &\n Partial<\n Pick<\n ActivityFields,\n | \"start\"\n | \"end\"\n | \"assignee\"\n | \"recurrenceRule\"\n | \"recurrenceExdates\"\n | \"recurrenceUntil\"\n | \"recurrenceCount\"\n >\n > & {\n /**\n * Tags to change on the activity. Use an empty array of NewActor to remove a tag.\n * Use twistTags to add/remove the twist from tags to avoid clearing other actors' tags.\n */\n tags?: NewTags;\n\n /**\n * Add or remove the twist's tags.\n * Maps tag ID to boolean: true = add tag, false = remove tag.\n * This is allowed on all activities the twist has access to.\n */\n twistTags?: Partial<Record<Tag, boolean>>;\n\n /**\n * Optional preview content for the activity. Can be Markdown formatted.\n * The preview will be automatically generated from this content (truncated to 100 chars).\n *\n * - string: Use this content for preview generation\n * - null: Explicitly disable preview (no preview will be shown)\n * - undefined (omitted): Preserve current preview value\n *\n * This field is write-only and won't be returned when reading activities.\n */\n preview?: string | null;\n\n /**\n * Create or update specific occurrences of this recurring activity.\n * Each entry specifies overrides for a specific occurrence.\n *\n * Setting a field to null reverts it to the series default.\n * Omitting a field leaves it unchanged.\n *\n * @example\n * ```typescript\n * // Update RSVPs for specific occurrences\n * await plot.updateActivity({\n * id: meetingId,\n * occurrences: [\n * {\n * occurrence: new Date(\"2025-01-27T14:00:00Z\"),\n * tags: { [Tag.Skip]: [user] }\n * },\n * {\n * occurrence: new Date(\"2025-02-03T14:00:00Z\"),\n * tags: { [Tag.Attend]: [user] }\n * },\n * {\n * occurrence: new Date(\"2025-02-10T14:00:00Z\"),\n * archived: true // Cancel this occurrence\n * }\n * ]\n * });\n * ```\n */\n occurrences?: (NewActivityOccurrence | ActivityOccurrenceUpdate)[];\n\n /**\n * Dates to add to the recurrence exclusion list.\n * These are merged with existing exdates. Use this for incremental updates\n * (e.g., cancelling a single occurrence) instead of replacing the full list.\n */\n addRecurrenceExdates?: Date[];\n\n /**\n * Dates to remove from the recurrence exclusion list.\n * Use this to \"uncancel\" a previously excluded occurrence.\n */\n removeRecurrenceExdates?: Date[];\n };\n\nexport type ActivityUpdate =\n | (({ id: Uuid } | { source: string }) & ActivitySingleUpdateFields)\n | ({\n /**\n * Update all activities matching the specified criteria. Only activities\n * that match all provided fields and were created by the twist will be updated.\n */\n match: ActivityFilter;\n } & ActivityBulkUpdateFields);\n\n/**\n * Represents a note within an activity.\n *\n * Notes contain the detailed content (note text, links) associated with an activity.\n * They are always ordered by creation time within their parent activity.\n */\nexport type Note = ActivityCommon & {\n /**\n * Globally unique, stable identifier for the note within its activity.\n * Can be used to upsert without knowing the id.\n *\n * Use one of these patterns:\n * - Hardcoded semantic keys for fixed note types: \"description\", \"cancellation\"\n * - External service IDs for dynamic collections: `comment:${immutableId}`\n *\n * Examples:\n * - `\"description\"` (for a Jira issue's description note)\n * - `\"comment:12345\"` (for a specific comment by ID)\n * - `\"gmail:msg:18d4e5f2a3b1c9d7\"` (for a Gmail message within a thread)\n *\n * \u26A0\uFE0F Ensure IDs are immutable - avoid human-readable slugs or titles.\n */\n key: string | null;\n /** The parent activity this note belongs to */\n activity: Activity;\n /** Primary content for the note (markdown) */\n content: string | null;\n /** Array of interactive links attached to the note */\n links: Array<ActivityLink> | null;\n /** The note this is a reply to, or null if not a reply */\n reNote: { id: Uuid } | null;\n};\n\n/**\n * Type for creating new notes.\n *\n * Requires the activity reference, with all other fields optional.\n * Can provide id, key, or neither for note identification:\n * - id: Provide a specific UUID for the note\n * - key: Provide an external identifier for upsert within the activity\n * - neither: A new note with auto-generated UUID will be created\n */\nexport type NewNote = Partial<\n Omit<\n Note,\n \"author\" | \"activity\" | \"tags\" | \"mentions\" | \"id\" | \"key\" | \"reNote\"\n >\n> &\n ({ id: Uuid } | { key: string } | {}) & {\n /** Reference to the parent activity (required) */\n activity:\n | Pick<Activity, \"id\">\n | {\n source: string;\n };\n\n /**\n * The person that created the item, or leave undefined to use the twist as author.\n */\n author?: NewActor;\n\n /**\n * Format of the note content. Determines how the note is processed:\n * - 'text': Plain text that will be converted to markdown (auto-links URLs, preserves line breaks)\n * - 'markdown': Already in markdown format (default, no conversion)\n * - 'html': HTML content that will be converted to markdown\n */\n contentType?: ContentType;\n\n /**\n * Tags to change on the activity. Use an empty array of NewActor to remove a tag.\n * Use twistTags to add/remove the twist from tags to avoid clearing other actors' tags.\n */\n tags?: NewTags;\n\n /**\n * Change the mentions on the note.\n */\n mentions?: NewActor[];\n\n /**\n * Whether the note should mark the parent activity as unread for users.\n * - undefined/omitted (default): Activity is unread for users, except auto-marked\n * as read for the author if they are the twist owner (user)\n * - true: Activity is explicitly unread for ALL users (use sparingly)\n * - false: Activity is marked as read for all users in the priority at note creation time\n *\n * For the default behavior, omit this field entirely.\n * Use false for initial sync to avoid marking historical items as unread.\n */\n unread?: boolean;\n\n /**\n * Reference to a parent note this note is a reply to.\n * - `{ id }`: reply by UUID\n * - `{ key }`: reply by key, resolved after creation (for batch ops)\n * - `null`: explicitly not a reply\n * - `undefined` (omitted): not a reply\n */\n reNote?: { id: Uuid } | { key: string } | null;\n };\n\n/**\n * Type for updating existing notes.\n * Must provide either id or key to identify the note to update.\n */\nexport type NoteUpdate = ({ id: Uuid; key?: string } | { key: string }) &\n Partial<\n Pick<Note, \"private\" | \"archived\" | \"content\" | \"links\" | \"reNote\">\n > & {\n /**\n * Format of the note content. Determines how the note is processed:\n * - 'text': Plain text that will be converted to markdown (auto-links URLs, preserves line breaks)\n * - 'markdown': Already in markdown format (default, no conversion)\n * - 'html': HTML content that will be converted to markdown\n */\n contentType?: ContentType;\n\n /**\n * Tags to change on the note. Use an empty array of NewActor to remove a tag.\n * Use twistTags to add/remove the twist from tags to avoid clearing other actors' tags.\n */\n tags?: NewTags;\n\n /**\n * Add or remove the twist's tags.\n * Maps tag ID to boolean: true = add tag, false = remove tag.\n * This is allowed on all notes the twist has access to.\n */\n twistTags?: Partial<Record<Tag, boolean>>;\n\n /**\n * Change the mentions on the note.\n */\n mentions?: NewActor[];\n };\n\n/**\n * Represents an actor in Plot - a user, contact, or twist.\n *\n * Actors can be associated with activities as authors, assignees, or mentions.\n * The email field is only included when ContactAccess.Read permission is granted.\n *\n * @example\n * ```typescript\n * const actor: Actor = {\n * id: \"f0ffd5f8-1635-4b13-9532-35f97446db90\" as ActorId,\n * type: ActorType.Contact,\n * email: \"john.doe@example.com\", // Only if ContactAccess.Read\n * name: \"John Doe\"\n * };\n * ```\n */\nexport type Actor = {\n /** Unique identifier for the actor */\n id: ActorId;\n /** Type of actor (User, Contact, or Twist) */\n type: ActorType;\n /**\n * Email address (only included with ContactAccess.Read permission).\n * - `undefined`: No permission to read email\n * - `null`: Permission granted but email not set\n * - `string`: Email address\n */\n email?: string | null;\n /**\n * Display name.\n * - `undefined`: Not included due to permissions\n * - `null`: Not set\n * - `string`: Display name\n */\n name?: string | null;\n};\n\n/**\n * An existing or new contact.\n */\nexport type NewActor =\n | {\n /** Unique identifier for the actor */\n id: ActorId;\n }\n | NewContact;\n\n/**\n * Enumeration of author types that can create activities.\n *\n * The author type affects how activities are displayed and processed\n * within the Plot system.\n */\nexport enum ActorType {\n /** Activities created by human users */\n User,\n /** Activities created by external contacts */\n Contact,\n /** Activities created by automated twists */\n Twist,\n}\n\n/**\n * Represents contact information for creating a new contact.\n *\n * Contacts are used throughout Plot for representing people associated\n * with activities, such as event attendees or task assignees.\n *\n * @example\n * ```typescript\n * const newContact: NewContact = {\n * email: \"john.doe@example.com\",\n * name: \"John Doe\",\n * avatar: \"https://avatar.example.com/john.jpg\"\n * };\n * ```\n */\nexport type NewContact = {\n /** Email address of the contact (required) */\n email: string;\n /** Optional display name for the contact */\n name?: string;\n /** Optional avatar image URL for the contact */\n avatar?: string;\n /**\n * External provider account source. Used for privacy compliance\n * (e.g. Atlassian personal data reporting for GDPR account closure).\n * Required for contacts sourced from providers that mandate personal data reporting.\n */\n source?: { provider: AuthProvider; accountId: string };\n};\n\nexport type ContentType = \"text\" | \"markdown\" | \"html\";\n";
7
+ declare const _default: "import type { NewSchedule, NewScheduleOccurrence, Schedule } from \"./schedule\";\nimport { type Tag } from \"./tag\";\nimport { type Callback } from \"./tools/callbacks\";\nimport { type AuthProvider } from \"./tools/integrations\";\nimport { type JSONValue } from \"./utils/types\";\nimport { Uuid } from \"./utils/uuid\";\n\nexport { Tag } from \"./tag\";\nexport { Uuid } from \"./utils/uuid\";\nexport { type JSONValue } from \"./utils/types\";\nexport { type AuthProvider } from \"./tools/integrations\";\n\n/**\n * @fileoverview\n * Core Plot entity types for working with threads, notes, priorities, and contacts.\n *\n * ## Type Pattern: Null vs Undefined Semantics\n *\n * Plot entity types use a consistent pattern to distinguish between missing, unset, and explicitly cleared values:\n *\n * ### Entity Types (Thread, Priority, Note, Actor)\n * - **Required fields**: No `?`, cannot be `undefined`\n * - Example: `id: Uuid`, `title: string`\n * - **Nullable fields**: Use `| null` to allow explicit clearing\n * - Example: `assignee: ActorId | null`, `done: Date | null`\n * - `null` = field is explicitly unset/cleared\n * - Non-null value = field has a value\n * - **Optional nullable fields**: Use `?` with `| null` for permission-based access\n * - Example: `email?: string | null`, `name?: string | null`\n * - `undefined` = field not included (e.g., no permission to access)\n * - `null` = field included but not set\n * - Value = field has a value\n *\n * ### New* Types (NewThread, NewNote, NewPriority)\n * Used for creating or updating entities. Support partial updates by distinguishing omitted vs cleared fields:\n * - **Required fields**: Must be provided (no `?`)\n * - Example: `title: string` in NewPriority\n * - **Optional fields**: Use `?` to make them optional\n * - Example: `title?: string`, `author?: NewActor`\n * - `undefined` (omitted) = don't set/update this field\n * - Provided value = set/update this field\n * - **Optional nullable fields**: Use `?` with `| null` to support clearing\n * - Example: `assignee?: NewActor | null`\n * - `undefined` (omitted) = don't change assignee\n * - `null` = clear the assignee\n * - NewActor = set/update the assignee\n *\n * This pattern allows API consumers to:\n * 1. Omit fields they don't want to change (undefined)\n * 2. Explicitly clear fields by setting to null\n * 3. Set or update fields by providing values\n *\n * @example\n * ```typescript\n * // Creating a new thread\n * const newThread: NewThread = {\n * title: \"Review pull request\",\n * };\n *\n * // Updating a thread - only change what's specified\n * const update: ThreadUpdate = {\n * id: threadId,\n * archived: true,\n * };\n * ```\n */\n\n/**\n * Represents a unique user, contact, or twist in Plot.\n *\n * ActorIds are used throughout Plot for:\n * - Activity authors and assignees\n * - Tag creators (actor_id in activity_tag/note_tag)\n * - Mentions in activities and notes\n * - Any entity that can perform actions in Plot\n */\nexport type ActorId = string & { readonly __brand: \"ActorId\" };\n\n/**\n * Theme colors for priorities.\n */\nexport enum ThemeColor {\n /** Catalyst - Green */\n Catalyst = 0,\n /** Call to Adventure - Blue */\n CallToAdventure = 1,\n /** Rising Action - Purple */\n RisingAction = 2,\n /** Momentum - Pink-Purple */\n Momentum = 3,\n /** Turning Point - Pink */\n TurningPoint = 4,\n /** Breakthrough - Orange */\n Breakthrough = 5,\n /** Climax - Olive */\n Climax = 6,\n /** Resolution - Blue-Gray */\n Resolution = 7,\n}\n\n/**\n * Represents a priority context within Plot.\n *\n * Priorities are similar to projects in other apps. All Activity is in a Priority.\n * Priorities can be nested.\n */\nexport type Priority = {\n /** Unique identifier for the priority */\n id: Uuid;\n /** Human-readable title for the priority */\n title: string;\n /** Whether this priority has been archived */\n archived: boolean;\n /**\n * Optional key for referencing this priority.\n * Keys are unique per priority tree (a user's personal priorities or the root of a shared priority).\n */\n key: string | null;\n /** Optional theme color for the priority (0-7). If not set, inherits from parent or defaults to 7 (Resolution). */\n color: ThemeColor | null;\n};\n\n/**\n * Type for creating new priorities.\n *\n * Supports multiple creation patterns:\n * - Provide a specific UUID for the priority\n * - Provide a key for upsert within the user's priorities\n * - Omit both to auto-generate a new UUID\n *\n * Optionally specify a parent priority by ID or key for hierarchical structures.\n */\nexport type NewPriority = Pick<Priority, \"title\"> &\n Partial<Omit<Priority, \"id\" | \"title\">> &\n (\n | {\n /**\n * Unique identifier for the priority, generated by Uuid.Generate().\n * Specifying an ID allows tools to track and upsert priorities.\n */\n id: Uuid;\n }\n | {\n /**\n * Unique key for the priority within the user's priorities.\n * Can be used to upsert without knowing the UUID.\n * For example, \"@plot\" identifies the Plot priority.\n */\n key: string;\n }\n | {\n /* Neither id nor key is required. An id will be generated and returned. */\n }\n ) & {\n /** Add the new priority as the child of another priority */\n parent?: { id: Uuid } | { key: string };\n };\n\n/**\n * Type for updating existing priorities.\n * Must provide either id or key to identify the priority to update.\n */\nexport type PriorityUpdate = ({ id: Uuid } | { key: string }) &\n Partial<Pick<Priority, \"title\" | \"archived\">>;\n\n/**\n * Enumeration of supported action types.\n *\n * Different action types have different behaviors when clicked by users\n * and may require different rendering approaches.\n */\nexport enum ActionType {\n /** External web links that open in browser */\n external = \"external\",\n /** Authentication flows for connecting services */\n auth = \"auth\",\n /** Callback actions that trigger twist methods when clicked */\n callback = \"callback\",\n /** Video conferencing links with provider-specific handling */\n conferencing = \"conferencing\",\n /** File attachment links stored in R2 */\n file = \"file\",\n /** Thread reference links for navigating to related threads */\n thread = \"thread\",\n}\n\n/**\n * Video conferencing providers for conferencing links.\n *\n * Used to identify the conferencing platform and provide\n * provider-specific UI elements (titles, icons, etc.).\n */\nexport enum ConferencingProvider {\n /** Google Meet */\n googleMeet = \"googleMeet\",\n /** Zoom */\n zoom = \"zoom\",\n /** Microsoft Teams */\n microsoftTeams = \"microsoftTeams\",\n /** Cisco Webex */\n webex = \"webex\",\n /** Other or unknown conferencing provider */\n other = \"other\",\n}\n\n/**\n * Represents a clickable action attached to a thread.\n *\n * Thread actions are rendered as buttons that enable user interaction with threads.\n * Different action types have specific behaviors and required fields for proper functionality.\n *\n * @example\n * ```typescript\n * // External action - opens URL in browser\n * const externalAction: Action = {\n * type: ActionType.external,\n * title: \"Open in Google Calendar\",\n * url: \"https://calendar.google.com/event/123\",\n * };\n *\n * // Conferencing action - opens video conference with provider info\n * const conferencingAction: Action = {\n * type: ActionType.conferencing,\n * url: \"https://meet.google.com/abc-defg-hij\",\n * provider: ConferencingProvider.googleMeet,\n * };\n *\n * // Integrations action - initiates OAuth flow\n * const authAction: Action = {\n * type: ActionType.auth,\n * title: \"Continue with Google\",\n * provider: AuthProvider.Google,\n * scopes: [\"https://www.googleapis.com/auth/calendar.readonly\"],\n * callback: \"callback-token-for-auth-completion\"\n * };\n *\n * // Callback action - triggers a twist method\n * const callbackAction: Action = {\n * type: ActionType.callback,\n * title: \"\uD83D\uDCC5 Primary Calendar\",\n * token: \"callback-token-here\"\n * };\n * ```\n */\nexport type Action =\n | {\n /** External web link that opens in browser */\n type: ActionType.external;\n /** Display text for the action button */\n title: string;\n /** URL to open when clicked */\n url: string;\n }\n | {\n /** Video conferencing action with provider-specific handling */\n type: ActionType.conferencing;\n /** URL to join the conference */\n url: string;\n /** Conferencing provider for UI customization */\n provider: ConferencingProvider;\n }\n | {\n /** Authentication action that initiates an OAuth flow */\n type: ActionType.auth;\n /** Display text for the auth button */\n title: string;\n /** OAuth provider (e.g., \"google\", \"microsoft\") */\n provider: string;\n /** Array of OAuth scopes to request */\n scopes: string[];\n /** Callback token for auth completion notification */\n callback: Callback;\n }\n | {\n /** Callback action that triggers a twist method when clicked */\n type: ActionType.callback;\n /** Display text for the callback button */\n title: string;\n /** Token identifying the callback to execute */\n callback: Callback;\n }\n | {\n /** File attachment action stored in R2 */\n type: ActionType.file;\n /** Unique identifier for the stored file */\n fileId: string;\n /** Original filename */\n fileName: string;\n /** File size in bytes */\n fileSize: number;\n /** MIME type of the file */\n mimeType: string;\n }\n | {\n /** Thread reference action for navigating to a related thread */\n type: ActionType.thread;\n /** UUID of the referenced thread */\n threadId: Uuid;\n };\n\n/**\n * Represents metadata about a thread, typically from an external system.\n *\n * Thread metadata enables storing additional information about threads,\n * which is useful for synchronization, linking back to external systems,\n * and storing tool-specific data.\n *\n * Must be valid JSON data (strings, numbers, booleans, null, objects, arrays).\n * Functions and other non-JSON values are not supported.\n *\n * @example\n * ```typescript\n * // Calendar event metadata\n * await plot.createThread({\n * title: \"Team Meeting\",\n * meta: {\n * calendarId: \"primary\",\n * htmlLink: \"https://calendar.google.com/event/abc123\",\n * conferenceData: { ... }\n * }\n * });\n *\n * // Project issue metadata\n * await plot.createThread({\n * title: \"Fix login bug\",\n * meta: {\n * projectId: \"TEAM\",\n * issueNumber: 123,\n * url: \"https://linear.app/team/issue/TEAM-123\"\n * }\n * });\n * ```\n */\nexport type ThreadMeta = {\n /** Source-specific properties and metadata */\n [key: string]: JSONValue;\n};\n\n/**\n * Tags on an item, along with the actors who added each tag.\n */\nexport type Tags = { [K in Tag]?: ActorId[] };\n\n/**\n * A set of tags to add to an item, along with the actors adding each tag.\n */\nexport type NewTags = { [K in Tag]?: NewActor[] };\n\n/**\n * Common fields shared by both Thread and Note entities.\n */\nexport type ThreadCommon = {\n /** Unique identifier for the thread */\n id: Uuid;\n /**\n * When this item was created.\n *\n * **For sources:** Set this to the external system's timestamp (e.g., email\n * sent date, comment creation date), NOT the sync time. If omitted, defaults\n * to the current time, which is almost never correct for synced data.\n */\n created: Date;\n /** Whether this thread is private (only visible to creator) */\n private: boolean;\n /** Whether this thread has been archived */\n archived: boolean;\n /** Tags attached to this thread. Maps tag ID to array of actor IDs who added that tag. */\n tags: Tags;\n /** Array of actor IDs (users, contacts, or twists) mentioned in this thread via @-mentions */\n mentions: ActorId[];\n};\n\n/**\n * Fields on a Thread entity.\n * Threads are simple containers for links and notes.\n */\ntype ThreadFields = ThreadCommon & {\n /** The display title/summary of the thread */\n title: string;\n /** The priority context this thread belongs to */\n priority: Priority;\n /** The schedule associated with this thread, if any */\n schedule?: Schedule;\n /** Source-specific metadata from the thread's link, populated on callbacks */\n meta?: ThreadMeta;\n};\n\nexport type Thread = ThreadFields;\n\nexport type ThreadWithNotes = Thread & {\n notes: Note[];\n};\n\nexport type NewThreadWithNotes = NewThread & {\n notes: Omit<NewNote, \"thread\">[];\n};\n\n/**\n * Configuration for automatic priority selection based on thread similarity.\n *\n * Maps thread fields to scoring weights or required exact matches:\n * - Number value: Maximum score for similarity matching on this field\n * - `true` value: Required exact match - threads must match exactly or be excluded\n *\n * Scoring rules:\n * - content: Uses vector similarity on thread embedding (cosine similarity)\n * - mentions: Percentage of existing thread's mentions that appear in new thread\n * - meta.field: Exact match on top-level meta fields (e.g., \"meta.sourceId\")\n *\n * When content is `true`, applies a strong similarity threshold to ensure only close matches.\n * Default (when neither priority nor pickPriority specified): `{content: true}`\n *\n * @example\n * ```typescript\n * // Require exact content match with strong similarity\n * pickPriority: { content: true }\n *\n * // Score based on content (max 100 points) and mentions\n * pickPriority: { content: 100, mentions: true }\n *\n * // Match on meta and score content\n * pickPriority: { \"meta.projectId\": true, content: 50 }\n * ```\n */\nexport type PickPriorityConfig = {\n content?: number | true;\n mentions?: number | true;\n [key: `meta.${string}`]: number | true;\n};\n\n/**\n * Type for creating new threads.\n *\n * Threads are simple containers. All other fields are optional.\n *\n * @example\n * ```typescript\n * const thread: NewThread = {\n * title: \"Review pull request\"\n * };\n * ```\n */\nexport type NewThread = Partial<\n Omit<ThreadFields, \"priority\" | \"tags\" | \"mentions\" | \"id\">\n> &\n (\n | {\n /** Unique identifier for the thread, generated by Uuid.Generate(). */\n id: Uuid;\n }\n | {\n /* id is optional. An id will be generated and returned. */\n }\n ) &\n (\n | {\n /** Explicit priority (required when specified) - disables automatic priority matching */\n priority: Pick<Priority, \"id\">;\n }\n | {\n /** Configuration for automatic priority selection based on similarity */\n pickPriority?: PickPriorityConfig;\n }\n ) & {\n /**\n * All tags to set on the new thread.\n */\n tags?: NewTags;\n\n /**\n * Whether the thread should be marked as unread for users.\n * - undefined/omitted (default): Thread is unread for users, except auto-marked\n * as read for the author if they are the twist owner (user)\n * - true: Thread is explicitly unread for ALL users (use sparingly)\n * - false: Thread is marked as read for all users in the priority at creation time\n */\n unread?: boolean;\n\n /**\n * Whether the thread is archived.\n * - true: Archive the thread\n * - false: Unarchive the thread\n * - undefined (default): Preserve current archive state\n */\n archived?: boolean;\n\n /**\n * Optional preview content for the thread. Can be Markdown formatted.\n * The preview will be automatically generated from this content (truncated to 100 chars).\n */\n preview?: string | null;\n\n /**\n * Optional schedules to create alongside the thread.\n */\n schedules?: Array<Omit<NewSchedule, \"threadId\">>;\n\n /**\n * Optional schedule occurrence overrides.\n */\n scheduleOccurrences?: NewScheduleOccurrence[];\n };\n\nexport type ThreadFilter = {\n meta?: {\n [key: string]: JSONValue;\n };\n};\n\n/**\n * Fields supported by bulk updates via `match`. Only simple scalar fields\n * that can be applied uniformly across many threads are included.\n */\ntype ThreadBulkUpdateFields = Partial<\n Pick<ThreadFields, \"title\" | \"private\" | \"archived\">\n>;\n\n/**\n * Fields supported by single-thread updates via `id` or `source`.\n * Includes all bulk fields plus tags and preview.\n */\ntype ThreadSingleUpdateFields = ThreadBulkUpdateFields & {\n /**\n * Tags to change on the thread. Use an empty array of NewActor to remove a tag.\n * Use twistTags to add/remove the twist from tags to avoid clearing other actors' tags.\n */\n tags?: NewTags;\n\n /**\n * Add or remove the twist's tags.\n * Maps tag ID to boolean: true = add tag, false = remove tag.\n * This is allowed on all threads the twist has access to.\n */\n twistTags?: Partial<Record<Tag, boolean>>;\n\n /**\n * Optional preview content for the thread. Can be Markdown formatted.\n * The preview will be automatically generated from this content (truncated to 100 chars).\n *\n * - string: Use this content for preview generation\n * - null: Explicitly disable preview (no preview will be shown)\n * - undefined (omitted): Preserve current preview value\n *\n * This field is write-only and won't be returned when reading threads.\n */\n preview?: string | null;\n};\n\nexport type ThreadUpdate =\n | (({ id: Uuid } | { source: string }) & ThreadSingleUpdateFields)\n | ({\n /**\n * Update all threads matching the specified criteria. Only threads\n * that match all provided fields and were created by the twist will be updated.\n */\n match: ThreadFilter;\n } & ThreadBulkUpdateFields);\n\n/**\n * Represents a note within a thread.\n *\n * Notes contain the detailed content (note text, actions) associated with a thread.\n * They are always ordered by creation time within their parent thread.\n */\nexport type Note = ThreadCommon & {\n /** The author of this note */\n author: Actor;\n /**\n * Globally unique, stable identifier for the note within its thread.\n * Can be used to upsert without knowing the id.\n *\n * Use one of these patterns:\n * - Hardcoded semantic keys for fixed note types: \"description\", \"cancellation\"\n * - External service IDs for dynamic collections: `comment:${immutableId}`\n *\n * Examples:\n * - `\"description\"` (for a Jira issue's description note)\n * - `\"comment:12345\"` (for a specific comment by ID)\n * - `\"gmail:msg:18d4e5f2a3b1c9d7\"` (for a Gmail message within a thread)\n *\n * Ensure IDs are immutable - avoid human-readable slugs or titles.\n */\n key: string | null;\n /** The parent thread this note belongs to */\n thread: Thread;\n /** Primary content for the note (markdown) */\n content: string | null;\n /** Array of interactive actions attached to the note */\n actions: Array<Action> | null;\n /** The note this is a reply to, or null if not a reply */\n reNote: { id: Uuid } | null;\n};\n\n/**\n * Type for creating new notes.\n *\n * Requires the thread reference, with all other fields optional.\n * Can provide id, key, or neither for note identification:\n * - id: Provide a specific UUID for the note\n * - key: Provide an external identifier for upsert within the thread\n * - neither: A new note with auto-generated UUID will be created\n */\nexport type NewNote = Partial<\n Omit<\n Note,\n \"author\" | \"thread\" | \"tags\" | \"mentions\" | \"id\" | \"key\" | \"reNote\"\n >\n> &\n ({ id: Uuid } | { key: string } | {}) & {\n /** Reference to the parent thread (required) */\n thread:\n | Pick<Thread, \"id\">\n | {\n source: string;\n };\n\n /**\n * The person that created the item, or leave undefined to use the twist as author.\n */\n author?: NewActor;\n\n /**\n * Format of the note content. Determines how the note is processed:\n * - 'text': Plain text that will be converted to markdown (auto-links URLs, preserves line breaks)\n * - 'markdown': Already in markdown format (default, no conversion)\n * - 'html': HTML content that will be converted to markdown\n */\n contentType?: ContentType;\n\n /**\n * Tags to change on the thread. Use an empty array of NewActor to remove a tag.\n * Use twistTags to add/remove the twist from tags to avoid clearing other actors' tags.\n */\n tags?: NewTags;\n\n /**\n * Change the mentions on the note.\n */\n mentions?: NewActor[];\n\n /**\n * Whether the note should mark the parent thread as unread for users.\n * - undefined/omitted (default): Thread is unread for users, except auto-marked\n * as read for the author if they are the twist owner (user)\n * - true: Thread is explicitly unread for ALL users (use sparingly)\n * - false: Thread is marked as read for all users in the priority at note creation time\n *\n * For the default behavior, omit this field entirely.\n * Use false for initial sync to avoid marking historical items as unread.\n */\n unread?: boolean;\n\n /**\n * Reference to a parent note this note is a reply to.\n * - `{ id }`: reply by UUID\n * - `{ key }`: reply by key, resolved after creation (for batch ops)\n * - `null`: explicitly not a reply\n * - `undefined` (omitted): not a reply\n */\n reNote?: { id: Uuid } | { key: string } | null;\n };\n\n/**\n * Type for updating existing notes.\n * Must provide either id or key to identify the note to update.\n */\nexport type NoteUpdate = ({ id: Uuid; key?: string } | { key: string }) &\n Partial<\n Pick<Note, \"private\" | \"archived\" | \"content\" | \"actions\" | \"reNote\">\n > & {\n /**\n * Format of the note content. Determines how the note is processed:\n * - 'text': Plain text that will be converted to markdown (auto-links URLs, preserves line breaks)\n * - 'markdown': Already in markdown format (default, no conversion)\n * - 'html': HTML content that will be converted to markdown\n */\n contentType?: ContentType;\n\n /**\n * Tags to change on the note. Use an empty array of NewActor to remove a tag.\n * Use twistTags to add/remove the twist from tags to avoid clearing other actors' tags.\n */\n tags?: NewTags;\n\n /**\n * Add or remove the twist's tags.\n * Maps tag ID to boolean: true = add tag, false = remove tag.\n * This is allowed on all notes the twist has access to.\n */\n twistTags?: Partial<Record<Tag, boolean>>;\n\n /**\n * Change the mentions on the note.\n */\n mentions?: NewActor[];\n };\n\n/**\n * Represents an actor in Plot - a user, contact, or twist.\n *\n * Actors can be associated with threads as authors, assignees, or mentions.\n * The email field is only included when ContactAccess.Read permission is granted.\n *\n * @example\n * ```typescript\n * const actor: Actor = {\n * id: \"f0ffd5f8-1635-4b13-9532-35f97446db90\" as ActorId,\n * type: ActorType.Contact,\n * email: \"john.doe@example.com\", // Only if ContactAccess.Read\n * name: \"John Doe\"\n * };\n * ```\n */\nexport type Actor = {\n /** Unique identifier for the actor */\n id: ActorId;\n /** Type of actor (User, Contact, or Twist) */\n type: ActorType;\n /**\n * Email address (only included with ContactAccess.Read permission).\n * - `undefined`: No permission to read email\n * - `null`: Permission granted but email not set\n * - `string`: Email address\n */\n email?: string | null;\n /**\n * Display name.\n * - `undefined`: Not included due to permissions\n * - `null`: Not set\n * - `string`: Display name\n */\n name?: string | null;\n};\n\n/**\n * An existing or new contact.\n */\nexport type NewActor =\n | {\n /** Unique identifier for the actor */\n id: ActorId;\n }\n | NewContact;\n\n/**\n * Enumeration of author types that can create threads.\n *\n * The author type affects how threads are displayed and processed\n * within the Plot system.\n */\nexport enum ActorType {\n /** Threads created by human users */\n User,\n /** Threads created by external contacts */\n Contact,\n /** Threads created by automated twists */\n Twist,\n}\n\n/**\n * Represents contact information for creating a new contact.\n *\n * Contacts are used throughout Plot for representing people associated\n * with activities, such as event attendees or task assignees.\n *\n * @example\n * ```typescript\n * const newContact: NewContact = {\n * email: \"john.doe@example.com\",\n * name: \"John Doe\",\n * avatar: \"https://avatar.example.com/john.jpg\"\n * };\n * ```\n */\nexport type NewContact = {\n /** Email address of the contact (required) */\n email: string;\n /** Optional display name for the contact */\n name?: string;\n /** Optional avatar image URL for the contact */\n avatar?: string;\n /**\n * External provider account source. Used for privacy compliance\n * (e.g. Atlassian personal data reporting for GDPR account closure).\n * Required for contacts sourced from providers that mandate personal data reporting.\n */\n source?: { provider: AuthProvider; accountId: string };\n};\n\nexport type ContentType = \"text\" | \"markdown\" | \"html\";\n\n/**\n * Represents an external entity linked to a thread.\n *\n * Links are created by sources to represent external entities (issues, emails, calendar events)\n * attached to a thread container. A thread can have multiple links (1:many).\n * Links store source-specific data like type, status, metadata, and embeddings.\n *\n * @example\n * ```typescript\n * // A link representing a Linear issue\n * const link: Link = {\n * id: \"...\" as Uuid,\n * threadId: \"...\" as Uuid,\n * source: \"linear:issue:549dd8bd-2bc9-43d1-95d5-4b4af0c5af1b\",\n * created: new Date(),\n * author: { id: \"...\" as ActorId, type: ActorType.Contact, name: \"Alice\" },\n * title: \"Fix login bug\",\n * type: \"issue\",\n * status: \"open\",\n * meta: { projectId: \"TEAM\", url: \"https://linear.app/team/TEAM-123\" },\n * assignee: null,\n * actions: null,\n * };\n * ```\n */\nexport type Link = {\n /** Unique identifier for the link */\n id: Uuid;\n /** The thread this link belongs to */\n threadId: Uuid;\n /** External source identifier for dedup/upsert */\n source: string | null;\n /** When this link was originally created in its source system */\n created: Date;\n /** The actor credited with creating this link */\n author: Actor | null;\n /** Display title */\n title: string;\n /** Truncated preview */\n preview: string | null;\n /** The actor assigned to this link */\n assignee: Actor | null;\n /** Source-defined type string (e.g., issue, pull_request, email, event) */\n type: string | null;\n /** Source-defined status string (e.g., open, done, closed) */\n status: string | null;\n /** Interactive action buttons */\n actions: Array<Action> | null;\n /** Source metadata */\n meta: ThreadMeta | null;\n /** URL to open the original item in its source application (e.g., \"Open in Linear\") */\n sourceUrl: string | null;\n /** Channel ID that produced this link (matches source_channel.channel_id) */\n channelId: string | null;\n};\n\n/**\n * Type for creating new links.\n *\n * Links are created by sources to represent external entities.\n * Requires a source identifier for dedup/upsert.\n */\nexport type NewLink = (\n | {\n /** Unique identifier for the link, generated by Uuid.Generate() */\n id: Uuid;\n }\n | {\n /**\n * Canonical ID for the item in an external system.\n * When set, uniquely identifies the link within a priority tree. This performs\n * an upsert.\n */\n source: string;\n }\n | {}\n) &\n Partial<Omit<Link, \"id\" | \"source\" | \"author\" | \"assignee\" | \"threadId\">> & {\n /** The person that created the item. By default, it will be the twist itself. */\n author?: NewActor;\n /** The person assigned to the item. */\n assignee?: NewActor | null;\n /**\n * Whether the thread should be marked as unread for users.\n * - undefined/omitted (default): Thread is unread for users, except auto-marked\n * as read for the author if they are the twist owner (user)\n * - false: Thread is marked as read for all users in the priority at creation time\n */\n unread?: boolean;\n /**\n * Whether the thread is archived.\n * - true: Archive the thread\n * - false: Unarchive the thread\n * - undefined (default): Preserve current archive state\n */\n archived?: boolean;\n /**\n * Configuration for automatic priority selection based on similarity.\n * Only used when the link creates a new thread.\n */\n pickPriority?: PickPriorityConfig;\n /**\n * Explicit priority (disables automatic priority matching).\n * Only used when the link creates a new thread.\n */\n priority?: Pick<Priority, \"id\">;\n };\n\n/**\n * A new link with notes to save via integrations.saveLink().\n * Creates a thread+link pair, with notes attached to the thread.\n */\nexport type NewLinkWithNotes = NewLink & {\n /** Title for the link and its thread container */\n title: string;\n /** Notes to attach to the thread */\n notes?: Omit<NewNote, \"thread\">[];\n /** Schedules to create for the link */\n schedules?: Array<Omit<NewSchedule, \"threadId\">>;\n /** Schedule occurrence overrides */\n scheduleOccurrences?: NewScheduleOccurrence[];\n};\n";
8
8
  export default _default;
9
9
  //# sourceMappingURL=plot.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"plot.d.ts","sourceRoot":"","sources":["../../src/llm-docs/plot.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;wBAEY,6s1CAAwn1C;AAAvo1C,wBAAwo1C"}
1
+ {"version":3,"file":"plot.d.ts","sourceRoot":"","sources":["../../src/llm-docs/plot.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;wBAEY,su6BAA4t6B;AAA3u6B,wBAA4u6B"}
@@ -4,5 +4,5 @@
4
4
  * This file is auto-generated during build. Do not edit manually.
5
5
  * Generated from: prebuild.ts
6
6
  */
7
- export default "import { type Tag } from \"./tag\";\nimport { type Callback } from \"./tools/callbacks\";\nimport { type AuthProvider } from \"./tools/integrations\";\nimport { type JSONValue } from \"./utils/types\";\nimport { Uuid } from \"./utils/uuid\";\n\nexport { Tag } from \"./tag\";\nexport { Uuid } from \"./utils/uuid\";\nexport { type JSONValue } from \"./utils/types\";\nexport { type AuthProvider } from \"./tools/integrations\";\n\n/**\n * @fileoverview\n * Core Plot entity types for working with activities, notes, priorities, and contacts.\n *\n * ## Type Pattern: Null vs Undefined Semantics\n *\n * Plot entity types use a consistent pattern to distinguish between missing, unset, and explicitly cleared values:\n *\n * ### Entity Types (Activity, Priority, Note, Actor)\n * - **Required fields**: No `?`, cannot be `undefined`\n * - Example: `id: Uuid`, `type: ActivityType`\n * - **Nullable fields**: Use `| null` to allow explicit clearing\n * - Example: `assignee: ActorId | null`, `done: Date | null`\n * - `null` = field is explicitly unset/cleared\n * - Non-null value = field has a value\n * - **Optional nullable fields**: Use `?` with `| null` for permission-based access\n * - Example: `email?: string | null`, `name?: string | null`\n * - `undefined` = field not included (e.g., no permission to access)\n * - `null` = field included but not set\n * - Value = field has a value\n *\n * ### New* Types (NewActivity, NewNote, NewPriority)\n * Used for creating or updating entities. Support partial updates by distinguishing omitted vs cleared fields:\n * - **Required fields**: Must be provided (no `?`)\n * - Example: `type: ActivityType` in NewActivity\n * - **Optional fields**: Use `?` to make them optional\n * - Example: `title?: string`, `author?: NewActor`\n * - `undefined` (omitted) = don't set/update this field\n * - Provided value = set/update this field\n * - **Optional nullable fields**: Use `?` with `| null` to support clearing\n * - Example: `assignee?: NewActor | null`\n * - `undefined` (omitted) = don't change assignee\n * - `null` = clear the assignee\n * - NewActor = set/update the assignee\n *\n * This pattern allows API consumers to:\n * 1. Omit fields they don't want to change (undefined)\n * 2. Explicitly clear fields by setting to null\n * 3. Set or update fields by providing values\n *\n * @example\n * ```typescript\n * // Creating a new activity\n * const newActivity: NewActivity = {\n * type: ActivityType.Action, // Required\n * title: \"Review PR\", // Optional, provided\n * assignee: null, // Optional nullable, explicitly clearing\n * // priority is omitted (undefined), will auto-select or use default\n * };\n *\n * // Updating an activity - only change what's specified\n * const update: ActivityUpdate = {\n * id: activityId,\n * done: new Date(), // Mark as done\n * assignee: null, // Clear assignee\n * // title is omitted, won't be changed\n * };\n * ```\n */\n\n/**\n * Represents a unique user, contact, or twist in Plot.\n *\n * ActorIds are used throughout Plot for:\n * - Activity authors and assignees\n * - Tag creators (actor_id in activity_tag/note_tag)\n * - Mentions in activities and notes\n * - Any entity that can perform actions in Plot\n */\nexport type ActorId = string & { readonly __brand: \"ActorId\" };\n\n/**\n * Theme colors for priorities.\n */\nexport enum ThemeColor {\n /** Catalyst - Green */\n Catalyst = 0,\n /** Call to Adventure - Blue */\n CallToAdventure = 1,\n /** Rising Action - Purple */\n RisingAction = 2,\n /** Momentum - Pink-Purple */\n Momentum = 3,\n /** Turning Point - Pink */\n TurningPoint = 4,\n /** Breakthrough - Orange */\n Breakthrough = 5,\n /** Climax - Olive */\n Climax = 6,\n /** Resolution - Blue-Gray */\n Resolution = 7,\n}\n\n/**\n * Represents a priority context within Plot.\n *\n * Priorities are similar to projects in other apps. All Activity is in a Priority.\n * Priorities can be nested.\n */\nexport type Priority = {\n /** Unique identifier for the priority */\n id: Uuid;\n /** Human-readable title for the priority */\n title: string;\n /** Whether this priority has been archived */\n archived: boolean;\n /**\n * Optional key for referencing this priority.\n * Keys are unique per priority tree (a user's personal priorities or the root of a shared priority).\n */\n key: string | null;\n /** Optional theme color for the priority (0-7). If not set, inherits from parent or defaults to 7 (Resolution). */\n color: ThemeColor | null;\n};\n\n/**\n * Type for creating new priorities.\n *\n * Supports multiple creation patterns:\n * - Provide a specific UUID for the priority\n * - Provide a key for upsert within the user's priorities\n * - Omit both to auto-generate a new UUID\n *\n * Optionally specify a parent priority by ID or key for hierarchical structures.\n */\nexport type NewPriority = Pick<Priority, \"title\"> &\n Partial<Omit<Priority, \"id\" | \"title\">> &\n (\n | {\n /**\n * Unique identifier for the priority, generated by Uuid.Generate().\n * Specifying an ID allows tools to track and upsert priorities.\n */\n id: Uuid;\n }\n | {\n /**\n * Unique key for the priority within the user's priorities.\n * Can be used to upsert without knowing the UUID.\n * For example, \"@plot\" identifies the Plot priority.\n */\n key: string;\n }\n | {\n /* Neither id nor key is required. An id will be generated and returned. */\n }\n ) & {\n /** Add the new priority as the child of another priority */\n parent?: { id: Uuid } | { key: string };\n };\n\n/**\n * Type for updating existing priorities.\n * Must provide either id or key to identify the priority to update.\n */\nexport type PriorityUpdate = ({ id: Uuid } | { key: string }) &\n Partial<Pick<Priority, \"title\" | \"archived\">>;\n\n/**\n * Enumeration of supported activity types in Plot.\n *\n * Each activity type has different behaviors and rendering characteristics\n * within the Plot application.\n */\nexport enum ActivityType {\n /** A note or piece of information without actionable requirements */\n Note,\n /** An actionable item that can be completed */\n Action,\n /** A scheduled occurrence with start and optional end time */\n Event,\n}\n\n/**\n * Kinds of activities. Used only for visual categorization (icon).\n */\nexport enum ActivityKind {\n document = \"document\", // any external document or item in an external system\n messages = \"messages\", // emails and chat threads\n meeting = \"meeting\", // in-person meeting\n videoconference = \"videoconference\",\n phone = \"phone\",\n focus = \"focus\",\n meal = \"meal\",\n exercise = \"exercise\",\n family = \"family\",\n travel = \"travel\",\n social = \"social\",\n entertainment = \"entertainment\",\n}\n\n/**\n * Enumeration of supported activity link types.\n *\n * Different link types have different behaviors when clicked by users\n * and may require different rendering approaches.\n */\nexport enum ActivityLinkType {\n /** External web links that open in browser */\n external = \"external\",\n /** Authentication flows for connecting services */\n auth = \"auth\",\n /** Callback links that trigger twist methods when clicked */\n callback = \"callback\",\n /** Video conferencing links with provider-specific handling */\n conferencing = \"conferencing\",\n /** File attachment links stored in R2 */\n file = \"file\",\n}\n\n/**\n * Video conferencing providers for conferencing links.\n *\n * Used to identify the conferencing platform and provide\n * provider-specific UI elements (titles, icons, etc.).\n */\nexport enum ConferencingProvider {\n /** Google Meet */\n googleMeet = \"googleMeet\",\n /** Zoom */\n zoom = \"zoom\",\n /** Microsoft Teams */\n microsoftTeams = \"microsoftTeams\",\n /** Cisco Webex */\n webex = \"webex\",\n /** Other or unknown conferencing provider */\n other = \"other\",\n}\n\n/**\n * Represents a clickable link attached to an activity.\n *\n * Activity links are rendered as buttons that enable user interaction with activities.\n * Different link types have specific behaviors and required fields for proper functionality.\n *\n * @example\n * ```typescript\n * // External link - opens URL in browser\n * const externalLink: ActivityLink = {\n * type: ActivityLinkType.external,\n * title: \"Open in Google Calendar\",\n * url: \"https://calendar.google.com/event/123\",\n * };\n *\n * // Conferencing link - opens video conference with provider info\n * const conferencingLink: ActivityLink = {\n * type: ActivityLinkType.conferencing,\n * url: \"https://meet.google.com/abc-defg-hij\",\n * provider: ConferencingProvider.googleMeet,\n * };\n *\n * // Integrations link - initiates OAuth flow\n * const authLink: ActivityLink = {\n * type: ActivityLinkType.auth,\n * title: \"Continue with Google\",\n * provider: AuthProvider.Google,\n * scopes: [\"https://www.googleapis.com/auth/calendar.readonly\"],\n * callback: \"callback-token-for-auth-completion\"\n * };\n *\n * // Callback link - triggers a twist method\n * const callbackLink: ActivityLink = {\n * type: ActivityLinkType.callback,\n * title: \"📅 Primary Calendar\",\n * token: \"callback-token-here\"\n * };\n * ```\n */\nexport type ActivityLink =\n | {\n /** External web link that opens in browser */\n type: ActivityLinkType.external;\n /** Display text for the link button */\n title: string;\n /** URL to open when clicked */\n url: string;\n }\n | {\n /** Video conferencing link with provider-specific handling */\n type: ActivityLinkType.conferencing;\n /** URL to join the conference */\n url: string;\n /** Conferencing provider for UI customization */\n provider: ConferencingProvider;\n }\n | {\n /** Authentication link that initiates an OAuth flow */\n type: ActivityLinkType.auth;\n /** Display text for the auth button */\n title: string;\n /** OAuth provider (e.g., \"google\", \"microsoft\") */\n provider: string;\n /** Array of OAuth scopes to request */\n scopes: string[];\n /** Callback token for auth completion notification */\n callback: Callback;\n }\n | {\n /** Callback link that triggers a twist method when clicked */\n type: ActivityLinkType.callback;\n /** Display text for the callback button */\n title: string;\n /** Token identifying the callback to execute */\n callback: Callback;\n }\n | {\n /** File attachment link stored in R2 */\n type: ActivityLinkType.file;\n /** Unique identifier for the stored file */\n fileId: string;\n /** Original filename */\n fileName: string;\n /** File size in bytes */\n fileSize: number;\n /** MIME type of the file */\n mimeType: string;\n };\n\n/**\n * Represents metadata about an activity, typically from an external system.\n *\n * Activity metadata enables storing additional information about activities,\n * which is useful for synchronization, linking back to external systems,\n * and storing tool-specific data.\n *\n * Must be valid JSON data (strings, numbers, booleans, null, objects, arrays).\n * Functions and other non-JSON values are not supported.\n *\n * @example\n * ```typescript\n * // Calendar event metadata\n * await plot.createActivity({\n * type: ActivityType.Event,\n * title: \"Team Meeting\",\n * start: new Date(\"2024-01-15T10:00:00Z\"),\n * meta: {\n * calendarId: \"primary\",\n * htmlLink: \"https://calendar.google.com/event/abc123\",\n * conferenceData: { ... }\n * }\n * });\n *\n * // Project issue metadata\n * await plot.createActivity({\n * type: ActivityType.Action,\n * title: \"Fix login bug\",\n * meta: {\n * projectId: \"TEAM\",\n * issueNumber: 123,\n * url: \"https://linear.app/team/issue/TEAM-123\"\n * }\n * });\n * ```\n */\nexport type ActivityMeta = {\n /** Source-specific properties and metadata */\n [key: string]: JSONValue;\n};\n\n/**\n * Tags on an item, along with the actors who added each tag.\n */\nexport type Tags = { [K in Tag]?: ActorId[] };\n\n/**\n * A set of tags to add to an item, along with the actors adding each tag.\n */\nexport type NewTags = { [K in Tag]?: NewActor[] };\n\n/**\n * Common fields shared by both Activity and Note entities.\n */\nexport type ActivityCommon = {\n /** Unique identifier for the activity */\n id: Uuid;\n /**\n * When this activity was originally created in its source system.\n *\n * For activities created in Plot, this is when the user created it.\n * For activities synced from external systems (GitHub issues, emails, calendar events),\n * this is the original creation time in that system.\n *\n * Defaults to the current time when creating new activities.\n */\n created: Date;\n /** Information about who created the activity */\n author: Actor;\n /** Whether this activity is private (only visible to author) */\n private: boolean;\n /** Whether this activity has been archived */\n archived: boolean;\n /** Tags attached to this activity. Maps tag ID to array of actor IDs who added that tag. */\n tags: Tags;\n /** Array of actor IDs (users, contacts, or twists) mentioned in this activity via @-mentions */\n mentions: ActorId[];\n};\n\n/**\n * Common fields shared by all activity types (Note, Action, Event).\n * Does not include the discriminant `type` field or type-specific fields like `done`.\n */\ntype ActivityFields = ActivityCommon & {\n /**\n * Globally unique, stable identifier for the item in an external system.\n * MUST use immutable system-generated IDs, not human-readable slugs or titles.\n *\n * Recommended format: `${domain}:${type}:${id}`\n *\n * Examples:\n * - `linear:issue:549dd8bd-2bc9-43d1-95d5-4b4af0c5af1b` (Linear issue by UUID)\n * - `jira:10001:issue:12345` (Jira issue by numeric ID with cloud ID)\n * - `gmail:thread:18d4e5f2a3b1c9d7` (Gmail thread by system ID)\n *\n * ⚠️ AVOID: URLs with mutable components like team names or issue keys\n * - Bad: `https://linear.app/team/issue/TEAM-123/title` (team and title can change)\n * - Bad: `jira:issue:PROJECT-42` (issue key can change)\n *\n * When set, uniquely identifies the activity within a priority tree for upsert operations.\n */\n source: string | null;\n /** The display title/summary of the activity */\n title: string;\n /** Optional kind for additional categorization within the activity */\n kind: ActivityKind | null;\n /**\n * The actor assigned to this activity.\n *\n * **For actions (tasks):**\n * - If not provided (undefined), defaults to the user who installed the twist (twist owner)\n * - To create an **unassigned action**, explicitly set `assignee: null`\n * - For synced tasks from external systems, typically set `assignee: null` for unassigned items\n *\n * **For notes and events:** Assignee is optional and typically null.\n * When marking an activity as done, it becomes an Action; if no assignee is set,\n * the twist owner is assigned automatically.\n *\n * @example\n * ```typescript\n * // Create action assigned to twist owner (default behavior)\n * const task: NewActivity = {\n * type: ActivityType.Action,\n * title: \"Follow up on email\"\n * // assignee omitted → defaults to twist owner\n * };\n *\n * // Create UNASSIGNED action (for backlog items)\n * const backlogTask: NewActivity = {\n * type: ActivityType.Action,\n * title: \"Review PR #123\",\n * assignee: null // Explicitly set to null\n * };\n *\n * // Create action with explicit assignee\n * const assignedTask: NewActivity = {\n * type: ActivityType.Action,\n * title: \"Deploy to production\",\n * assignee: {\n * id: userId as ActorId,\n * type: ActorType.User,\n * name: \"Alice\"\n * }\n * };\n * ```\n */\n assignee: Actor | null;\n /**\n * Start time of a scheduled activity. Notes are not typically scheduled unless they're about specific times.\n * For recurring events, this represents the start of the first occurrence.\n * Can be a Date object for timed events or a date string in \"YYYY-MM-DD\" format for all-day events.\n *\n * **Activity Scheduling States** (for Actions):\n * - **Do Now** (current/actionable): When creating an Action, omitting `start` defaults to current time\n * - **Do Later** (future scheduled): Set `start` to a future Date or date string\n * - **Do Someday** (unscheduled backlog): Explicitly set `start: null`\n *\n * **Important for synced tasks**: When syncing unassigned backlog items from external systems,\n * set BOTH `start: null` AND `assignee: null` to create unscheduled, unassigned actions.\n *\n * @example\n * ```typescript\n * // \"Do Now\" - assigned to twist owner, actionable immediately\n * await this.tools.plot.createActivity({\n * type: ActivityType.Action,\n * title: \"Urgent task\"\n * // start omitted → defaults to now\n * // assignee omitted → defaults to twist owner\n * });\n *\n * // \"Do Later\" - scheduled for a specific time\n * await this.tools.plot.createActivity({\n * type: ActivityType.Action,\n * title: \"Future task\",\n * start: new Date(\"2025-02-01\")\n * });\n *\n * // \"Do Someday\" - unassigned backlog item (common for synced tasks)\n * await this.tools.plot.createActivity({\n * type: ActivityType.Action,\n * title: \"Backlog task\",\n * start: null, // Explicitly unscheduled\n * assignee: null // Explicitly unassigned\n * });\n * ```\n */\n start: Date | string | null;\n /**\n * End time of a scheduled activity. Notes are not typically scheduled unless they're about specific times.\n * For recurring events, this represents the end of the first occurrence.\n * Can be a Date object for timed events or a date string in \"YYYY-MM-DD\" format for all-day events.\n * Null for tasks or activities without defined end times.\n */\n end: Date | string | null;\n /**\n * For recurring activities, the last occurrence date (inclusive).\n * Can be a Date object, date string in \"YYYY-MM-DD\" format, or null if recurring indefinitely.\n * When both recurrenceCount and recurrenceUntil are provided, recurrenceCount takes precedence.\n */\n recurrenceUntil: Date | string | null;\n /**\n * For recurring activities, the number of occurrences to generate.\n * Takes precedence over recurrenceUntil if both are provided.\n * Null for non-recurring activities or indefinite recurrence.\n */\n recurrenceCount: number | null;\n /** The priority context this activity belongs to */\n priority: Priority;\n /** Recurrence rule in RFC 5545 RRULE format (e.g., \"FREQ=WEEKLY;BYDAY=MO,WE,FR\") */\n recurrenceRule: string | null;\n /** Array of dates to exclude from the recurrence pattern */\n recurrenceExdates: Date[] | null;\n /** Metadata about the activity, typically from an external system that created it */\n meta: ActivityMeta | null;\n /** Sort order for the activity (fractional positioning) */\n order: number;\n};\n\nexport type Activity = ActivityFields &\n (\n | { type: ActivityType.Note }\n | {\n type: ActivityType.Action;\n /**\n * Timestamp when the activity was marked as complete. Null if not completed.\n */\n done: Date | null;\n }\n | { type: ActivityType.Event }\n );\n\nexport type ActivityWithNotes = Activity & {\n notes: Note[];\n};\n\nexport type NewActivityWithNotes = NewActivity & {\n notes: Omit<NewNote, \"activity\">[];\n};\n\n/**\n * Represents a specific instance of a recurring activity.\n * All field values are computed by merging the recurring activity's\n * defaults with any occurrence-specific overrides.\n */\nexport type ActivityOccurrence = {\n /**\n * Original date/datetime of this occurrence.\n * Use start for the occurrence's current start time.\n * Format: Date object or \"YYYY-MM-DD\" for all-day events.\n */\n occurrence: Date | string;\n\n /**\n * The recurring activity of which this is an occurrence.\n */\n activity: Activity;\n\n /**\n * Effective values for this occurrence (series defaults + overrides).\n * These are the actual values that apply to this specific instance.\n */\n start: Date | string;\n end: Date | string | null;\n done: Date | null;\n title: string;\n /**\n * Meta is merged, with the occurrence's meta taking precedence.\n */\n meta: ActivityMeta | null;\n\n /**\n * Tags for this occurrence (merged with the recurring tags).\n */\n tags: Tags;\n\n /**\n * True if the occurrence is archived.\n */\n archived: boolean;\n};\n\n/**\n * Type for creating or updating activity occurrences.\n *\n * Follows the same pattern as Activity/NewActivity:\n * - Required fields: `occurrence` (key) and `start` (for scheduling)\n * - Optional fields: All others from ActivityOccurrence\n * - Additional fields: `twistTags` for add/remove, `unread` for notification control\n *\n * @example\n * ```typescript\n * const activity: NewActivity = {\n * type: ActivityType.Event,\n * recurrenceRule: \"FREQ=WEEKLY;BYDAY=MO\",\n * occurrences: [\n * {\n * occurrence: new Date(\"2025-01-27T14:00:00Z\"),\n * start: new Date(\"2025-01-27T14:00:00Z\"),\n * tags: { [Tag.Skip]: [user] }\n * }\n * ]\n * };\n * ```\n */\nexport type NewActivityOccurrence = Pick<\n ActivityOccurrence,\n \"occurrence\" | \"start\"\n> &\n Partial<\n Omit<ActivityOccurrence, \"occurrence\" | \"start\" | \"activity\" | \"tags\">\n > & {\n /**\n * Tags specific to this occurrence.\n * These replace any recurrence-level tags for this occurrence.\n */\n tags?: NewTags;\n\n /**\n * Add or remove the twist's tags on this occurrence.\n * Maps tag ID to boolean: true = add tag, false = remove tag.\n */\n twistTags?: Partial<Record<Tag, boolean>>;\n\n /**\n * Whether this occurrence should be marked as unread for users.\n * - undefined/omitted (default): Occurrence is unread for users, except auto-marked\n * as read for the author if they are the twist owner (user)\n * - true: Occurrence is explicitly unread for ALL users (use sparingly)\n * - false: Occurrence is marked as read for all users\n *\n * For the default behavior, omit this field entirely.\n * Use false for initial sync to avoid marking historical items as unread.\n */\n unread?: boolean;\n };\n\n/**\n * Inline type for creating/updating occurrences within NewActivity/ActivityUpdate.\n * Used to specify occurrence-specific overrides when creating or updating a recurring activity.\n */\nexport type ActivityOccurrenceUpdate = Pick<\n NewActivityOccurrence,\n \"occurrence\"\n> &\n Partial<Omit<NewActivityOccurrence, \"occurrence\" | \"activity\">>;\n\n/**\n * Configuration for automatic priority selection based on activity similarity.\n *\n * Maps activity fields to scoring weights or required exact matches:\n * - Number value: Maximum score for similarity matching on this field\n * - `true` value: Required exact match - activities must match exactly or be excluded\n *\n * Scoring rules:\n * - content: Uses vector similarity on activity embedding (cosine similarity)\n * - type: Exact match on ActivityType\n * - mentions: Percentage of existing activity's mentions that appear in new activity\n * - meta.field: Exact match on top-level meta fields (e.g., \"meta.sourceId\")\n *\n * When content is `true`, applies a strong similarity threshold to ensure only close matches.\n * Default (when neither priority nor pickPriority specified): `{content: true}`\n *\n * @example\n * ```typescript\n * // Require exact content match with strong similarity\n * pickPriority: { content: true }\n *\n * // Score based on content (max 100 points) and require exact type match\n * pickPriority: { content: 100, type: true }\n *\n * // Match on meta and score content\n * pickPriority: { \"meta.projectId\": true, content: 50 }\n * ```\n */\nexport type PickPriorityConfig = {\n content?: number | true;\n type?: number | true;\n mentions?: number | true;\n [key: `meta.${string}`]: number | true;\n};\n\n/**\n * Type for creating new activities.\n *\n * Requires only the activity type, with all other fields optional.\n * The author will be automatically assigned by the Plot system based on\n * the current execution context. The ID can be optionally provided by\n * tools for tracking and update detection purposes.\n *\n * **Important: Defaults for Actions**\n *\n * When creating an Activity of type `Action`:\n * - **`start` omitted** → Defaults to current time (now) → \"Do Now\"\n * - **`assignee` omitted** → Defaults to twist owner → Assigned action\n *\n * To create unassigned backlog items (common for synced tasks), you MUST explicitly set BOTH:\n * - `start: null` → \"Do Someday\" (unscheduled)\n * - `assignee: null` → Unassigned\n *\n * **Scheduling States**:\n * - **\"Do Now\"** (actionable today): Omit `start` or set to current time\n * - **\"Do Later\"** (scheduled): Set `start` to a future Date\n * - **\"Do Someday\"** (backlog): Set `start: null`\n *\n * Priority can be specified in three ways:\n * 1. Explicit priority: `priority: { id: \"...\" }` - Use specific priority (disables pickPriority)\n * 2. Pick priority config: `pickPriority: { ... }` - Auto-select based on similarity\n * 3. Neither: Defaults to `pickPriority: { content: true }` for automatic matching\n *\n * @example\n * ```typescript\n * // \"Do Now\" - Assigned to twist owner, actionable immediately\n * const urgentTask: NewActivity = {\n * type: ActivityType.Action,\n * title: \"Review pull request\"\n * // start omitted → defaults to now\n * // assignee omitted → defaults to twist owner\n * };\n *\n * // \"Do Someday\" - UNASSIGNED backlog item (for synced tasks)\n * const backlogTask: NewActivity = {\n * type: ActivityType.Action,\n * title: \"Refactor user service\",\n * start: null, // Must explicitly set to null\n * assignee: null // Must explicitly set to null\n * };\n *\n * // \"Do Later\" - Scheduled for specific date\n * const futureTask: NewActivity = {\n * type: ActivityType.Action,\n * title: \"Prepare Q1 review\",\n * start: new Date(\"2025-03-15\")\n * };\n *\n * // Note (typically unscheduled)\n * const note: NewActivity = {\n * type: ActivityType.Note,\n * title: \"Meeting notes\",\n * content: \"Discussed Q4 roadmap...\",\n * start: null // Notes typically don't have scheduled times\n * };\n *\n * // Event (always has explicit start/end times)\n * const event: NewActivity = {\n * type: ActivityType.Event,\n * title: \"Team standup\",\n * start: new Date(\"2025-01-15T10:00:00\"),\n * end: new Date(\"2025-01-15T10:30:00\")\n * };\n * ```\n */\nexport type NewActivity = (\n | { type: ActivityType.Note; done?: never }\n | { type: ActivityType.Action; done?: Date | null }\n | { type: ActivityType.Event; done?: never }\n) &\n Partial<\n Omit<\n ActivityFields,\n \"author\" | \"assignee\" | \"priority\" | \"tags\" | \"mentions\" | \"id\" | \"source\"\n >\n > &\n (\n | {\n /**\n * Unique identifier for the activity, generated by Uuid.Generate().\n * Specifying an ID allows tools to track and upsert activities.\n */\n id: Uuid;\n }\n | {\n /**\n * Canonical URL for the item in an external system.\n * For example, https://acme.atlassian.net/browse/PROJ-42 could represent a Jira issue.\n * When set, it uniquely identifies the activity within a priority tree. This performs\n * an upsert.\n */\n source: string;\n }\n | {\n /* Neither id nor source is required. An id will be generated and returned. */\n }\n ) &\n (\n | {\n /** Explicit priority (required when specified) - disables automatic priority matching */\n priority: Pick<Priority, \"id\">;\n }\n | {\n /** Configuration for automatic priority selection based on similarity */\n pickPriority?: PickPriorityConfig;\n }\n ) & {\n /**\n * The person that created the item. By default, it will be the twist itself.\n */\n author?: NewActor;\n\n /**\n * The person that assigned to the item.\n */\n assignee?: NewActor | null;\n\n /**\n * All tags to set on the new activity.\n */\n tags?: NewTags;\n\n /**\n * Whether the activity should be marked as unread for users.\n * - undefined/omitted (default): Activity is unread for users, except auto-marked\n * as read for the author if they are the twist owner (user)\n * - true: Activity is explicitly unread for ALL users (use sparingly)\n * - false: Activity is marked as read for all users in the priority at creation time\n *\n * For the default behavior, omit this field entirely.\n * Use false for initial sync to avoid marking historical items as unread.\n */\n unread?: boolean;\n\n /**\n * Whether the activity is archived.\n * - true: Archive the activity\n * - false: Unarchive the activity\n * - undefined (default): Preserve current archive state\n *\n * Best practice: Set to false during initial syncs to ensure activities\n * are unarchived. Omit during incremental syncs to preserve user's choice.\n */\n archived?: boolean;\n\n /**\n * Optional preview content for the activity. Can be Markdown formatted.\n * The preview will be automatically generated from this content (truncated to 100 chars).\n *\n * - string: Use this content for preview generation\n * - null: Explicitly disable preview (no preview will be shown)\n * - undefined (default): Fall back to legacy behavior (generate from first note with content)\n *\n * This field is write-only and won't be returned when reading activities.\n */\n preview?: string | null;\n\n /**\n * Create or update specific occurrences of a recurring activity.\n * Each entry specifies overrides for a specific occurrence.\n *\n * When occurrence matches the recurrence rule but only tags are specified,\n * the occurrence is created with just tags in activity_tag.occurrence (no activity_exception).\n *\n * When any other field is specified, creates/updates an activity_exception row.\n *\n * @example\n * ```typescript\n * // Create recurring event with per-occurrence RSVPs\n * const meeting: NewActivity = {\n * type: ActivityType.Event,\n * recurrenceRule: \"FREQ=WEEKLY;BYDAY=MO\",\n * start: new Date(\"2025-01-20T14:00:00Z\"),\n * duration: 1800000, // 30 minutes\n * occurrences: [\n * {\n * occurrence: new Date(\"2025-01-27T14:00:00Z\"),\n * tags: { [Tag.Skip]: [{ email: \"user@example.com\" }] }\n * },\n * {\n * occurrence: new Date(\"2025-02-03T14:00:00Z\"),\n * start: new Date(\"2025-02-03T15:00:00Z\"), // Reschedule this one\n * tags: { [Tag.Attend]: [{ email: \"user@example.com\" }] }\n * }\n * ]\n * };\n * ```\n */\n occurrences?: NewActivityOccurrence[];\n\n /**\n * Dates to add to the recurrence exclusion list.\n * These are merged with existing exdates. Use this for incremental updates\n * (e.g., cancelling a single occurrence) instead of replacing the full list.\n */\n addRecurrenceExdates?: Date[];\n\n /**\n * Dates to remove from the recurrence exclusion list.\n * Use this to \"uncancel\" a previously excluded occurrence.\n */\n removeRecurrenceExdates?: Date[];\n };\n\nexport type ActivityFilter = {\n type?: ActorType;\n meta?: {\n [key: string]: JSONValue;\n };\n};\n\n/**\n * Fields supported by bulk updates via `match`. Only simple scalar fields\n * that can be applied uniformly across many activities are included.\n */\ntype ActivityBulkUpdateFields = Partial<\n Pick<ActivityFields, \"kind\" | \"title\" | \"private\" | \"archived\" | \"meta\" | \"order\">\n> & {\n /** Update the type of all matching activities. */\n type?: ActivityType;\n /**\n * Timestamp when the activities were marked as complete. Null to clear.\n * Setting done will automatically set the type to Action if not already.\n */\n done?: Date | null;\n};\n\n/**\n * Fields supported by single-activity updates via `id` or `source`.\n * Includes all bulk fields plus scheduling, recurrence, tags, and occurrences.\n */\ntype ActivitySingleUpdateFields = ActivityBulkUpdateFields &\n Partial<\n Pick<\n ActivityFields,\n | \"start\"\n | \"end\"\n | \"assignee\"\n | \"recurrenceRule\"\n | \"recurrenceExdates\"\n | \"recurrenceUntil\"\n | \"recurrenceCount\"\n >\n > & {\n /**\n * Tags to change on the activity. Use an empty array of NewActor to remove a tag.\n * Use twistTags to add/remove the twist from tags to avoid clearing other actors' tags.\n */\n tags?: NewTags;\n\n /**\n * Add or remove the twist's tags.\n * Maps tag ID to boolean: true = add tag, false = remove tag.\n * This is allowed on all activities the twist has access to.\n */\n twistTags?: Partial<Record<Tag, boolean>>;\n\n /**\n * Optional preview content for the activity. Can be Markdown formatted.\n * The preview will be automatically generated from this content (truncated to 100 chars).\n *\n * - string: Use this content for preview generation\n * - null: Explicitly disable preview (no preview will be shown)\n * - undefined (omitted): Preserve current preview value\n *\n * This field is write-only and won't be returned when reading activities.\n */\n preview?: string | null;\n\n /**\n * Create or update specific occurrences of this recurring activity.\n * Each entry specifies overrides for a specific occurrence.\n *\n * Setting a field to null reverts it to the series default.\n * Omitting a field leaves it unchanged.\n *\n * @example\n * ```typescript\n * // Update RSVPs for specific occurrences\n * await plot.updateActivity({\n * id: meetingId,\n * occurrences: [\n * {\n * occurrence: new Date(\"2025-01-27T14:00:00Z\"),\n * tags: { [Tag.Skip]: [user] }\n * },\n * {\n * occurrence: new Date(\"2025-02-03T14:00:00Z\"),\n * tags: { [Tag.Attend]: [user] }\n * },\n * {\n * occurrence: new Date(\"2025-02-10T14:00:00Z\"),\n * archived: true // Cancel this occurrence\n * }\n * ]\n * });\n * ```\n */\n occurrences?: (NewActivityOccurrence | ActivityOccurrenceUpdate)[];\n\n /**\n * Dates to add to the recurrence exclusion list.\n * These are merged with existing exdates. Use this for incremental updates\n * (e.g., cancelling a single occurrence) instead of replacing the full list.\n */\n addRecurrenceExdates?: Date[];\n\n /**\n * Dates to remove from the recurrence exclusion list.\n * Use this to \"uncancel\" a previously excluded occurrence.\n */\n removeRecurrenceExdates?: Date[];\n };\n\nexport type ActivityUpdate =\n | (({ id: Uuid } | { source: string }) & ActivitySingleUpdateFields)\n | ({\n /**\n * Update all activities matching the specified criteria. Only activities\n * that match all provided fields and were created by the twist will be updated.\n */\n match: ActivityFilter;\n } & ActivityBulkUpdateFields);\n\n/**\n * Represents a note within an activity.\n *\n * Notes contain the detailed content (note text, links) associated with an activity.\n * They are always ordered by creation time within their parent activity.\n */\nexport type Note = ActivityCommon & {\n /**\n * Globally unique, stable identifier for the note within its activity.\n * Can be used to upsert without knowing the id.\n *\n * Use one of these patterns:\n * - Hardcoded semantic keys for fixed note types: \"description\", \"cancellation\"\n * - External service IDs for dynamic collections: `comment:${immutableId}`\n *\n * Examples:\n * - `\"description\"` (for a Jira issue's description note)\n * - `\"comment:12345\"` (for a specific comment by ID)\n * - `\"gmail:msg:18d4e5f2a3b1c9d7\"` (for a Gmail message within a thread)\n *\n * ⚠️ Ensure IDs are immutable - avoid human-readable slugs or titles.\n */\n key: string | null;\n /** The parent activity this note belongs to */\n activity: Activity;\n /** Primary content for the note (markdown) */\n content: string | null;\n /** Array of interactive links attached to the note */\n links: Array<ActivityLink> | null;\n /** The note this is a reply to, or null if not a reply */\n reNote: { id: Uuid } | null;\n};\n\n/**\n * Type for creating new notes.\n *\n * Requires the activity reference, with all other fields optional.\n * Can provide id, key, or neither for note identification:\n * - id: Provide a specific UUID for the note\n * - key: Provide an external identifier for upsert within the activity\n * - neither: A new note with auto-generated UUID will be created\n */\nexport type NewNote = Partial<\n Omit<\n Note,\n \"author\" | \"activity\" | \"tags\" | \"mentions\" | \"id\" | \"key\" | \"reNote\"\n >\n> &\n ({ id: Uuid } | { key: string } | {}) & {\n /** Reference to the parent activity (required) */\n activity:\n | Pick<Activity, \"id\">\n | {\n source: string;\n };\n\n /**\n * The person that created the item, or leave undefined to use the twist as author.\n */\n author?: NewActor;\n\n /**\n * Format of the note content. Determines how the note is processed:\n * - 'text': Plain text that will be converted to markdown (auto-links URLs, preserves line breaks)\n * - 'markdown': Already in markdown format (default, no conversion)\n * - 'html': HTML content that will be converted to markdown\n */\n contentType?: ContentType;\n\n /**\n * Tags to change on the activity. Use an empty array of NewActor to remove a tag.\n * Use twistTags to add/remove the twist from tags to avoid clearing other actors' tags.\n */\n tags?: NewTags;\n\n /**\n * Change the mentions on the note.\n */\n mentions?: NewActor[];\n\n /**\n * Whether the note should mark the parent activity as unread for users.\n * - undefined/omitted (default): Activity is unread for users, except auto-marked\n * as read for the author if they are the twist owner (user)\n * - true: Activity is explicitly unread for ALL users (use sparingly)\n * - false: Activity is marked as read for all users in the priority at note creation time\n *\n * For the default behavior, omit this field entirely.\n * Use false for initial sync to avoid marking historical items as unread.\n */\n unread?: boolean;\n\n /**\n * Reference to a parent note this note is a reply to.\n * - `{ id }`: reply by UUID\n * - `{ key }`: reply by key, resolved after creation (for batch ops)\n * - `null`: explicitly not a reply\n * - `undefined` (omitted): not a reply\n */\n reNote?: { id: Uuid } | { key: string } | null;\n };\n\n/**\n * Type for updating existing notes.\n * Must provide either id or key to identify the note to update.\n */\nexport type NoteUpdate = ({ id: Uuid; key?: string } | { key: string }) &\n Partial<\n Pick<Note, \"private\" | \"archived\" | \"content\" | \"links\" | \"reNote\">\n > & {\n /**\n * Format of the note content. Determines how the note is processed:\n * - 'text': Plain text that will be converted to markdown (auto-links URLs, preserves line breaks)\n * - 'markdown': Already in markdown format (default, no conversion)\n * - 'html': HTML content that will be converted to markdown\n */\n contentType?: ContentType;\n\n /**\n * Tags to change on the note. Use an empty array of NewActor to remove a tag.\n * Use twistTags to add/remove the twist from tags to avoid clearing other actors' tags.\n */\n tags?: NewTags;\n\n /**\n * Add or remove the twist's tags.\n * Maps tag ID to boolean: true = add tag, false = remove tag.\n * This is allowed on all notes the twist has access to.\n */\n twistTags?: Partial<Record<Tag, boolean>>;\n\n /**\n * Change the mentions on the note.\n */\n mentions?: NewActor[];\n };\n\n/**\n * Represents an actor in Plot - a user, contact, or twist.\n *\n * Actors can be associated with activities as authors, assignees, or mentions.\n * The email field is only included when ContactAccess.Read permission is granted.\n *\n * @example\n * ```typescript\n * const actor: Actor = {\n * id: \"f0ffd5f8-1635-4b13-9532-35f97446db90\" as ActorId,\n * type: ActorType.Contact,\n * email: \"john.doe@example.com\", // Only if ContactAccess.Read\n * name: \"John Doe\"\n * };\n * ```\n */\nexport type Actor = {\n /** Unique identifier for the actor */\n id: ActorId;\n /** Type of actor (User, Contact, or Twist) */\n type: ActorType;\n /**\n * Email address (only included with ContactAccess.Read permission).\n * - `undefined`: No permission to read email\n * - `null`: Permission granted but email not set\n * - `string`: Email address\n */\n email?: string | null;\n /**\n * Display name.\n * - `undefined`: Not included due to permissions\n * - `null`: Not set\n * - `string`: Display name\n */\n name?: string | null;\n};\n\n/**\n * An existing or new contact.\n */\nexport type NewActor =\n | {\n /** Unique identifier for the actor */\n id: ActorId;\n }\n | NewContact;\n\n/**\n * Enumeration of author types that can create activities.\n *\n * The author type affects how activities are displayed and processed\n * within the Plot system.\n */\nexport enum ActorType {\n /** Activities created by human users */\n User,\n /** Activities created by external contacts */\n Contact,\n /** Activities created by automated twists */\n Twist,\n}\n\n/**\n * Represents contact information for creating a new contact.\n *\n * Contacts are used throughout Plot for representing people associated\n * with activities, such as event attendees or task assignees.\n *\n * @example\n * ```typescript\n * const newContact: NewContact = {\n * email: \"john.doe@example.com\",\n * name: \"John Doe\",\n * avatar: \"https://avatar.example.com/john.jpg\"\n * };\n * ```\n */\nexport type NewContact = {\n /** Email address of the contact (required) */\n email: string;\n /** Optional display name for the contact */\n name?: string;\n /** Optional avatar image URL for the contact */\n avatar?: string;\n /**\n * External provider account source. Used for privacy compliance\n * (e.g. Atlassian personal data reporting for GDPR account closure).\n * Required for contacts sourced from providers that mandate personal data reporting.\n */\n source?: { provider: AuthProvider; accountId: string };\n};\n\nexport type ContentType = \"text\" | \"markdown\" | \"html\";\n";
7
+ export default "import type { NewSchedule, NewScheduleOccurrence, Schedule } from \"./schedule\";\nimport { type Tag } from \"./tag\";\nimport { type Callback } from \"./tools/callbacks\";\nimport { type AuthProvider } from \"./tools/integrations\";\nimport { type JSONValue } from \"./utils/types\";\nimport { Uuid } from \"./utils/uuid\";\n\nexport { Tag } from \"./tag\";\nexport { Uuid } from \"./utils/uuid\";\nexport { type JSONValue } from \"./utils/types\";\nexport { type AuthProvider } from \"./tools/integrations\";\n\n/**\n * @fileoverview\n * Core Plot entity types for working with threads, notes, priorities, and contacts.\n *\n * ## Type Pattern: Null vs Undefined Semantics\n *\n * Plot entity types use a consistent pattern to distinguish between missing, unset, and explicitly cleared values:\n *\n * ### Entity Types (Thread, Priority, Note, Actor)\n * - **Required fields**: No `?`, cannot be `undefined`\n * - Example: `id: Uuid`, `title: string`\n * - **Nullable fields**: Use `| null` to allow explicit clearing\n * - Example: `assignee: ActorId | null`, `done: Date | null`\n * - `null` = field is explicitly unset/cleared\n * - Non-null value = field has a value\n * - **Optional nullable fields**: Use `?` with `| null` for permission-based access\n * - Example: `email?: string | null`, `name?: string | null`\n * - `undefined` = field not included (e.g., no permission to access)\n * - `null` = field included but not set\n * - Value = field has a value\n *\n * ### New* Types (NewThread, NewNote, NewPriority)\n * Used for creating or updating entities. Support partial updates by distinguishing omitted vs cleared fields:\n * - **Required fields**: Must be provided (no `?`)\n * - Example: `title: string` in NewPriority\n * - **Optional fields**: Use `?` to make them optional\n * - Example: `title?: string`, `author?: NewActor`\n * - `undefined` (omitted) = don't set/update this field\n * - Provided value = set/update this field\n * - **Optional nullable fields**: Use `?` with `| null` to support clearing\n * - Example: `assignee?: NewActor | null`\n * - `undefined` (omitted) = don't change assignee\n * - `null` = clear the assignee\n * - NewActor = set/update the assignee\n *\n * This pattern allows API consumers to:\n * 1. Omit fields they don't want to change (undefined)\n * 2. Explicitly clear fields by setting to null\n * 3. Set or update fields by providing values\n *\n * @example\n * ```typescript\n * // Creating a new thread\n * const newThread: NewThread = {\n * title: \"Review pull request\",\n * };\n *\n * // Updating a thread - only change what's specified\n * const update: ThreadUpdate = {\n * id: threadId,\n * archived: true,\n * };\n * ```\n */\n\n/**\n * Represents a unique user, contact, or twist in Plot.\n *\n * ActorIds are used throughout Plot for:\n * - Activity authors and assignees\n * - Tag creators (actor_id in activity_tag/note_tag)\n * - Mentions in activities and notes\n * - Any entity that can perform actions in Plot\n */\nexport type ActorId = string & { readonly __brand: \"ActorId\" };\n\n/**\n * Theme colors for priorities.\n */\nexport enum ThemeColor {\n /** Catalyst - Green */\n Catalyst = 0,\n /** Call to Adventure - Blue */\n CallToAdventure = 1,\n /** Rising Action - Purple */\n RisingAction = 2,\n /** Momentum - Pink-Purple */\n Momentum = 3,\n /** Turning Point - Pink */\n TurningPoint = 4,\n /** Breakthrough - Orange */\n Breakthrough = 5,\n /** Climax - Olive */\n Climax = 6,\n /** Resolution - Blue-Gray */\n Resolution = 7,\n}\n\n/**\n * Represents a priority context within Plot.\n *\n * Priorities are similar to projects in other apps. All Activity is in a Priority.\n * Priorities can be nested.\n */\nexport type Priority = {\n /** Unique identifier for the priority */\n id: Uuid;\n /** Human-readable title for the priority */\n title: string;\n /** Whether this priority has been archived */\n archived: boolean;\n /**\n * Optional key for referencing this priority.\n * Keys are unique per priority tree (a user's personal priorities or the root of a shared priority).\n */\n key: string | null;\n /** Optional theme color for the priority (0-7). If not set, inherits from parent or defaults to 7 (Resolution). */\n color: ThemeColor | null;\n};\n\n/**\n * Type for creating new priorities.\n *\n * Supports multiple creation patterns:\n * - Provide a specific UUID for the priority\n * - Provide a key for upsert within the user's priorities\n * - Omit both to auto-generate a new UUID\n *\n * Optionally specify a parent priority by ID or key for hierarchical structures.\n */\nexport type NewPriority = Pick<Priority, \"title\"> &\n Partial<Omit<Priority, \"id\" | \"title\">> &\n (\n | {\n /**\n * Unique identifier for the priority, generated by Uuid.Generate().\n * Specifying an ID allows tools to track and upsert priorities.\n */\n id: Uuid;\n }\n | {\n /**\n * Unique key for the priority within the user's priorities.\n * Can be used to upsert without knowing the UUID.\n * For example, \"@plot\" identifies the Plot priority.\n */\n key: string;\n }\n | {\n /* Neither id nor key is required. An id will be generated and returned. */\n }\n ) & {\n /** Add the new priority as the child of another priority */\n parent?: { id: Uuid } | { key: string };\n };\n\n/**\n * Type for updating existing priorities.\n * Must provide either id or key to identify the priority to update.\n */\nexport type PriorityUpdate = ({ id: Uuid } | { key: string }) &\n Partial<Pick<Priority, \"title\" | \"archived\">>;\n\n/**\n * Enumeration of supported action types.\n *\n * Different action types have different behaviors when clicked by users\n * and may require different rendering approaches.\n */\nexport enum ActionType {\n /** External web links that open in browser */\n external = \"external\",\n /** Authentication flows for connecting services */\n auth = \"auth\",\n /** Callback actions that trigger twist methods when clicked */\n callback = \"callback\",\n /** Video conferencing links with provider-specific handling */\n conferencing = \"conferencing\",\n /** File attachment links stored in R2 */\n file = \"file\",\n /** Thread reference links for navigating to related threads */\n thread = \"thread\",\n}\n\n/**\n * Video conferencing providers for conferencing links.\n *\n * Used to identify the conferencing platform and provide\n * provider-specific UI elements (titles, icons, etc.).\n */\nexport enum ConferencingProvider {\n /** Google Meet */\n googleMeet = \"googleMeet\",\n /** Zoom */\n zoom = \"zoom\",\n /** Microsoft Teams */\n microsoftTeams = \"microsoftTeams\",\n /** Cisco Webex */\n webex = \"webex\",\n /** Other or unknown conferencing provider */\n other = \"other\",\n}\n\n/**\n * Represents a clickable action attached to a thread.\n *\n * Thread actions are rendered as buttons that enable user interaction with threads.\n * Different action types have specific behaviors and required fields for proper functionality.\n *\n * @example\n * ```typescript\n * // External action - opens URL in browser\n * const externalAction: Action = {\n * type: ActionType.external,\n * title: \"Open in Google Calendar\",\n * url: \"https://calendar.google.com/event/123\",\n * };\n *\n * // Conferencing action - opens video conference with provider info\n * const conferencingAction: Action = {\n * type: ActionType.conferencing,\n * url: \"https://meet.google.com/abc-defg-hij\",\n * provider: ConferencingProvider.googleMeet,\n * };\n *\n * // Integrations action - initiates OAuth flow\n * const authAction: Action = {\n * type: ActionType.auth,\n * title: \"Continue with Google\",\n * provider: AuthProvider.Google,\n * scopes: [\"https://www.googleapis.com/auth/calendar.readonly\"],\n * callback: \"callback-token-for-auth-completion\"\n * };\n *\n * // Callback action - triggers a twist method\n * const callbackAction: Action = {\n * type: ActionType.callback,\n * title: \"📅 Primary Calendar\",\n * token: \"callback-token-here\"\n * };\n * ```\n */\nexport type Action =\n | {\n /** External web link that opens in browser */\n type: ActionType.external;\n /** Display text for the action button */\n title: string;\n /** URL to open when clicked */\n url: string;\n }\n | {\n /** Video conferencing action with provider-specific handling */\n type: ActionType.conferencing;\n /** URL to join the conference */\n url: string;\n /** Conferencing provider for UI customization */\n provider: ConferencingProvider;\n }\n | {\n /** Authentication action that initiates an OAuth flow */\n type: ActionType.auth;\n /** Display text for the auth button */\n title: string;\n /** OAuth provider (e.g., \"google\", \"microsoft\") */\n provider: string;\n /** Array of OAuth scopes to request */\n scopes: string[];\n /** Callback token for auth completion notification */\n callback: Callback;\n }\n | {\n /** Callback action that triggers a twist method when clicked */\n type: ActionType.callback;\n /** Display text for the callback button */\n title: string;\n /** Token identifying the callback to execute */\n callback: Callback;\n }\n | {\n /** File attachment action stored in R2 */\n type: ActionType.file;\n /** Unique identifier for the stored file */\n fileId: string;\n /** Original filename */\n fileName: string;\n /** File size in bytes */\n fileSize: number;\n /** MIME type of the file */\n mimeType: string;\n }\n | {\n /** Thread reference action for navigating to a related thread */\n type: ActionType.thread;\n /** UUID of the referenced thread */\n threadId: Uuid;\n };\n\n/**\n * Represents metadata about a thread, typically from an external system.\n *\n * Thread metadata enables storing additional information about threads,\n * which is useful for synchronization, linking back to external systems,\n * and storing tool-specific data.\n *\n * Must be valid JSON data (strings, numbers, booleans, null, objects, arrays).\n * Functions and other non-JSON values are not supported.\n *\n * @example\n * ```typescript\n * // Calendar event metadata\n * await plot.createThread({\n * title: \"Team Meeting\",\n * meta: {\n * calendarId: \"primary\",\n * htmlLink: \"https://calendar.google.com/event/abc123\",\n * conferenceData: { ... }\n * }\n * });\n *\n * // Project issue metadata\n * await plot.createThread({\n * title: \"Fix login bug\",\n * meta: {\n * projectId: \"TEAM\",\n * issueNumber: 123,\n * url: \"https://linear.app/team/issue/TEAM-123\"\n * }\n * });\n * ```\n */\nexport type ThreadMeta = {\n /** Source-specific properties and metadata */\n [key: string]: JSONValue;\n};\n\n/**\n * Tags on an item, along with the actors who added each tag.\n */\nexport type Tags = { [K in Tag]?: ActorId[] };\n\n/**\n * A set of tags to add to an item, along with the actors adding each tag.\n */\nexport type NewTags = { [K in Tag]?: NewActor[] };\n\n/**\n * Common fields shared by both Thread and Note entities.\n */\nexport type ThreadCommon = {\n /** Unique identifier for the thread */\n id: Uuid;\n /**\n * When this item was created.\n *\n * **For sources:** Set this to the external system's timestamp (e.g., email\n * sent date, comment creation date), NOT the sync time. If omitted, defaults\n * to the current time, which is almost never correct for synced data.\n */\n created: Date;\n /** Whether this thread is private (only visible to creator) */\n private: boolean;\n /** Whether this thread has been archived */\n archived: boolean;\n /** Tags attached to this thread. Maps tag ID to array of actor IDs who added that tag. */\n tags: Tags;\n /** Array of actor IDs (users, contacts, or twists) mentioned in this thread via @-mentions */\n mentions: ActorId[];\n};\n\n/**\n * Fields on a Thread entity.\n * Threads are simple containers for links and notes.\n */\ntype ThreadFields = ThreadCommon & {\n /** The display title/summary of the thread */\n title: string;\n /** The priority context this thread belongs to */\n priority: Priority;\n /** The schedule associated with this thread, if any */\n schedule?: Schedule;\n /** Source-specific metadata from the thread's link, populated on callbacks */\n meta?: ThreadMeta;\n};\n\nexport type Thread = ThreadFields;\n\nexport type ThreadWithNotes = Thread & {\n notes: Note[];\n};\n\nexport type NewThreadWithNotes = NewThread & {\n notes: Omit<NewNote, \"thread\">[];\n};\n\n/**\n * Configuration for automatic priority selection based on thread similarity.\n *\n * Maps thread fields to scoring weights or required exact matches:\n * - Number value: Maximum score for similarity matching on this field\n * - `true` value: Required exact match - threads must match exactly or be excluded\n *\n * Scoring rules:\n * - content: Uses vector similarity on thread embedding (cosine similarity)\n * - mentions: Percentage of existing thread's mentions that appear in new thread\n * - meta.field: Exact match on top-level meta fields (e.g., \"meta.sourceId\")\n *\n * When content is `true`, applies a strong similarity threshold to ensure only close matches.\n * Default (when neither priority nor pickPriority specified): `{content: true}`\n *\n * @example\n * ```typescript\n * // Require exact content match with strong similarity\n * pickPriority: { content: true }\n *\n * // Score based on content (max 100 points) and mentions\n * pickPriority: { content: 100, mentions: true }\n *\n * // Match on meta and score content\n * pickPriority: { \"meta.projectId\": true, content: 50 }\n * ```\n */\nexport type PickPriorityConfig = {\n content?: number | true;\n mentions?: number | true;\n [key: `meta.${string}`]: number | true;\n};\n\n/**\n * Type for creating new threads.\n *\n * Threads are simple containers. All other fields are optional.\n *\n * @example\n * ```typescript\n * const thread: NewThread = {\n * title: \"Review pull request\"\n * };\n * ```\n */\nexport type NewThread = Partial<\n Omit<ThreadFields, \"priority\" | \"tags\" | \"mentions\" | \"id\">\n> &\n (\n | {\n /** Unique identifier for the thread, generated by Uuid.Generate(). */\n id: Uuid;\n }\n | {\n /* id is optional. An id will be generated and returned. */\n }\n ) &\n (\n | {\n /** Explicit priority (required when specified) - disables automatic priority matching */\n priority: Pick<Priority, \"id\">;\n }\n | {\n /** Configuration for automatic priority selection based on similarity */\n pickPriority?: PickPriorityConfig;\n }\n ) & {\n /**\n * All tags to set on the new thread.\n */\n tags?: NewTags;\n\n /**\n * Whether the thread should be marked as unread for users.\n * - undefined/omitted (default): Thread is unread for users, except auto-marked\n * as read for the author if they are the twist owner (user)\n * - true: Thread is explicitly unread for ALL users (use sparingly)\n * - false: Thread is marked as read for all users in the priority at creation time\n */\n unread?: boolean;\n\n /**\n * Whether the thread is archived.\n * - true: Archive the thread\n * - false: Unarchive the thread\n * - undefined (default): Preserve current archive state\n */\n archived?: boolean;\n\n /**\n * Optional preview content for the thread. Can be Markdown formatted.\n * The preview will be automatically generated from this content (truncated to 100 chars).\n */\n preview?: string | null;\n\n /**\n * Optional schedules to create alongside the thread.\n */\n schedules?: Array<Omit<NewSchedule, \"threadId\">>;\n\n /**\n * Optional schedule occurrence overrides.\n */\n scheduleOccurrences?: NewScheduleOccurrence[];\n };\n\nexport type ThreadFilter = {\n meta?: {\n [key: string]: JSONValue;\n };\n};\n\n/**\n * Fields supported by bulk updates via `match`. Only simple scalar fields\n * that can be applied uniformly across many threads are included.\n */\ntype ThreadBulkUpdateFields = Partial<\n Pick<ThreadFields, \"title\" | \"private\" | \"archived\">\n>;\n\n/**\n * Fields supported by single-thread updates via `id` or `source`.\n * Includes all bulk fields plus tags and preview.\n */\ntype ThreadSingleUpdateFields = ThreadBulkUpdateFields & {\n /**\n * Tags to change on the thread. Use an empty array of NewActor to remove a tag.\n * Use twistTags to add/remove the twist from tags to avoid clearing other actors' tags.\n */\n tags?: NewTags;\n\n /**\n * Add or remove the twist's tags.\n * Maps tag ID to boolean: true = add tag, false = remove tag.\n * This is allowed on all threads the twist has access to.\n */\n twistTags?: Partial<Record<Tag, boolean>>;\n\n /**\n * Optional preview content for the thread. Can be Markdown formatted.\n * The preview will be automatically generated from this content (truncated to 100 chars).\n *\n * - string: Use this content for preview generation\n * - null: Explicitly disable preview (no preview will be shown)\n * - undefined (omitted): Preserve current preview value\n *\n * This field is write-only and won't be returned when reading threads.\n */\n preview?: string | null;\n};\n\nexport type ThreadUpdate =\n | (({ id: Uuid } | { source: string }) & ThreadSingleUpdateFields)\n | ({\n /**\n * Update all threads matching the specified criteria. Only threads\n * that match all provided fields and were created by the twist will be updated.\n */\n match: ThreadFilter;\n } & ThreadBulkUpdateFields);\n\n/**\n * Represents a note within a thread.\n *\n * Notes contain the detailed content (note text, actions) associated with a thread.\n * They are always ordered by creation time within their parent thread.\n */\nexport type Note = ThreadCommon & {\n /** The author of this note */\n author: Actor;\n /**\n * Globally unique, stable identifier for the note within its thread.\n * Can be used to upsert without knowing the id.\n *\n * Use one of these patterns:\n * - Hardcoded semantic keys for fixed note types: \"description\", \"cancellation\"\n * - External service IDs for dynamic collections: `comment:${immutableId}`\n *\n * Examples:\n * - `\"description\"` (for a Jira issue's description note)\n * - `\"comment:12345\"` (for a specific comment by ID)\n * - `\"gmail:msg:18d4e5f2a3b1c9d7\"` (for a Gmail message within a thread)\n *\n * Ensure IDs are immutable - avoid human-readable slugs or titles.\n */\n key: string | null;\n /** The parent thread this note belongs to */\n thread: Thread;\n /** Primary content for the note (markdown) */\n content: string | null;\n /** Array of interactive actions attached to the note */\n actions: Array<Action> | null;\n /** The note this is a reply to, or null if not a reply */\n reNote: { id: Uuid } | null;\n};\n\n/**\n * Type for creating new notes.\n *\n * Requires the thread reference, with all other fields optional.\n * Can provide id, key, or neither for note identification:\n * - id: Provide a specific UUID for the note\n * - key: Provide an external identifier for upsert within the thread\n * - neither: A new note with auto-generated UUID will be created\n */\nexport type NewNote = Partial<\n Omit<\n Note,\n \"author\" | \"thread\" | \"tags\" | \"mentions\" | \"id\" | \"key\" | \"reNote\"\n >\n> &\n ({ id: Uuid } | { key: string } | {}) & {\n /** Reference to the parent thread (required) */\n thread:\n | Pick<Thread, \"id\">\n | {\n source: string;\n };\n\n /**\n * The person that created the item, or leave undefined to use the twist as author.\n */\n author?: NewActor;\n\n /**\n * Format of the note content. Determines how the note is processed:\n * - 'text': Plain text that will be converted to markdown (auto-links URLs, preserves line breaks)\n * - 'markdown': Already in markdown format (default, no conversion)\n * - 'html': HTML content that will be converted to markdown\n */\n contentType?: ContentType;\n\n /**\n * Tags to change on the thread. Use an empty array of NewActor to remove a tag.\n * Use twistTags to add/remove the twist from tags to avoid clearing other actors' tags.\n */\n tags?: NewTags;\n\n /**\n * Change the mentions on the note.\n */\n mentions?: NewActor[];\n\n /**\n * Whether the note should mark the parent thread as unread for users.\n * - undefined/omitted (default): Thread is unread for users, except auto-marked\n * as read for the author if they are the twist owner (user)\n * - true: Thread is explicitly unread for ALL users (use sparingly)\n * - false: Thread is marked as read for all users in the priority at note creation time\n *\n * For the default behavior, omit this field entirely.\n * Use false for initial sync to avoid marking historical items as unread.\n */\n unread?: boolean;\n\n /**\n * Reference to a parent note this note is a reply to.\n * - `{ id }`: reply by UUID\n * - `{ key }`: reply by key, resolved after creation (for batch ops)\n * - `null`: explicitly not a reply\n * - `undefined` (omitted): not a reply\n */\n reNote?: { id: Uuid } | { key: string } | null;\n };\n\n/**\n * Type for updating existing notes.\n * Must provide either id or key to identify the note to update.\n */\nexport type NoteUpdate = ({ id: Uuid; key?: string } | { key: string }) &\n Partial<\n Pick<Note, \"private\" | \"archived\" | \"content\" | \"actions\" | \"reNote\">\n > & {\n /**\n * Format of the note content. Determines how the note is processed:\n * - 'text': Plain text that will be converted to markdown (auto-links URLs, preserves line breaks)\n * - 'markdown': Already in markdown format (default, no conversion)\n * - 'html': HTML content that will be converted to markdown\n */\n contentType?: ContentType;\n\n /**\n * Tags to change on the note. Use an empty array of NewActor to remove a tag.\n * Use twistTags to add/remove the twist from tags to avoid clearing other actors' tags.\n */\n tags?: NewTags;\n\n /**\n * Add or remove the twist's tags.\n * Maps tag ID to boolean: true = add tag, false = remove tag.\n * This is allowed on all notes the twist has access to.\n */\n twistTags?: Partial<Record<Tag, boolean>>;\n\n /**\n * Change the mentions on the note.\n */\n mentions?: NewActor[];\n };\n\n/**\n * Represents an actor in Plot - a user, contact, or twist.\n *\n * Actors can be associated with threads as authors, assignees, or mentions.\n * The email field is only included when ContactAccess.Read permission is granted.\n *\n * @example\n * ```typescript\n * const actor: Actor = {\n * id: \"f0ffd5f8-1635-4b13-9532-35f97446db90\" as ActorId,\n * type: ActorType.Contact,\n * email: \"john.doe@example.com\", // Only if ContactAccess.Read\n * name: \"John Doe\"\n * };\n * ```\n */\nexport type Actor = {\n /** Unique identifier for the actor */\n id: ActorId;\n /** Type of actor (User, Contact, or Twist) */\n type: ActorType;\n /**\n * Email address (only included with ContactAccess.Read permission).\n * - `undefined`: No permission to read email\n * - `null`: Permission granted but email not set\n * - `string`: Email address\n */\n email?: string | null;\n /**\n * Display name.\n * - `undefined`: Not included due to permissions\n * - `null`: Not set\n * - `string`: Display name\n */\n name?: string | null;\n};\n\n/**\n * An existing or new contact.\n */\nexport type NewActor =\n | {\n /** Unique identifier for the actor */\n id: ActorId;\n }\n | NewContact;\n\n/**\n * Enumeration of author types that can create threads.\n *\n * The author type affects how threads are displayed and processed\n * within the Plot system.\n */\nexport enum ActorType {\n /** Threads created by human users */\n User,\n /** Threads created by external contacts */\n Contact,\n /** Threads created by automated twists */\n Twist,\n}\n\n/**\n * Represents contact information for creating a new contact.\n *\n * Contacts are used throughout Plot for representing people associated\n * with activities, such as event attendees or task assignees.\n *\n * @example\n * ```typescript\n * const newContact: NewContact = {\n * email: \"john.doe@example.com\",\n * name: \"John Doe\",\n * avatar: \"https://avatar.example.com/john.jpg\"\n * };\n * ```\n */\nexport type NewContact = {\n /** Email address of the contact (required) */\n email: string;\n /** Optional display name for the contact */\n name?: string;\n /** Optional avatar image URL for the contact */\n avatar?: string;\n /**\n * External provider account source. Used for privacy compliance\n * (e.g. Atlassian personal data reporting for GDPR account closure).\n * Required for contacts sourced from providers that mandate personal data reporting.\n */\n source?: { provider: AuthProvider; accountId: string };\n};\n\nexport type ContentType = \"text\" | \"markdown\" | \"html\";\n\n/**\n * Represents an external entity linked to a thread.\n *\n * Links are created by sources to represent external entities (issues, emails, calendar events)\n * attached to a thread container. A thread can have multiple links (1:many).\n * Links store source-specific data like type, status, metadata, and embeddings.\n *\n * @example\n * ```typescript\n * // A link representing a Linear issue\n * const link: Link = {\n * id: \"...\" as Uuid,\n * threadId: \"...\" as Uuid,\n * source: \"linear:issue:549dd8bd-2bc9-43d1-95d5-4b4af0c5af1b\",\n * created: new Date(),\n * author: { id: \"...\" as ActorId, type: ActorType.Contact, name: \"Alice\" },\n * title: \"Fix login bug\",\n * type: \"issue\",\n * status: \"open\",\n * meta: { projectId: \"TEAM\", url: \"https://linear.app/team/TEAM-123\" },\n * assignee: null,\n * actions: null,\n * };\n * ```\n */\nexport type Link = {\n /** Unique identifier for the link */\n id: Uuid;\n /** The thread this link belongs to */\n threadId: Uuid;\n /** External source identifier for dedup/upsert */\n source: string | null;\n /** When this link was originally created in its source system */\n created: Date;\n /** The actor credited with creating this link */\n author: Actor | null;\n /** Display title */\n title: string;\n /** Truncated preview */\n preview: string | null;\n /** The actor assigned to this link */\n assignee: Actor | null;\n /** Source-defined type string (e.g., issue, pull_request, email, event) */\n type: string | null;\n /** Source-defined status string (e.g., open, done, closed) */\n status: string | null;\n /** Interactive action buttons */\n actions: Array<Action> | null;\n /** Source metadata */\n meta: ThreadMeta | null;\n /** URL to open the original item in its source application (e.g., \"Open in Linear\") */\n sourceUrl: string | null;\n /** Channel ID that produced this link (matches source_channel.channel_id) */\n channelId: string | null;\n};\n\n/**\n * Type for creating new links.\n *\n * Links are created by sources to represent external entities.\n * Requires a source identifier for dedup/upsert.\n */\nexport type NewLink = (\n | {\n /** Unique identifier for the link, generated by Uuid.Generate() */\n id: Uuid;\n }\n | {\n /**\n * Canonical ID for the item in an external system.\n * When set, uniquely identifies the link within a priority tree. This performs\n * an upsert.\n */\n source: string;\n }\n | {}\n) &\n Partial<Omit<Link, \"id\" | \"source\" | \"author\" | \"assignee\" | \"threadId\">> & {\n /** The person that created the item. By default, it will be the twist itself. */\n author?: NewActor;\n /** The person assigned to the item. */\n assignee?: NewActor | null;\n /**\n * Whether the thread should be marked as unread for users.\n * - undefined/omitted (default): Thread is unread for users, except auto-marked\n * as read for the author if they are the twist owner (user)\n * - false: Thread is marked as read for all users in the priority at creation time\n */\n unread?: boolean;\n /**\n * Whether the thread is archived.\n * - true: Archive the thread\n * - false: Unarchive the thread\n * - undefined (default): Preserve current archive state\n */\n archived?: boolean;\n /**\n * Configuration for automatic priority selection based on similarity.\n * Only used when the link creates a new thread.\n */\n pickPriority?: PickPriorityConfig;\n /**\n * Explicit priority (disables automatic priority matching).\n * Only used when the link creates a new thread.\n */\n priority?: Pick<Priority, \"id\">;\n };\n\n/**\n * A new link with notes to save via integrations.saveLink().\n * Creates a thread+link pair, with notes attached to the thread.\n */\nexport type NewLinkWithNotes = NewLink & {\n /** Title for the link and its thread container */\n title: string;\n /** Notes to attach to the thread */\n notes?: Omit<NewNote, \"thread\">[];\n /** Schedules to create for the link */\n schedules?: Array<Omit<NewSchedule, \"threadId\">>;\n /** Schedule occurrence overrides */\n scheduleOccurrences?: NewScheduleOccurrence[];\n};\n";
8
8
  //# sourceMappingURL=plot.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"plot.js","sourceRoot":"","sources":["../../src/llm-docs/plot.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAe,wn1CAAwn1C,CAAC"}
1
+ {"version":3,"file":"plot.js","sourceRoot":"","sources":["../../src/llm-docs/plot.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAe,4t6BAA4t6B,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Generated LLM documentation for @plotday/twister/schedule
3
+ *
4
+ * This file is auto-generated during build. Do not edit manually.
5
+ * Generated from: prebuild.ts
6
+ */
7
+ declare const _default: "import { type Tag } from \"./tag\";\nimport {\n type Actor,\n type ActorId,\n type NewActor,\n type NewTags,\n type Tags,\n} from \"./plot\";\nimport { Uuid } from \"./utils/uuid\";\n\nexport { Uuid } from \"./utils/uuid\";\n\n/**\n * Represents a schedule entry for a thread.\n *\n * Schedules define when a thread occurs in time. A thread may have zero or more schedules:\n * - Shared schedules (userId is null): visible to all members of the thread's priority\n * - Per-user schedules (userId set): private ordering/scheduling for a specific user\n *\n * For recurring events in the SDK, start/end represent the first occurrence's\n * time. In the database, the `at`/`on` range is expanded to span from the first\n * occurrence start to the last occurrence end (or open-ended if no fixed end).\n * The `duration` column stores the per-occurrence duration, enabling range overlap\n * queries to correctly find all recurring events with occurrences in a given window.\n */\nexport type Schedule = {\n /** When this schedule was created */\n created: Date;\n /** Whether this schedule has been archived */\n archived: boolean;\n /** If set, this is a per-user schedule visible only to this user */\n userId: ActorId | null;\n /** Per-user ordering within a day (only set for per-user schedules) */\n order: number | null;\n /**\n * Start time of the schedule.\n * Date object for timed events, date string in \"YYYY-MM-DD\" format for all-day events.\n */\n start: Date | string | null;\n /**\n * End time of the schedule.\n * Date object for timed events, date string in \"YYYY-MM-DD\" format for all-day events.\n */\n end: Date | string | null;\n /** Recurrence rule in RFC 5545 RRULE format (e.g., \"FREQ=WEEKLY;BYDAY=MO,WE,FR\") */\n recurrenceRule: string | null;\n /** Duration of each occurrence in milliseconds (required for recurring schedules) */\n duration: number | null;\n /** Array of dates to exclude from the recurrence pattern */\n recurrenceExdates: Date[] | null;\n /**\n * For occurrence exceptions: the original date/time of this occurrence in the series.\n * Format: Date object or \"YYYY-MM-DD\" for all-day events.\n */\n occurrence: Date | string | null;\n /** Contacts invited to this schedule (attendees/participants) */\n contacts: ScheduleContact[];\n};\n\nexport type ScheduleContactStatus = \"attend\" | \"skip\";\nexport type ScheduleContactRole = \"organizer\" | \"required\" | \"optional\";\n\nexport type ScheduleContact = {\n contact: Actor;\n status: ScheduleContactStatus | null;\n role: ScheduleContactRole;\n archived: boolean;\n};\n\nexport type NewScheduleContact = {\n contact: NewActor;\n status?: ScheduleContactStatus | null;\n role?: ScheduleContactRole | null;\n archived?: boolean;\n};\n\n/**\n * Type for creating new schedules.\n *\n * Requires `threadId` and `start`. All other fields are optional.\n *\n * @example\n * ```typescript\n * // Simple timed event\n * const schedule: NewSchedule = {\n * threadId: threadId,\n * start: new Date(\"2025-03-15T10:00:00Z\"),\n * end: new Date(\"2025-03-15T11:00:00Z\")\n * };\n *\n * // All-day event\n * const allDay: NewSchedule = {\n * threadId: threadId,\n * start: \"2025-03-15\",\n * end: \"2025-03-16\"\n * };\n *\n * // Recurring weekly event\n * const recurring: NewSchedule = {\n * threadId: threadId,\n * start: new Date(\"2025-01-20T14:00:00Z\"),\n * end: new Date(\"2025-01-20T15:00:00Z\"),\n * recurrenceRule: \"FREQ=WEEKLY;BYDAY=MO\",\n * recurrenceUntil: new Date(\"2025-06-30\")\n * };\n * ```\n */\nexport type NewSchedule = {\n /** The thread this schedule belongs to */\n threadId: Uuid;\n /**\n * Start time. Date for timed events, \"YYYY-MM-DD\" for all-day.\n * Determines whether the schedule uses `at` (timed) or `on` (all-day) storage.\n */\n start: Date | string;\n /** End time. Date for timed events, \"YYYY-MM-DD\" for all-day. */\n end?: Date | string | null;\n /** Recurrence rule in RFC 5545 RRULE format */\n recurrenceRule?: string | null;\n /**\n * For recurring schedules, the last occurrence date (inclusive).\n * When both recurrenceCount and recurrenceUntil are provided, recurrenceCount takes precedence.\n */\n recurrenceUntil?: Date | string | null;\n /**\n * For recurring schedules, the number of occurrences to generate.\n * Takes precedence over recurrenceUntil if both are provided.\n */\n recurrenceCount?: number | null;\n /** Array of dates to exclude from the recurrence pattern */\n recurrenceExdates?: Date[] | null;\n /**\n * For occurrence exceptions: the original date/time of this occurrence.\n */\n occurrence?: Date | string | null;\n /** If set, this is a per-user schedule for the specified user */\n userId?: ActorId | null;\n /** Per-user ordering (only valid with userId) */\n order?: number | null;\n /** Whether to archive this schedule */\n archived?: boolean;\n /** Contacts to upsert on this schedule. Upserted by contact identity. */\n contacts?: NewScheduleContact[];\n};\n\n/**\n * Represents a specific instance of a recurring schedule.\n * All field values are computed by merging the recurring schedule's\n * defaults with any occurrence-specific overrides.\n */\nexport type ScheduleOccurrence = {\n /**\n * Original date/datetime of this occurrence.\n * Use start for the occurrence's current start time.\n */\n occurrence: Date | string;\n\n /** The recurring schedule of which this is an occurrence */\n schedule: Schedule;\n\n /** Effective start for this occurrence (series default + override) */\n start: Date | string;\n /** Effective end for this occurrence */\n end: Date | string | null;\n\n /** Tags for this occurrence */\n tags: Tags;\n\n /** True if the occurrence is archived */\n archived: boolean;\n};\n\n/**\n * Type for creating or updating schedule occurrences.\n */\nexport type NewScheduleOccurrence = Pick<\n ScheduleOccurrence,\n \"occurrence\" | \"start\"\n> &\n Partial<\n Omit<ScheduleOccurrence, \"occurrence\" | \"start\" | \"schedule\" | \"tags\">\n > & {\n /** Tags for this occurrence */\n tags?: NewTags;\n\n /** Add or remove the twist's tags on this occurrence */\n twistTags?: Partial<Record<Tag, boolean>>;\n\n /** Whether this occurrence should be marked as unread */\n unread?: boolean;\n\n /** Contacts to upsert on this occurrence's schedule */\n contacts?: NewScheduleContact[];\n };\n\n/**\n * Type for updating schedule occurrences inline.\n */\nexport type ScheduleOccurrenceUpdate = Pick<\n NewScheduleOccurrence,\n \"occurrence\"\n> &\n Partial<Omit<NewScheduleOccurrence, \"occurrence\" | \"schedule\">>;\n";
8
+ export default _default;
9
+ //# sourceMappingURL=schedule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedule.d.ts","sourceRoot":"","sources":["../../src/llm-docs/schedule.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;wBAEY,8iNAA8iN;AAA7jN,wBAA8jN"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Generated LLM documentation for @plotday/twister/schedule
3
+ *
4
+ * This file is auto-generated during build. Do not edit manually.
5
+ * Generated from: prebuild.ts
6
+ */
7
+ export default "import { type Tag } from \"./tag\";\nimport {\n type Actor,\n type ActorId,\n type NewActor,\n type NewTags,\n type Tags,\n} from \"./plot\";\nimport { Uuid } from \"./utils/uuid\";\n\nexport { Uuid } from \"./utils/uuid\";\n\n/**\n * Represents a schedule entry for a thread.\n *\n * Schedules define when a thread occurs in time. A thread may have zero or more schedules:\n * - Shared schedules (userId is null): visible to all members of the thread's priority\n * - Per-user schedules (userId set): private ordering/scheduling for a specific user\n *\n * For recurring events in the SDK, start/end represent the first occurrence's\n * time. In the database, the `at`/`on` range is expanded to span from the first\n * occurrence start to the last occurrence end (or open-ended if no fixed end).\n * The `duration` column stores the per-occurrence duration, enabling range overlap\n * queries to correctly find all recurring events with occurrences in a given window.\n */\nexport type Schedule = {\n /** When this schedule was created */\n created: Date;\n /** Whether this schedule has been archived */\n archived: boolean;\n /** If set, this is a per-user schedule visible only to this user */\n userId: ActorId | null;\n /** Per-user ordering within a day (only set for per-user schedules) */\n order: number | null;\n /**\n * Start time of the schedule.\n * Date object for timed events, date string in \"YYYY-MM-DD\" format for all-day events.\n */\n start: Date | string | null;\n /**\n * End time of the schedule.\n * Date object for timed events, date string in \"YYYY-MM-DD\" format for all-day events.\n */\n end: Date | string | null;\n /** Recurrence rule in RFC 5545 RRULE format (e.g., \"FREQ=WEEKLY;BYDAY=MO,WE,FR\") */\n recurrenceRule: string | null;\n /** Duration of each occurrence in milliseconds (required for recurring schedules) */\n duration: number | null;\n /** Array of dates to exclude from the recurrence pattern */\n recurrenceExdates: Date[] | null;\n /**\n * For occurrence exceptions: the original date/time of this occurrence in the series.\n * Format: Date object or \"YYYY-MM-DD\" for all-day events.\n */\n occurrence: Date | string | null;\n /** Contacts invited to this schedule (attendees/participants) */\n contacts: ScheduleContact[];\n};\n\nexport type ScheduleContactStatus = \"attend\" | \"skip\";\nexport type ScheduleContactRole = \"organizer\" | \"required\" | \"optional\";\n\nexport type ScheduleContact = {\n contact: Actor;\n status: ScheduleContactStatus | null;\n role: ScheduleContactRole;\n archived: boolean;\n};\n\nexport type NewScheduleContact = {\n contact: NewActor;\n status?: ScheduleContactStatus | null;\n role?: ScheduleContactRole | null;\n archived?: boolean;\n};\n\n/**\n * Type for creating new schedules.\n *\n * Requires `threadId` and `start`. All other fields are optional.\n *\n * @example\n * ```typescript\n * // Simple timed event\n * const schedule: NewSchedule = {\n * threadId: threadId,\n * start: new Date(\"2025-03-15T10:00:00Z\"),\n * end: new Date(\"2025-03-15T11:00:00Z\")\n * };\n *\n * // All-day event\n * const allDay: NewSchedule = {\n * threadId: threadId,\n * start: \"2025-03-15\",\n * end: \"2025-03-16\"\n * };\n *\n * // Recurring weekly event\n * const recurring: NewSchedule = {\n * threadId: threadId,\n * start: new Date(\"2025-01-20T14:00:00Z\"),\n * end: new Date(\"2025-01-20T15:00:00Z\"),\n * recurrenceRule: \"FREQ=WEEKLY;BYDAY=MO\",\n * recurrenceUntil: new Date(\"2025-06-30\")\n * };\n * ```\n */\nexport type NewSchedule = {\n /** The thread this schedule belongs to */\n threadId: Uuid;\n /**\n * Start time. Date for timed events, \"YYYY-MM-DD\" for all-day.\n * Determines whether the schedule uses `at` (timed) or `on` (all-day) storage.\n */\n start: Date | string;\n /** End time. Date for timed events, \"YYYY-MM-DD\" for all-day. */\n end?: Date | string | null;\n /** Recurrence rule in RFC 5545 RRULE format */\n recurrenceRule?: string | null;\n /**\n * For recurring schedules, the last occurrence date (inclusive).\n * When both recurrenceCount and recurrenceUntil are provided, recurrenceCount takes precedence.\n */\n recurrenceUntil?: Date | string | null;\n /**\n * For recurring schedules, the number of occurrences to generate.\n * Takes precedence over recurrenceUntil if both are provided.\n */\n recurrenceCount?: number | null;\n /** Array of dates to exclude from the recurrence pattern */\n recurrenceExdates?: Date[] | null;\n /**\n * For occurrence exceptions: the original date/time of this occurrence.\n */\n occurrence?: Date | string | null;\n /** If set, this is a per-user schedule for the specified user */\n userId?: ActorId | null;\n /** Per-user ordering (only valid with userId) */\n order?: number | null;\n /** Whether to archive this schedule */\n archived?: boolean;\n /** Contacts to upsert on this schedule. Upserted by contact identity. */\n contacts?: NewScheduleContact[];\n};\n\n/**\n * Represents a specific instance of a recurring schedule.\n * All field values are computed by merging the recurring schedule's\n * defaults with any occurrence-specific overrides.\n */\nexport type ScheduleOccurrence = {\n /**\n * Original date/datetime of this occurrence.\n * Use start for the occurrence's current start time.\n */\n occurrence: Date | string;\n\n /** The recurring schedule of which this is an occurrence */\n schedule: Schedule;\n\n /** Effective start for this occurrence (series default + override) */\n start: Date | string;\n /** Effective end for this occurrence */\n end: Date | string | null;\n\n /** Tags for this occurrence */\n tags: Tags;\n\n /** True if the occurrence is archived */\n archived: boolean;\n};\n\n/**\n * Type for creating or updating schedule occurrences.\n */\nexport type NewScheduleOccurrence = Pick<\n ScheduleOccurrence,\n \"occurrence\" | \"start\"\n> &\n Partial<\n Omit<ScheduleOccurrence, \"occurrence\" | \"start\" | \"schedule\" | \"tags\">\n > & {\n /** Tags for this occurrence */\n tags?: NewTags;\n\n /** Add or remove the twist's tags on this occurrence */\n twistTags?: Partial<Record<Tag, boolean>>;\n\n /** Whether this occurrence should be marked as unread */\n unread?: boolean;\n\n /** Contacts to upsert on this occurrence's schedule */\n contacts?: NewScheduleContact[];\n };\n\n/**\n * Type for updating schedule occurrences inline.\n */\nexport type ScheduleOccurrenceUpdate = Pick<\n NewScheduleOccurrence,\n \"occurrence\"\n> &\n Partial<Omit<NewScheduleOccurrence, \"occurrence\" | \"schedule\">>;\n";
8
+ //# sourceMappingURL=schedule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedule.js","sourceRoot":"","sources":["../../src/llm-docs/schedule.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAe,8iNAA8iN,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Generated LLM documentation for @plotday/twister/source
3
+ *
4
+ * This file is auto-generated during build. Do not edit manually.
5
+ * Generated from: prebuild.ts
6
+ */
7
+ declare const _default: "import { type Actor, type ActorId, type Link, type Note, type Thread } from \"./plot\";\nimport type { ScheduleContactStatus } from \"./schedule\";\nimport {\n type AuthProvider,\n type AuthToken,\n type Authorization,\n type Channel,\n type LinkTypeConfig,\n} from \"./tools/integrations\";\nimport { Twist } from \"./twist\";\n\n/**\n * Base class for sources \u2014 twists that sync data from external services.\n *\n * Sources declare a single OAuth provider and scopes, and implement channel\n * lifecycle methods for discovering and syncing external resources. They save\n * data directly via `integrations.saveLink()` instead of using the Plot tool.\n *\n * @example\n * ```typescript\n * class LinearSource extends Source<LinearSource> {\n * readonly provider = AuthProvider.Linear;\n * readonly scopes = [\"read\", \"write\"];\n * readonly linkTypes = [{\n * type: \"issue\",\n * label: \"Issue\",\n * statuses: [\n * { status: \"open\", label: \"Open\" },\n * { status: \"done\", label: \"Done\" },\n * ],\n * }];\n *\n * build(build: ToolBuilder) {\n * return {\n * integrations: build(Integrations),\n * };\n * }\n *\n * async getChannels(auth: Authorization, token: AuthToken): Promise<Channel[]> {\n * const teams = await this.listTeams(token);\n * return teams.map(t => ({ id: t.id, title: t.name }));\n * }\n *\n * async onChannelEnabled(channel: Channel) {\n * const issues = await this.fetchIssues(channel.id);\n * for (const issue of issues) {\n * await this.tools.integrations.saveLink(issue);\n * }\n * }\n *\n * async onChannelDisabled(channel: Channel) {\n * // Clean up webhooks, sync state, etc.\n * }\n * }\n * ```\n */\nexport abstract class Source<TSelf> extends Twist<TSelf> {\n /**\n * Static marker to identify Source subclasses without instanceof checks\n * across worker boundaries.\n */\n static readonly isSource = true;\n\n // ---- Identity (abstract \u2014 every source must declare) ----\n\n /** The OAuth provider this source authenticates with. */\n abstract readonly provider: AuthProvider;\n\n /** OAuth scopes to request for this source. */\n abstract readonly scopes: string[];\n\n // ---- Optional metadata ----\n\n /**\n * Registry of link types this source creates (e.g., issue, event, message).\n * Used for display in the UI (icons, labels, statuses).\n */\n readonly linkTypes?: LinkTypeConfig[];\n\n // ---- Channel lifecycle (abstract \u2014 every source must implement) ----\n\n /**\n * Returns available channels for the authorized actor.\n * Called after OAuth is complete, during the setup/edit modal.\n *\n * @param auth - The completed authorization with provider and actor info\n * @param token - The access token for making API calls\n * @returns Promise resolving to available channels for the user to select\n */\n abstract getChannels(\n auth: Authorization,\n token: AuthToken\n ): Promise<Channel[]>;\n\n /**\n * Called when a channel resource is enabled for syncing.\n * Should set up webhooks and start initial sync.\n *\n * @param channel - The channel that was enabled\n */\n abstract onChannelEnabled(channel: Channel): Promise<void>;\n\n /**\n * Called when a channel resource is disabled.\n * Should stop sync, clean up webhooks, and remove state.\n *\n * @param channel - The channel that was disabled\n */\n abstract onChannelDisabled(channel: Channel): Promise<void>;\n\n // ---- Write-back hooks (optional, default no-ops) ----\n\n /**\n * Called when a link created by this source is updated by the user.\n * Override to write back changes to the external service\n * (e.g., changing issue status in Linear when marked done in Plot).\n *\n * @param link - The updated link\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onLinkUpdated(link: Link): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Called when a note is created on a thread owned by this source.\n * Override to write back comments to the external service\n * (e.g., adding a comment to a Linear issue).\n *\n * @param note - The created note\n * @param thread - The thread the note belongs to (includes thread.meta with source-specific data)\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onNoteCreated(note: Note, thread: Thread): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Called when a user reads or unreads a thread owned by this source.\n * Override to write back read status to the external service\n * (e.g., marking an email as read in Gmail).\n *\n * @param thread - The thread that was read/unread (includes thread.meta with source-specific data)\n * @param actor - The user who performed the action\n * @param unread - false when marked as read, true when marked as unread\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onThreadRead(thread: Thread, actor: Actor, unread: boolean): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Called when a user marks or unmarks a thread as todo.\n * Override to sync todo status to the external service\n * (e.g., starring an email in Gmail when marked as todo).\n *\n * @param thread - The thread (includes thread.meta with source-specific data)\n * @param actor - The user who changed the todo status\n * @param todo - true when marked as todo, false when done or removed\n * @param options - Additional context\n * @param options.date - The todo date (when todo=true)\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onThreadToDo(thread: Thread, actor: Actor, todo: boolean, options: { date?: Date }): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Called when a schedule contact's RSVP status changes on a thread owned by this source.\n * Override to sync RSVP changes back to the external calendar.\n *\n * @param thread - The thread (includes thread.meta with source-specific data)\n * @param scheduleId - The schedule ID\n * @param contactId - The contact whose status changed\n * @param status - The new RSVP status ('attend', 'skip', or null)\n * @param actor - The user who changed the status\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onScheduleContactUpdated(thread: Thread, scheduleId: string, contactId: ActorId, status: ScheduleContactStatus | null, actor: Actor): Promise<void> {\n return Promise.resolve();\n }\n\n // ---- Activation ----\n\n /**\n * Called when the source is activated after OAuth is complete.\n *\n * Unlike Twist.activate() which receives a priority, Source.activate()\n * receives the authorization and actor since sources are not installed\n * in priorities.\n *\n * Default implementation does nothing. Override for custom setup.\n *\n * @param context - The activation context\n * @param context.auth - The completed OAuth authorization\n * @param context.actor - The actor who activated the source\n */\n // @ts-ignore - Source.activate() intentionally has a different signature than Twist.activate()\n activate(context: { auth: Authorization; actor: Actor }): Promise<void> {\n return Promise.resolve();\n }\n}\n";
8
+ export default _default;
9
+ //# sourceMappingURL=source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../../src/llm-docs/source.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;wBAEY,6qOAA8pO;AAA7qO,wBAA8qO"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Generated LLM documentation for @plotday/twister/source
3
+ *
4
+ * This file is auto-generated during build. Do not edit manually.
5
+ * Generated from: prebuild.ts
6
+ */
7
+ export default "import { type Actor, type ActorId, type Link, type Note, type Thread } from \"./plot\";\nimport type { ScheduleContactStatus } from \"./schedule\";\nimport {\n type AuthProvider,\n type AuthToken,\n type Authorization,\n type Channel,\n type LinkTypeConfig,\n} from \"./tools/integrations\";\nimport { Twist } from \"./twist\";\n\n/**\n * Base class for sources — twists that sync data from external services.\n *\n * Sources declare a single OAuth provider and scopes, and implement channel\n * lifecycle methods for discovering and syncing external resources. They save\n * data directly via `integrations.saveLink()` instead of using the Plot tool.\n *\n * @example\n * ```typescript\n * class LinearSource extends Source<LinearSource> {\n * readonly provider = AuthProvider.Linear;\n * readonly scopes = [\"read\", \"write\"];\n * readonly linkTypes = [{\n * type: \"issue\",\n * label: \"Issue\",\n * statuses: [\n * { status: \"open\", label: \"Open\" },\n * { status: \"done\", label: \"Done\" },\n * ],\n * }];\n *\n * build(build: ToolBuilder) {\n * return {\n * integrations: build(Integrations),\n * };\n * }\n *\n * async getChannels(auth: Authorization, token: AuthToken): Promise<Channel[]> {\n * const teams = await this.listTeams(token);\n * return teams.map(t => ({ id: t.id, title: t.name }));\n * }\n *\n * async onChannelEnabled(channel: Channel) {\n * const issues = await this.fetchIssues(channel.id);\n * for (const issue of issues) {\n * await this.tools.integrations.saveLink(issue);\n * }\n * }\n *\n * async onChannelDisabled(channel: Channel) {\n * // Clean up webhooks, sync state, etc.\n * }\n * }\n * ```\n */\nexport abstract class Source<TSelf> extends Twist<TSelf> {\n /**\n * Static marker to identify Source subclasses without instanceof checks\n * across worker boundaries.\n */\n static readonly isSource = true;\n\n // ---- Identity (abstract — every source must declare) ----\n\n /** The OAuth provider this source authenticates with. */\n abstract readonly provider: AuthProvider;\n\n /** OAuth scopes to request for this source. */\n abstract readonly scopes: string[];\n\n // ---- Optional metadata ----\n\n /**\n * Registry of link types this source creates (e.g., issue, event, message).\n * Used for display in the UI (icons, labels, statuses).\n */\n readonly linkTypes?: LinkTypeConfig[];\n\n // ---- Channel lifecycle (abstract — every source must implement) ----\n\n /**\n * Returns available channels for the authorized actor.\n * Called after OAuth is complete, during the setup/edit modal.\n *\n * @param auth - The completed authorization with provider and actor info\n * @param token - The access token for making API calls\n * @returns Promise resolving to available channels for the user to select\n */\n abstract getChannels(\n auth: Authorization,\n token: AuthToken\n ): Promise<Channel[]>;\n\n /**\n * Called when a channel resource is enabled for syncing.\n * Should set up webhooks and start initial sync.\n *\n * @param channel - The channel that was enabled\n */\n abstract onChannelEnabled(channel: Channel): Promise<void>;\n\n /**\n * Called when a channel resource is disabled.\n * Should stop sync, clean up webhooks, and remove state.\n *\n * @param channel - The channel that was disabled\n */\n abstract onChannelDisabled(channel: Channel): Promise<void>;\n\n // ---- Write-back hooks (optional, default no-ops) ----\n\n /**\n * Called when a link created by this source is updated by the user.\n * Override to write back changes to the external service\n * (e.g., changing issue status in Linear when marked done in Plot).\n *\n * @param link - The updated link\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onLinkUpdated(link: Link): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Called when a note is created on a thread owned by this source.\n * Override to write back comments to the external service\n * (e.g., adding a comment to a Linear issue).\n *\n * @param note - The created note\n * @param thread - The thread the note belongs to (includes thread.meta with source-specific data)\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onNoteCreated(note: Note, thread: Thread): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Called when a user reads or unreads a thread owned by this source.\n * Override to write back read status to the external service\n * (e.g., marking an email as read in Gmail).\n *\n * @param thread - The thread that was read/unread (includes thread.meta with source-specific data)\n * @param actor - The user who performed the action\n * @param unread - false when marked as read, true when marked as unread\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onThreadRead(thread: Thread, actor: Actor, unread: boolean): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Called when a user marks or unmarks a thread as todo.\n * Override to sync todo status to the external service\n * (e.g., starring an email in Gmail when marked as todo).\n *\n * @param thread - The thread (includes thread.meta with source-specific data)\n * @param actor - The user who changed the todo status\n * @param todo - true when marked as todo, false when done or removed\n * @param options - Additional context\n * @param options.date - The todo date (when todo=true)\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onThreadToDo(thread: Thread, actor: Actor, todo: boolean, options: { date?: Date }): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Called when a schedule contact's RSVP status changes on a thread owned by this source.\n * Override to sync RSVP changes back to the external calendar.\n *\n * @param thread - The thread (includes thread.meta with source-specific data)\n * @param scheduleId - The schedule ID\n * @param contactId - The contact whose status changed\n * @param status - The new RSVP status ('attend', 'skip', or null)\n * @param actor - The user who changed the status\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onScheduleContactUpdated(thread: Thread, scheduleId: string, contactId: ActorId, status: ScheduleContactStatus | null, actor: Actor): Promise<void> {\n return Promise.resolve();\n }\n\n // ---- Activation ----\n\n /**\n * Called when the source is activated after OAuth is complete.\n *\n * Unlike Twist.activate() which receives a priority, Source.activate()\n * receives the authorization and actor since sources are not installed\n * in priorities.\n *\n * Default implementation does nothing. Override for custom setup.\n *\n * @param context - The activation context\n * @param context.auth - The completed OAuth authorization\n * @param context.actor - The actor who activated the source\n */\n // @ts-ignore - Source.activate() intentionally has a different signature than Twist.activate()\n activate(context: { auth: Authorization; actor: Actor }): Promise<void> {\n return Promise.resolve();\n }\n}\n";
8
+ //# sourceMappingURL=source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source.js","sourceRoot":"","sources":["../../src/llm-docs/source.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAe,8pOAA8pO,CAAC"}
@@ -4,6 +4,6 @@
4
4
  * This file is auto-generated during build. Do not edit manually.
5
5
  * Generated from: prebuild.ts
6
6
  */
7
- declare const _default: "/**\n * Activity tags. Three types:\n * 1. Special tags, which trigger other behaviors\n * 2. Toggle tags, which anyone can toggle a shared value on or off\n * 3. Count tags, where everyone can add or remove their own\n */\nexport enum Tag {\n // Special tags\n Now = 1,\n Later = 2,\n Done = 3,\n Archived = 4,\n Someday = 7,\n\n // Toggle tags\n Pinned = 100,\n Urgent = 101,\n Inbox = 102,\n Goal = 103,\n Decision = 104,\n Waiting = 105,\n Blocked = 106,\n Warning = 107,\n Question = 108,\n Twist = 109,\n Star = 110,\n Idea = 111,\n\n // Count tags\n Yes = 1000,\n No = 1001,\n Volunteer = 1002,\n Tada = 1003,\n Fire = 1004,\n Totally = 1005,\n Looking = 1006,\n Love = 1007,\n Rocket = 1008,\n Sparkles = 1009,\n Thanks = 1010,\n Smile = 1011,\n Wave = 1012,\n Praise = 1015,\n Applause = 1016,\n Cool = 1017,\n Sad = 1018,\n // RSVP tags - mutually exclusive per actor\n // When an actor adds one of these tags, the other two are automatically removed\n Attend = 1019,\n Skip = 1020,\n Undecided = 1021,\n}\n";
7
+ declare const _default: "/**\n * Thread tags. Three types:\n * 1. Special tags, which trigger other behaviors\n * 2. Toggle tags, which anyone can toggle a shared value on or off\n * 3. Count tags, where everyone can add or remove their own\n */\nexport enum Tag {\n // Special tags\n Todo = 1,\n Done = 3,\n\n // Toggle tags\n Pinned = 100,\n Urgent = 101,\n Goal = 103,\n Decision = 104,\n Waiting = 105,\n Blocked = 106,\n Warning = 107,\n Question = 108,\n Twist = 109,\n Star = 110,\n Idea = 111,\n\n // Count tags\n Yes = 1000,\n No = 1001,\n Volunteer = 1002,\n Tada = 1003,\n Fire = 1004,\n Totally = 1005,\n Looking = 1006,\n Love = 1007,\n Rocket = 1008,\n Sparkles = 1009,\n Thanks = 1010,\n Smile = 1011,\n Wave = 1012,\n Praise = 1015,\n Applause = 1016,\n Cool = 1017,\n Sad = 1018,\n}\n";
8
8
  export default _default;
9
9
  //# sourceMappingURL=tag.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tag.d.ts","sourceRoot":"","sources":["../../src/llm-docs/tag.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;wBAEY,qiCAAqiC;AAApjC,wBAAqjC"}
1
+ {"version":3,"file":"tag.d.ts","sourceRoot":"","sources":["../../src/llm-docs/tag.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;wBAEY,2yBAA2yB;AAA1zB,wBAA2zB"}
@@ -4,5 +4,5 @@
4
4
  * This file is auto-generated during build. Do not edit manually.
5
5
  * Generated from: prebuild.ts
6
6
  */
7
- export default "/**\n * Activity tags. Three types:\n * 1. Special tags, which trigger other behaviors\n * 2. Toggle tags, which anyone can toggle a shared value on or off\n * 3. Count tags, where everyone can add or remove their own\n */\nexport enum Tag {\n // Special tags\n Now = 1,\n Later = 2,\n Done = 3,\n Archived = 4,\n Someday = 7,\n\n // Toggle tags\n Pinned = 100,\n Urgent = 101,\n Inbox = 102,\n Goal = 103,\n Decision = 104,\n Waiting = 105,\n Blocked = 106,\n Warning = 107,\n Question = 108,\n Twist = 109,\n Star = 110,\n Idea = 111,\n\n // Count tags\n Yes = 1000,\n No = 1001,\n Volunteer = 1002,\n Tada = 1003,\n Fire = 1004,\n Totally = 1005,\n Looking = 1006,\n Love = 1007,\n Rocket = 1008,\n Sparkles = 1009,\n Thanks = 1010,\n Smile = 1011,\n Wave = 1012,\n Praise = 1015,\n Applause = 1016,\n Cool = 1017,\n Sad = 1018,\n // RSVP tags - mutually exclusive per actor\n // When an actor adds one of these tags, the other two are automatically removed\n Attend = 1019,\n Skip = 1020,\n Undecided = 1021,\n}\n";
7
+ export default "/**\n * Thread tags. Three types:\n * 1. Special tags, which trigger other behaviors\n * 2. Toggle tags, which anyone can toggle a shared value on or off\n * 3. Count tags, where everyone can add or remove their own\n */\nexport enum Tag {\n // Special tags\n Todo = 1,\n Done = 3,\n\n // Toggle tags\n Pinned = 100,\n Urgent = 101,\n Goal = 103,\n Decision = 104,\n Waiting = 105,\n Blocked = 106,\n Warning = 107,\n Question = 108,\n Twist = 109,\n Star = 110,\n Idea = 111,\n\n // Count tags\n Yes = 1000,\n No = 1001,\n Volunteer = 1002,\n Tada = 1003,\n Fire = 1004,\n Totally = 1005,\n Looking = 1006,\n Love = 1007,\n Rocket = 1008,\n Sparkles = 1009,\n Thanks = 1010,\n Smile = 1011,\n Wave = 1012,\n Praise = 1015,\n Applause = 1016,\n Cool = 1017,\n Sad = 1018,\n}\n";
8
8
  //# sourceMappingURL=tag.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tag.js","sourceRoot":"","sources":["../../src/llm-docs/tag.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAe,qiCAAqiC,CAAC"}
1
+ {"version":3,"file":"tag.js","sourceRoot":"","sources":["../../src/llm-docs/tag.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAe,2yBAA2yB,CAAC"}