@plotday/twister 0.52.0 → 0.54.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 (219) hide show
  1. package/bin/commands/deploy.js +4 -0
  2. package/bin/commands/deploy.js.map +1 -1
  3. package/bin/templates/AGENTS.template.md +6 -10
  4. package/cli/templates/AGENTS.template.md +6 -10
  5. package/dist/connector.d.ts +179 -10
  6. package/dist/connector.d.ts.map +1 -1
  7. package/dist/connector.js +78 -4
  8. package/dist/connector.js.map +1 -1
  9. package/dist/docs/assets/hierarchy.js +1 -1
  10. package/dist/docs/assets/navigation.js +1 -1
  11. package/dist/docs/assets/search.js +1 -1
  12. package/dist/docs/classes/index.Connector.html +74 -26
  13. package/dist/docs/classes/index.FileNotFoundError.html +2 -0
  14. package/dist/docs/classes/index.Files.html +16 -0
  15. package/dist/docs/classes/index.Imap.html +1 -1
  16. package/dist/docs/classes/index.Options.html +1 -1
  17. package/dist/docs/classes/index.Smtp.html +1 -1
  18. package/dist/docs/classes/tool.ITool.html +1 -1
  19. package/dist/docs/classes/tools_ai.AI.html +7 -5
  20. package/dist/docs/classes/tools_callbacks.Callbacks.html +1 -1
  21. package/dist/docs/classes/tools_integrations.Integrations.html +17 -23
  22. package/dist/docs/classes/tools_network.Network.html +1 -1
  23. package/dist/docs/classes/tools_plot.Plot.html +62 -56
  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 +2 -2
  27. package/dist/docs/classes/twist.Twist.html +3 -3
  28. package/dist/docs/documents/Building_Connectors.html +1 -1
  29. package/dist/docs/enums/plot.ActionType.html +10 -8
  30. package/dist/docs/enums/plot.ActorType.html +4 -4
  31. package/dist/docs/enums/plot.ConferencingProvider.html +6 -6
  32. package/dist/docs/enums/plot.ThemeColor.html +10 -10
  33. package/dist/docs/enums/tag.Tag.html +16 -46
  34. package/dist/docs/enums/tools_ai.AIModel.html +2 -2
  35. package/dist/docs/enums/tools_integrations.AuthProvider.html +13 -13
  36. package/dist/docs/enums/{tools_plot.PriorityAccess.html → tools_plot.FocusAccess.html} +6 -6
  37. package/dist/docs/enums/tools_plot.ThreadAccess.html +1 -1
  38. package/dist/docs/hierarchy.html +1 -1
  39. package/dist/docs/interfaces/tools_ai.AIRequest.html +27 -11
  40. package/dist/docs/interfaces/tools_ai.AIResponse.html +9 -9
  41. package/dist/docs/interfaces/tools_ai.FilePart.html +5 -5
  42. package/dist/docs/interfaces/tools_ai.ImagePart.html +4 -4
  43. package/dist/docs/interfaces/tools_ai.ReasoningPart.html +4 -4
  44. package/dist/docs/interfaces/tools_ai.RedactedReasoningPart.html +3 -3
  45. package/dist/docs/interfaces/tools_ai.TextPart.html +3 -3
  46. package/dist/docs/interfaces/tools_ai.ToolCallPart.html +5 -5
  47. package/dist/docs/interfaces/tools_ai.ToolExecutionOptions.html +4 -4
  48. package/dist/docs/interfaces/tools_ai.ToolResultPart.html +5 -5
  49. package/dist/docs/media/AGENTS.md +22 -14
  50. package/dist/docs/modules/index.html +1 -1
  51. package/dist/docs/modules/plot.html +1 -1
  52. package/dist/docs/modules/tools_integrations.html +1 -1
  53. package/dist/docs/modules/tools_plot.html +1 -1
  54. package/dist/docs/types/index.CreateLinkDraft.html +31 -7
  55. package/dist/docs/types/index.NoteWriteBackResult.html +3 -3
  56. package/dist/docs/types/index.ReactionCapabilities.html +17 -0
  57. package/dist/docs/types/index.ResolvedRecipient.html +24 -0
  58. package/dist/docs/types/index.Schedule.html +1 -1
  59. package/dist/docs/types/plot.Action.html +9 -2
  60. package/dist/docs/types/plot.Actor.html +5 -5
  61. package/dist/docs/types/plot.ActorId.html +1 -1
  62. package/dist/docs/types/plot.Contact.html +4 -4
  63. package/dist/docs/types/plot.ContentType.html +1 -1
  64. package/dist/docs/types/{plot.Priority.html → plot.Focus.html} +14 -11
  65. package/dist/docs/types/plot.FocusUpdate.html +3 -0
  66. package/dist/docs/types/plot.Link.html +16 -16
  67. package/dist/docs/types/plot.LinkUpdate.html +1 -1
  68. package/dist/docs/types/plot.NewActor.html +1 -1
  69. package/dist/docs/types/plot.NewContact.html +1 -1
  70. package/dist/docs/types/plot.NewFocus.html +13 -0
  71. package/dist/docs/types/plot.NewLink.html +6 -6
  72. package/dist/docs/types/plot.NewLinkWithNotes.html +1 -1
  73. package/dist/docs/types/plot.NewNote.html +5 -3
  74. package/dist/docs/types/plot.NewReactions.html +4 -0
  75. package/dist/docs/types/plot.NewTags.html +1 -1
  76. package/dist/docs/types/plot.NewThread.html +6 -4
  77. package/dist/docs/types/plot.NewThreadWithNotes.html +1 -1
  78. package/dist/docs/types/plot.Note.html +2 -2
  79. package/dist/docs/types/plot.NoteUpdate.html +4 -2
  80. package/dist/docs/types/plot.PlanOperation.html +6 -6
  81. package/dist/docs/types/plot.Reaction.html +13 -0
  82. package/dist/docs/types/plot.Reactions.html +3 -0
  83. package/dist/docs/types/plot.Tags.html +1 -1
  84. package/dist/docs/types/plot.Thread.html +1 -1
  85. package/dist/docs/types/plot.ThreadAccessLevel.html +3 -3
  86. package/dist/docs/types/plot.ThreadCommon.html +9 -5
  87. package/dist/docs/types/plot.ThreadFilter.html +2 -2
  88. package/dist/docs/types/plot.ThreadMeta.html +1 -1
  89. package/dist/docs/types/plot.ThreadType.html +4 -4
  90. package/dist/docs/types/plot.ThreadUpdate.html +1 -1
  91. package/dist/docs/types/plot.ThreadWithNotes.html +1 -1
  92. package/dist/docs/types/tools_ai.AIAssistantMessage.html +2 -2
  93. package/dist/docs/types/tools_ai.AICapabilities.html +7 -3
  94. package/dist/docs/types/tools_ai.AIMessage.html +1 -1
  95. package/dist/docs/types/tools_ai.AIOptions.html +2 -2
  96. package/dist/docs/types/tools_ai.AISource.html +1 -1
  97. package/dist/docs/types/tools_ai.AISystemMessage.html +2 -2
  98. package/dist/docs/types/tools_ai.AITool.html +10 -9
  99. package/dist/docs/types/tools_ai.AIToolMessage.html +2 -2
  100. package/dist/docs/types/tools_ai.AIToolSet.html +1 -1
  101. package/dist/docs/types/tools_ai.AIUsage.html +5 -5
  102. package/dist/docs/types/tools_ai.AIUserMessage.html +2 -2
  103. package/dist/docs/types/tools_ai.DataContent.html +1 -1
  104. package/dist/docs/types/tools_ai.ModelPreferences.html +4 -4
  105. package/dist/docs/types/tools_integrations.ArchiveLinkFilter.html +5 -5
  106. package/dist/docs/types/tools_integrations.AuthToken.html +4 -4
  107. package/dist/docs/types/tools_integrations.Authorization.html +4 -4
  108. package/dist/docs/types/tools_integrations.Channel.html +5 -5
  109. package/dist/docs/types/tools_integrations.ComposeConfig.html +35 -0
  110. package/dist/docs/types/tools_integrations.ContactRoleConfig.html +14 -0
  111. package/dist/docs/types/tools_integrations.LinkTypeConfig.html +55 -28
  112. package/dist/docs/types/tools_integrations.SyncContext.html +3 -3
  113. package/dist/docs/types/tools_plot.SearchOptions.html +5 -6
  114. package/dist/docs/types/tools_twists.TwistPermissions.html +1 -1
  115. package/dist/llm-docs/connector.d.ts +1 -1
  116. package/dist/llm-docs/connector.d.ts.map +1 -1
  117. package/dist/llm-docs/connector.js +1 -1
  118. package/dist/llm-docs/connector.js.map +1 -1
  119. package/dist/llm-docs/index.d.ts.map +1 -1
  120. package/dist/llm-docs/index.js +2 -0
  121. package/dist/llm-docs/index.js.map +1 -1
  122. package/dist/llm-docs/plot.d.ts +1 -1
  123. package/dist/llm-docs/plot.d.ts.map +1 -1
  124. package/dist/llm-docs/plot.js +1 -1
  125. package/dist/llm-docs/plot.js.map +1 -1
  126. package/dist/llm-docs/schedule.d.ts +1 -1
  127. package/dist/llm-docs/schedule.d.ts.map +1 -1
  128. package/dist/llm-docs/schedule.js +1 -1
  129. package/dist/llm-docs/schedule.js.map +1 -1
  130. package/dist/llm-docs/tag.d.ts +1 -1
  131. package/dist/llm-docs/tag.d.ts.map +1 -1
  132. package/dist/llm-docs/tag.js +1 -1
  133. package/dist/llm-docs/tag.js.map +1 -1
  134. package/dist/llm-docs/tools/ai.d.ts +1 -1
  135. package/dist/llm-docs/tools/ai.d.ts.map +1 -1
  136. package/dist/llm-docs/tools/ai.js +1 -1
  137. package/dist/llm-docs/tools/ai.js.map +1 -1
  138. package/dist/llm-docs/tools/files.d.ts +9 -0
  139. package/dist/llm-docs/tools/files.d.ts.map +1 -0
  140. package/dist/llm-docs/tools/files.js +8 -0
  141. package/dist/llm-docs/tools/files.js.map +1 -0
  142. package/dist/llm-docs/tools/integrations.d.ts +1 -1
  143. package/dist/llm-docs/tools/integrations.d.ts.map +1 -1
  144. package/dist/llm-docs/tools/integrations.js +1 -1
  145. package/dist/llm-docs/tools/integrations.js.map +1 -1
  146. package/dist/llm-docs/tools/plot.d.ts +1 -1
  147. package/dist/llm-docs/tools/plot.d.ts.map +1 -1
  148. package/dist/llm-docs/tools/plot.js +1 -1
  149. package/dist/llm-docs/tools/plot.js.map +1 -1
  150. package/dist/llm-docs/tools/twists.d.ts +1 -1
  151. package/dist/llm-docs/tools/twists.d.ts.map +1 -1
  152. package/dist/llm-docs/tools/twists.js +1 -1
  153. package/dist/llm-docs/tools/twists.js.map +1 -1
  154. package/dist/llm-docs/twist-guide-template.d.ts +1 -1
  155. package/dist/llm-docs/twist-guide-template.d.ts.map +1 -1
  156. package/dist/llm-docs/twist-guide-template.js +1 -1
  157. package/dist/llm-docs/twist-guide-template.js.map +1 -1
  158. package/dist/llm-docs/twist.d.ts +1 -1
  159. package/dist/llm-docs/twist.d.ts.map +1 -1
  160. package/dist/llm-docs/twist.js +1 -1
  161. package/dist/llm-docs/twist.js.map +1 -1
  162. package/dist/plot.d.ts +146 -85
  163. package/dist/plot.d.ts.map +1 -1
  164. package/dist/plot.js +3 -1
  165. package/dist/plot.js.map +1 -1
  166. package/dist/schedule.d.ts +1 -1
  167. package/dist/tag.d.ts +17 -43
  168. package/dist/tag.d.ts.map +1 -1
  169. package/dist/tag.js +17 -46
  170. package/dist/tag.js.map +1 -1
  171. package/dist/tools/ai.d.ts +46 -10
  172. package/dist/tools/ai.d.ts.map +1 -1
  173. package/dist/tools/ai.js.map +1 -1
  174. package/dist/tools/files.d.ts +33 -0
  175. package/dist/tools/files.d.ts.map +1 -0
  176. package/dist/tools/files.js +22 -0
  177. package/dist/tools/files.js.map +1 -0
  178. package/dist/tools/index.d.ts +1 -0
  179. package/dist/tools/index.d.ts.map +1 -1
  180. package/dist/tools/index.js +1 -0
  181. package/dist/tools/index.js.map +1 -1
  182. package/dist/tools/integrations.d.ts +130 -50
  183. package/dist/tools/integrations.d.ts.map +1 -1
  184. package/dist/tools/integrations.js.map +1 -1
  185. package/dist/tools/plot.d.ts +66 -56
  186. package/dist/tools/plot.d.ts.map +1 -1
  187. package/dist/tools/plot.js +14 -14
  188. package/dist/tools/plot.js.map +1 -1
  189. package/dist/tools/twists.d.ts +2 -2
  190. package/dist/twist-guide.d.ts +1 -1
  191. package/dist/twist-guide.d.ts.map +1 -1
  192. package/dist/twist.d.ts +3 -3
  193. package/dist/twist.js +3 -3
  194. package/package.json +6 -1
  195. package/src/connector.ts +182 -10
  196. package/src/llm-docs/connector.ts +1 -1
  197. package/src/llm-docs/index.ts +2 -0
  198. package/src/llm-docs/plot.ts +1 -1
  199. package/src/llm-docs/schedule.ts +1 -1
  200. package/src/llm-docs/tag.ts +1 -1
  201. package/src/llm-docs/tools/ai.ts +1 -1
  202. package/src/llm-docs/tools/files.ts +8 -0
  203. package/src/llm-docs/tools/integrations.ts +1 -1
  204. package/src/llm-docs/tools/plot.ts +1 -1
  205. package/src/llm-docs/tools/twists.ts +1 -1
  206. package/src/llm-docs/twist-guide-template.ts +1 -1
  207. package/src/llm-docs/twist.ts +1 -1
  208. package/src/plot.ts +156 -75
  209. package/src/schedule.ts +1 -1
  210. package/src/tag.ts +17 -48
  211. package/src/tools/ai.ts +46 -10
  212. package/src/tools/files.ts +37 -0
  213. package/src/tools/index.ts +1 -0
  214. package/src/tools/integrations.ts +131 -61
  215. package/src/tools/plot.ts +69 -59
  216. package/src/tools/twists.ts +2 -2
  217. package/src/twist.ts +3 -3
  218. package/dist/docs/types/plot.NewPriority.html +0 -15
  219. package/dist/docs/types/plot.PriorityUpdate.html +0 -5
@@ -0,0 +1,37 @@
1
+ import { ITool } from "..";
2
+
3
+ /**
4
+ * Built-in tool for reading files attached to notes in Plot.
5
+ *
6
+ * Files are uploaded by clients via POST /files which creates an
7
+ * ActionType.file entry on a note. Connectors call read() during outbound
8
+ * (e.g. onNoteCreated) to retrieve those bytes and send them to the source
9
+ * system.
10
+ *
11
+ * For inbound attachments, connectors emit ActionType.fileRef actions and
12
+ * implement Connector.downloadAttachment — no upload tool is needed because
13
+ * inbound bytes never enter Plot's R2 storage.
14
+ */
15
+ export abstract class Files extends ITool {
16
+ /**
17
+ * Read a file uploaded by a client and attached to a note in a focus
18
+ * where this twist is installed.
19
+ *
20
+ * @param fileId The id from an ActionType.file action.
21
+ * @returns Bytes plus original metadata.
22
+ * @throws FileNotFoundError if the file is missing or out of scope.
23
+ */
24
+ abstract read(fileId: string): Promise<{
25
+ data: Uint8Array;
26
+ fileName: string;
27
+ mimeType: string;
28
+ fileSize: number;
29
+ }>;
30
+ }
31
+
32
+ export class FileNotFoundError extends Error {
33
+ constructor(fileId: string) {
34
+ super(`File not found or out of scope: ${fileId}`);
35
+ this.name = "FileNotFoundError";
36
+ }
37
+ }
@@ -1,6 +1,7 @@
1
1
  export * from "./twists";
2
2
  export * from "./ai";
3
3
  export * from "./callbacks";
4
+ export * from "./files";
4
5
  export * from "./integrations";
5
6
  export * from "./network";
6
7
  export * from "./plot";
@@ -4,9 +4,7 @@ import {
4
4
  type NewContact,
5
5
  type NewLinkWithNotes,
6
6
  ITool,
7
- Serializable,
8
7
  } from "..";
9
- import { Tag } from "../tag";
10
8
  import type { JSONValue } from "../utils/types";
11
9
  import type { Uuid } from "../utils/uuid";
12
10
 
@@ -34,6 +32,13 @@ export type LinkTypeConfig = {
34
32
  type: string;
35
33
  /** Human-readable label (e.g., "Issue", "Pull Request") */
36
34
  label: string;
35
+ /**
36
+ * Connector's word for a note on a linked item of this type — used by the
37
+ * Flutter app to adapt note/composer copy ("Add a comment" on Linear,
38
+ * "Add a message" on Slack, "Add a reply" on Gmail). Defaults to "note"
39
+ * when omitted. Use the singular noun in title case (e.g. "Comment").
40
+ */
41
+ noteLabel?: string;
37
42
  /** URL to an icon for this link type (light mode). Prefer Iconify `logos/*` URLs. */
38
43
  logo?: string;
39
44
  /** URL to an icon for dark mode. Use when the default logo is invisible on dark backgrounds (e.g., Iconify `simple-icons/*` with `?color=`). */
@@ -46,8 +51,6 @@ export type LinkTypeConfig = {
46
51
  status: string;
47
52
  /** Human-readable label (e.g., "Open", "Done") */
48
53
  label: string;
49
- /** Tag to propagate to thread when this status is active (e.g., Tag.Done) */
50
- tag?: Tag;
51
54
  /** Whether this status represents completion (done, closed, merged, cancelled, etc.) */
52
55
  done?: boolean;
53
56
  /**
@@ -59,41 +62,128 @@ export type LinkTypeConfig = {
59
62
  */
60
63
  active?: boolean;
61
64
  /**
62
- * Mark the thread `task=true` in Plot when a link enters this status.
63
- * Use for project-tracker assignments Linear / Todoist / Jira / etc.
64
- * `task` puts the thread on the user's task list without flooding their
65
- * inbox under `active`: the user explicitly flips it to `active` when
66
- * they decide to start.
67
- */
68
- task?: boolean;
69
- /**
70
- * Mark the thread `to_read=true` in Plot when a link enters this status.
71
- * Use for connectors that explicitly track read-later state (Pocket
72
- * archives, Slack "remind me", etc).
73
- */
74
- toRead?: boolean;
75
- /**
76
- * @deprecated Use `active` (messaging) or `task` (project tracker) instead.
77
- * Treated as `task: true` for backward compatibility.
78
- *
79
- * Original meaning: whether this status represents the connector's
80
- * "to-do" / active state. When a user adds a thread to Plot's agenda,
81
- * done-status links flip to the status marked `todo: true` (e.g.,
82
- * Gmail's "starred", Linear's "todo").
65
+ * Marks this status as the connector's "to-do" / active state. When a
66
+ * user brings a done thread back into Plot's agenda, done-status links
67
+ * are flipped to the status marked `todo: true` (e.g. Gmail's "starred",
68
+ * Linear's "unstarted"); connectors that don't mark one fall back to the
69
+ * first non-done status.
83
70
  */
84
71
  todo?: boolean;
85
- /**
86
- * Default status applied when Plot asks the connector to create a new
87
- * item of this type via `Connector.onCreateLink`. Declaring at least one
88
- * status with `createDefault: true` is how a link type opts in to
89
- * Plot-initiated creation. At most one status per type should set this.
90
- */
91
- createDefault?: boolean;
92
72
  }>;
93
73
  /** Whether this link type supports displaying and changing the assignee */
94
74
  supportsAssignee?: boolean;
95
75
  /** Default thread creation mode for this link type: 'all' | 'actionable' | 'manual' */
96
76
  defaultCreateThreads?: string;
77
+ /**
78
+ * Opt-in: declares this link type is composable from Plot via
79
+ * `Connector.onCreateLink`. Omit to make the link type sync-only (no
80
+ * "Create new …" picker entry).
81
+ *
82
+ * Connectors that need multiple compose modes for what users perceive as
83
+ * the same kind of thing (e.g. Slack channel post vs DM) should declare
84
+ * **separate linkTypes**, one per user-facing thread type. That keeps
85
+ * each linkType isomorphic to one filter chip.
86
+ */
87
+ compose?: ComposeConfig;
88
+ /**
89
+ * Per-connector contact roles. Examples:
90
+ * email → [{id:"to",label:"To",default:true},{id:"cc",label:"CC"},{id:"bcc",label:"BCC",hidden:true}]
91
+ * calendar → [{id:"required",label:"Required",default:true},{id:"optional",label:"Optional"}]
92
+ *
93
+ * Plot uses this list to render a role picker on each contact chip in the
94
+ * composer and to label non-default roles on existing threads. Exactly one
95
+ * role should be marked `default: true`. Connectors that don't distinguish
96
+ * roles (Slack, Linear) omit this field entirely.
97
+ */
98
+ contactRoles?: ContactRoleConfig[];
99
+ /**
100
+ * Whether contacts on an existing thread can be added, removed, or have
101
+ * their role changed (email-style mid-thread recipient changes). When
102
+ * false, the thread's contact list is fixed after creation. Defaults to
103
+ * false when omitted.
104
+ */
105
+ supportsContactChanges?: boolean;
106
+ /**
107
+ * Declares how sharing on threads of this link type is scoped:
108
+ *
109
+ * - `"thread"` (default): one roster shared across all notes in the
110
+ * thread. Native Plot threads, Slack DMs, calendar events.
111
+ * - `"channel"`: visibility is the external channel's membership;
112
+ * the per-thread `contacts` array is ignored for sharing UI.
113
+ * Slack channels, Linear projects.
114
+ * - `"message"`: each note carries its own recipient set via
115
+ * `note.access_contacts`; the thread roster is the union across
116
+ * all messages. Email.
117
+ *
118
+ * Omit to default to `"thread"`. When set to `"message"`, every
119
+ * note this connector ingests must populate `access_contacts`
120
+ * explicitly (never NULL).
121
+ */
122
+ sharingModel?: "thread" | "channel" | "message";
123
+ };
124
+
125
+ /**
126
+ * Declares how a link type is composable from Plot via
127
+ * `Connector.onCreateLink`. Attached to {@link LinkTypeConfig.compose}.
128
+ */
129
+ export type ComposeConfig = {
130
+ /**
131
+ * Selects the destination model for the "Create new …" picker.
132
+ *
133
+ * - `"channels"` (default): one chip per enabled channel (e.g. a Linear
134
+ * team, a Slack channel). Existing behaviour for task-tracker / calendar
135
+ * connectors.
136
+ * - `"contacts"`: one chip per connection (account); the user picks
137
+ * recipients from their contacts. The runtime pre-resolves the chosen
138
+ * Plot contacts to platform account IDs via the per-connection
139
+ * `contact_external_account` rows and delivers them as
140
+ * `CreateLinkDraft.recipients`. Contacts without a row for this specific
141
+ * connection are filtered out of the picker — used by closed-roster
142
+ * messaging platforms (Slack DM, Teams DM, Google Chat DM, LinkedIn DM).
143
+ * - `"addresses"`: one chip per connection; the picker accepts any
144
+ * contact with an addressable identifier (e.g. an email) or a free-form
145
+ * typed address. The runtime fills `recipients` for contacts with a
146
+ * connection-scoped row and falls back to the contact's primary address
147
+ * (e.g. `contact.email`) when no row exists. Free-form addresses arrive
148
+ * via the thread's `inviteEmails`. Used by open address spaces like
149
+ * Gmail.
150
+ */
151
+ targets?: "channels" | "contacts" | "addresses";
152
+ /**
153
+ * Status to assign newly-created links. Should match an entry in the
154
+ * parent linkType's `statuses[]`, OR a symbolic id that the connector's
155
+ * `onCreateLink` resolves itself (e.g. Linear's `"unstarted"` category is
156
+ * resolved per-team to a state UUID inside the connector — see
157
+ * `connectors/linear/src/linear.ts`).
158
+ */
159
+ status: string;
160
+ /**
161
+ * Optional override for the picker chip / "Create new …" copy. Defaults
162
+ * to the parent linkType's `label`. Use to disambiguate compose entries
163
+ * when the parent label alone isn't specific enough (e.g. "Direct
164
+ * messages" for a DM-mode compose on a chat connector).
165
+ */
166
+ label?: string;
167
+ };
168
+
169
+ /**
170
+ * Declares one contact role for a connector's link type. See
171
+ * `LinkTypeConfig.contactRoles`.
172
+ */
173
+ export type ContactRoleConfig = {
174
+ /** Stable machine id, e.g. "to" / "cc" / "bcc" / "required" / "optional". */
175
+ id: string;
176
+ /** Display label shown next to a contact chip, e.g. "To", "CC", "Required". */
177
+ label: string;
178
+ /** Exactly one role per linkType should be marked default. */
179
+ default?: boolean;
180
+ /**
181
+ * Hidden roles are visible only to (a) the contact themselves and
182
+ * (b) the user who added them. The API filters them out of every other
183
+ * viewer's `thread.contacts` and `thread.contactMeta`. Use for BCC-style
184
+ * semantics where other recipients must not see the hidden contact.
185
+ */
186
+ hidden?: boolean;
97
187
  };
98
188
 
99
189
  /**
@@ -210,32 +300,7 @@ export abstract class Integrations extends ITool {
210
300
  abstract get(provider: AuthProvider, channelId: string): Promise<AuthToken | null>;
211
301
 
212
302
  /**
213
- * Execute a callback as a specific actor, requesting auth if needed.
214
- *
215
- * If the actor has a valid token, calls the callback immediately with it.
216
- * If the actor has no token, creates a private auth note in the specified
217
- * activity prompting them to connect. Once they authorize, this callback fires.
218
- *
219
- * @param provider - The OAuth provider
220
- * @param actorId - The actor to act as
221
- * @param activityId - The activity to create an auth note in (if needed)
222
- * @param callback - Function to call with the token
223
- * @param extraArgs - Additional arguments to pass to the callback
224
- */
225
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
226
- abstract actAs<
227
- TArgs extends Serializable[],
228
- TCallback extends (token: AuthToken, ...args: TArgs) => any
229
- >(
230
- provider: AuthProvider,
231
- actorId: ActorId,
232
- activityId: Uuid,
233
- callback: TCallback,
234
- ...extraArgs: TArgs
235
- ): Promise<void>;
236
-
237
- /**
238
- * Saves a link with notes to the connector's priority.
303
+ * Saves a link with notes to the connector's focus.
239
304
  *
240
305
  * Creates a thread+link pair. The thread is a lightweight container;
241
306
  * the link holds the external entity data (source, meta, type, status, etc.).
@@ -274,10 +339,15 @@ export abstract class Integrations extends ITool {
274
339
  abstract saveLinks(links: NewLinkWithNotes[]): Promise<(Uuid | null)[]>;
275
340
 
276
341
  /**
277
- * Saves contacts to the connector's priority.
342
+ * Upserts contacts into the connector's focus without requiring a Link.
343
+ *
344
+ * Use this for messaging connectors to bulk-sync workspace members so the
345
+ * recipient picker can filter contacts by reachable platform account. Populate
346
+ * `NewContact.source` to persist `contact_external_account` rows (the platform
347
+ * identity used to address the contact). Returns one `Actor` per input, in order.
278
348
  *
279
- * @param contacts - Array of contacts to save
280
- * @returns Promise resolving to the saved actors
349
+ * @param contacts - Contacts to upsert, keyed by `source`/`key`
350
+ * @returns Promise resolving to the saved actors, 1:1 with input order
281
351
  */
282
352
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
283
353
  abstract saveContacts(contacts: NewContact[]): Promise<Actor[]>;
package/src/tools/plot.ts CHANGED
@@ -10,12 +10,12 @@ import {
10
10
  type NewThread,
11
11
  type NewThreadWithNotes,
12
12
  type NewNote,
13
- type NewPriority,
13
+ type NewFocus,
14
14
  type Note,
15
15
  type NoteUpdate,
16
16
  type PlanOperation,
17
- type Priority,
18
- type PriorityUpdate,
17
+ type Focus,
18
+ type FocusUpdate,
19
19
  Uuid,
20
20
  } from "..";
21
21
  import {
@@ -38,23 +38,23 @@ export enum ThreadAccess {
38
38
  Create,
39
39
  /**
40
40
  * List/query all Threads owned by the twist's user.
41
- * Update any Thread (title, tags, archived, type, priority) regardless of creator.
41
+ * Update any Thread (title, tags, archived, type, focus) regardless of creator.
42
42
  * Create Notes on any Thread (not just own or mentioned).
43
43
  * All Create permissions.
44
44
  */
45
45
  Full,
46
46
  }
47
47
 
48
- export enum PriorityAccess {
48
+ export enum FocusAccess {
49
49
  /**
50
- * Create new Priorities under the twist owner's priority tree.
51
- * Update Priorities created by the twist.
50
+ * Create new Focuses for the twist owner.
51
+ * Update Focuses created by the twist.
52
52
  */
53
53
  Create,
54
54
  /**
55
- * Read all Priorities owned by the twist's user.
56
- * Create new Priorities under the twist owner's priority tree.
57
- * Update and archive any Priority owned by the twist's user.
55
+ * Read all Focuses owned by the twist's user.
56
+ * Create new Focuses for the twist owner.
57
+ * Update and archive any Focus owned by the twist's user.
58
58
  */
59
59
  Full,
60
60
  }
@@ -100,7 +100,7 @@ export type LinkFilter = {
100
100
 
101
101
  type SearchResultBase = {
102
102
  thread: { id: string; title: string | null };
103
- priority: { id: string; title: string | null };
103
+ focus: { id: string; title: string | null };
104
104
  similarity: number;
105
105
  };
106
106
 
@@ -131,18 +131,17 @@ export type SearchOptions = {
131
131
  /** Minimum similarity score 0-1 (default: 0.3) */
132
132
  threshold?: number;
133
133
  /**
134
- * Scope search to this priority + descendants. Must be owned by the twist
135
- * owner. When omitted, the server scopes the search to the owner's entire
136
- * priority tree.
134
+ * Scope search to this focus. Must be owned by the twist owner. When
135
+ * omitted, the server scopes the search across all of the owner's focuses.
137
136
  */
138
- priorityId?: string;
137
+ focusId?: string;
139
138
  };
140
139
 
141
140
  /**
142
141
  * Built-in tool for interacting with the core Plot data layer.
143
142
  *
144
143
  * The Plot tool provides twists with the ability to create and manage threads,
145
- * priorities, and contacts within the Plot system. This is the primary interface
144
+ * focuses, and contacts within the Plot system. This is the primary interface
146
145
  * for twists to persist data and interact with the Plot database.
147
146
  *
148
147
  * @example
@@ -203,8 +202,8 @@ export abstract class Plot extends ITool {
203
202
  * }],
204
203
  * },
205
204
  * link: true,
206
- * priority: {
207
- * access: PriorityAccess.Full
205
+ * focus: {
206
+ * access: FocusAccess.Full
208
207
  * },
209
208
  * contact: {
210
209
  * access: ContactAccess.Read
@@ -247,14 +246,35 @@ export abstract class Plot extends ITool {
247
246
  * ```
248
247
  */
249
248
  intents?: NoteIntentHandler[];
249
+ /**
250
+ * Single conversational handler for mentions.
251
+ *
252
+ * When set, EVERY mention of this twist is routed directly to this
253
+ * handler — intent matching (and the built-in "What can you do?" /
254
+ * "Remove yourself" intents) is skipped. Use this to build a
255
+ * general-purpose conversational assistant that responds to any
256
+ * request, rather than classifying into a fixed set of `intents`.
257
+ *
258
+ * `handler` and `intents` are mutually exclusive; when both are
259
+ * present, `handler` takes precedence and `intents` is ignored.
260
+ *
261
+ * @example
262
+ * ```typescript
263
+ * note: {
264
+ * defaultMention: true,
265
+ * handler: this.respond, // (note: Note) => Promise<void>
266
+ * }
267
+ * ```
268
+ */
269
+ handler?: (note: Note) => Promise<void>;
250
270
  };
251
271
  /** Enable link processing from connected source channels. */
252
272
  link?: true | {
253
273
  /** Access level for links. When omitted with `link: true`, only source channel links are accessible. */
254
274
  access?: LinkAccess;
255
275
  };
256
- priority?: {
257
- access?: PriorityAccess;
276
+ focus?: {
277
+ access?: FocusAccess;
258
278
  };
259
279
  contact?: {
260
280
  access?: ContactAccess;
@@ -262,7 +282,7 @@ export abstract class Plot extends ITool {
262
282
  /** Enable semantic search across notes and links owned by the twist's user. */
263
283
  search?: true;
264
284
  /**
265
- * When true, admin write operations (on threads/notes/links/priorities not created by this twist)
285
+ * When true, admin write operations (on threads/notes/links/focuses not created by this twist)
266
286
  * require user approval via plan actions instead of executing immediately.
267
287
  * Read operations and operations on the twist's own content still work directly.
268
288
  */
@@ -313,8 +333,7 @@ export abstract class Plot extends ITool {
313
333
  * For tags, provide a Record<number, boolean> where true adds a tag and false removes it.
314
334
  * Tags not included in the update remain unchanged.
315
335
  *
316
- * When updating the parent, the thread's path will be automatically recalculated to
317
- * maintain the correct hierarchical structure.
336
+ * Set `focus` to move the thread to a different focus.
318
337
  *
319
338
  * Scheduling is handled separately via `createSchedule()` / `updateSchedule()`.
320
339
  *
@@ -481,41 +500,41 @@ export abstract class Plot extends ITool {
481
500
  abstract getNote(note: { id: Uuid } | { key: string }): Promise<Note | null>;
482
501
 
483
502
  /**
484
- * Creates a new priority in the Plot system.
503
+ * Creates a new focus in the Plot system.
485
504
  *
486
- * Priorities serve as organizational containers for threads and twists.
487
- * The created priority will be automatically assigned a unique ID.
505
+ * Focuses serve as organizational containers for threads and twists.
506
+ * The created focus will be automatically assigned a unique ID.
488
507
  *
489
- * @param priority - The priority data to create
490
- * @returns Promise resolving to the complete created priority
508
+ * @param focus - The focus data to create
509
+ * @returns Promise resolving to the complete created focus
491
510
  */
492
511
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
493
- abstract createPriority(priority: NewPriority): Promise<Priority & { created: boolean }>;
512
+ abstract createFocus(focus: NewFocus): Promise<Focus & { created: boolean }>;
494
513
 
495
514
  /**
496
- * Retrieves a priority by ID or key.
515
+ * Retrieves a focus by ID or key.
497
516
  *
498
- * Archived priorities are included in the results.
517
+ * Archived focuses are included in the results.
499
518
  *
500
- * @param priority - Priority lookup by ID or key
501
- * @returns Promise resolving to the matching priority or null if not found
519
+ * @param focus - Focus lookup by ID or key
520
+ * @returns Promise resolving to the matching focus or null if not found
502
521
  */
503
522
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
504
- abstract getPriority(
505
- priority: { id: Uuid } | { key: string }
506
- ): Promise<Priority | null>;
523
+ abstract getFocus(
524
+ focus: { id: Uuid } | { key: string }
525
+ ): Promise<Focus | null>;
507
526
 
508
527
  /**
509
- * Updates an existing priority in the Plot system.
528
+ * Updates an existing focus in the Plot system.
510
529
  *
511
- * The priority is identified by either its ID or key.
530
+ * The focus is identified by either its ID or key.
512
531
  * Only the fields specified in the update will be changed.
513
532
  *
514
- * @param update - Priority update containing ID/key and fields to change
533
+ * @param update - Focus update containing ID/key and fields to change
515
534
  * @returns Promise that resolves when the update is complete
516
535
  */
517
536
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
518
- abstract updatePriority(update: PriorityUpdate): Promise<void>;
537
+ abstract updateFocus(update: FocusUpdate): Promise<void>;
519
538
 
520
539
  /**
521
540
  * Retrieves actors by their IDs.
@@ -611,12 +630,10 @@ export abstract class Plot extends ITool {
611
630
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
612
631
  abstract getThreads(options?: {
613
632
  /**
614
- * Priority to list threads from. Must be owned by the twist owner.
615
- * When omitted, defaults to the owner's root priority.
633
+ * Focus to list threads from. Must be owned by the twist owner.
634
+ * When omitted, defaults to the owner's Inbox.
616
635
  */
617
- priorityId?: Uuid;
618
- /** Include threads from descendant priorities. Default: true. */
619
- includeDescendants?: boolean;
636
+ focusId?: Uuid;
620
637
  /** Include archived threads. Default: false. */
621
638
  includeArchived?: boolean;
622
639
  /** Maximum number of threads to return. Default: 50, max: 200. */
@@ -626,25 +643,18 @@ export abstract class Plot extends ITool {
626
643
  }): Promise<Thread[]>;
627
644
 
628
645
  /**
629
- * Lists priorities owned by the twist's user.
646
+ * Lists focuses owned by the twist's user.
630
647
  *
631
- * Requires `PriorityAccess.Full`.
648
+ * Requires `FocusAccess.Full`.
632
649
  *
633
- * @param options - Query options for filtering priorities
634
- * @returns Promise resolving to array of priorities
650
+ * @param options - Query options for filtering focuses
651
+ * @returns Promise resolving to array of focuses
635
652
  */
636
653
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
637
- abstract getPriorities(options?: {
638
- /**
639
- * Parent priority to list children of. Must be owned by the twist
640
- * owner. When omitted, defaults to the owner's root priority.
641
- */
642
- parentId?: Uuid;
643
- /** Include all descendants, not just direct children. Default: false. */
644
- includeDescendants?: boolean;
645
- /** Include archived priorities. Default: false. */
654
+ abstract getFocuses(options?: {
655
+ /** Include archived focuses. Default: false. */
646
656
  includeArchived?: boolean;
647
- }): Promise<Priority[]>;
657
+ }): Promise<Focus[]>;
648
658
 
649
659
  /**
650
660
  * Updates a link.
@@ -46,7 +46,7 @@ export type Log = {
46
46
  * },
47
47
  * "plot": {
48
48
  * "thread:mentioned": ["read", "write", "update"],
49
- * "priority": ["read", "write", "update"]
49
+ * "focus": ["read", "write", "update"]
50
50
  * }
51
51
  * }
52
52
  * ```
@@ -77,7 +77,7 @@ export type TwistPermissions = Record<string, Record<string, string[]>>;
77
77
  */
78
78
  export abstract class Twists extends ITool {
79
79
  /**
80
- * Creates a new twist ID and grants access to people in the current priority.
80
+ * Creates a new twist ID and grants access to people in the current focus.
81
81
  *
82
82
  * @returns Promise resolving to the generated twist ID
83
83
  * @throws When twist creation fails
package/src/twist.ts CHANGED
@@ -10,9 +10,9 @@ import type { InferTools, ToolBuilder, ToolShed } from "./utils/types";
10
10
  * Base class for all twists.
11
11
  *
12
12
  * A twist is installed at the workspace level and is owned by a single user
13
- * (see `this.userId`). It has no inherent priority scope: threads, notes, and
14
- * links it creates are filed against the owner's priorities, with automatic
15
- * priority matching when no explicit target is provided.
13
+ * (see `this.userId`). It has no inherent focus scope: threads, notes, and
14
+ * links it creates are filed against the owner's focuses, with automatic
15
+ * focus matching when no explicit target is provided.
16
16
  *
17
17
  * Override `build()` to declare tool dependencies and lifecycle methods to
18
18
  * handle events.
@@ -1,15 +0,0 @@
1
- <!DOCTYPE html><html class="default" lang="en" data-base="../"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>NewPriority | Creating Plot Twists</title><link rel="icon" href="../assets/favicon.svg" type="image/svg+xml"/><meta name="description" content="Documentation for Creating Plot Twists"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script><script async src="../assets/hierarchy.js" id="tsd-hierarchy-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><a href="/" class="title">Creating Plot Twists</a><div id="tsd-toolbar-links"><a href="https://plot.day">Plot</a><a href="https://github.com/plotday/plot">GitHub</a><a href="https://www.npmjs.com/package/@plotday/twister">NPM</a></div><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-search"></use></svg></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/><ul role="listbox" id="tsd-search-results"></ul><div id="tsd-search-status" aria-live="polite" aria-atomic="true"><div>Preparing search index...</div></div></dialog><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb" aria-label="Breadcrumb"><li><a href="../modules/plot.html">plot</a></li><li><a href="" aria-current="page">NewPriority</a></li></ul><h1>Type Alias NewPriority</h1></div><div class="tsd-signature"><span class="tsd-kind-type-alias">NewPriority</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Pick</span><span class="tsd-signature-symbol">&lt;</span><a href="plot.Priority.html" class="tsd-signature-type tsd-kind-type-alias">Priority</a><span class="tsd-signature-symbol">,</span> <span class="tsd-signature-type">&quot;title&quot;</span><span class="tsd-signature-symbol">&gt;</span> <span class="tsd-signature-symbol">&amp;</span> <span class="tsd-signature-type">Partial</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">Omit</span><span class="tsd-signature-symbol">&lt;</span><a href="plot.Priority.html" class="tsd-signature-type tsd-kind-type-alias">Priority</a><span class="tsd-signature-symbol">,</span> <span class="tsd-signature-type">&quot;id&quot;</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">&quot;title&quot;</span><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol">&gt;</span> <span class="tsd-signature-symbol">&amp;</span> (<br/>    <span class="tsd-signature-symbol">{</span> <span class="tsd-kind-property">id</span><span class="tsd-signature-symbol">:</span> <a href="index.Uuid.html" class="tsd-signature-type tsd-kind-type-alias">Uuid</a> <span class="tsd-signature-symbol">}</span><br/>    <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-symbol">{</span> <span class="tsd-kind-property">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">}</span><br/>    <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-symbol">{}</span><br/>) <span class="tsd-signature-symbol">&amp;</span> <span class="tsd-signature-symbol">{</span> <span class="tsd-kind-property">parent</span><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">{</span> <span class="tsd-kind-property">id</span><span class="tsd-signature-symbol">:</span> <a href="index.Uuid.html" class="tsd-signature-type tsd-kind-type-alias">Uuid</a> <span class="tsd-signature-symbol">}</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-symbol">{</span> <span class="tsd-kind-property">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">}</span> <span class="tsd-signature-symbol">}</span></div><div class="tsd-comment tsd-typography"><p>Type for creating new priorities.</p>
2
- <p>Supports multiple creation patterns:</p>
3
- <ul>
4
- <li>Provide a specific UUID for the priority</li>
5
- <li>Provide a key for upsert within the user's priorities</li>
6
- <li>Omit both to auto-generate a new UUID</li>
7
- </ul>
8
- <p>Optionally specify a parent priority by ID or key for hierarchical structures.</p>
9
- </div><div class="tsd-type-declaration"><h4>Type Declaration</h4><ul><li><span class="tsd-signature-symbol">{</span> <span class="tsd-kind-property">id</span><span class="tsd-signature-symbol">:</span> <a href="index.Uuid.html" class="tsd-signature-type tsd-kind-type-alias">Uuid</a> <span class="tsd-signature-symbol">}</span><ul class="tsd-parameters"><li class="tsd-parameter"><h5><span class="tsd-kind-property">id</span><span class="tsd-signature-symbol">: </span><a href="index.Uuid.html" class="tsd-signature-type tsd-kind-type-alias">Uuid</a></h5><div class="tsd-comment tsd-typography"><p>Unique identifier for the priority, generated by Uuid.Generate().
10
- Specifying an ID allows tools to track and upsert priorities.</p>
11
- </div></li></ul></li><li><span class="tsd-signature-symbol">{</span> <span class="tsd-kind-property">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">}</span><ul class="tsd-parameters"><li class="tsd-parameter"><h5><span class="tsd-kind-property">key</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span></h5><div class="tsd-comment tsd-typography"><p>Unique key for the priority within the user's priorities.
12
- Can be used to upsert without knowing the UUID.
13
- For example, &quot;@plot&quot; identifies the Plot priority.</p>
14
- </div></li></ul></li><li><span class="tsd-signature-symbol">{}</span></li></ul><ul class="tsd-parameters"><li class="tsd-parameter"><h5><code class="tsd-tag">Optional</code><span class="tsd-kind-property">parent</span><span class="tsd-signature-symbol">?: </span><span class="tsd-signature-symbol">{</span> <span class="tsd-kind-property">id</span><span class="tsd-signature-symbol">:</span> <a href="index.Uuid.html" class="tsd-signature-type tsd-kind-type-alias">Uuid</a> <span class="tsd-signature-symbol">}</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-symbol">{</span> <span class="tsd-kind-property">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">}</span></h5><div class="tsd-comment tsd-typography"><p>Add the new priority as the child of another priority</p>
15
- </div></li></ul></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twist/twister/src/plot.ts#L133">plot.ts:133</a></li></ul></aside></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div><div class="site-menu"><nav id="tsd-sidebar-links" class="tsd-navigation"><a href="https://plot.day" class="tsd-nav-link">Plot</a><a href="https://github.com/plotday/plot" class="tsd-nav-link">GitHub</a><a href="https://www.npmjs.com/package/@plotday/twister" class="tsd-nav-link">NPM</a></nav><nav class="tsd-navigation"><a href="../modules.html">Creating Plot Twists</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>