@plotday/twister 0.57.0 → 0.59.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +53 -44
- package/bin/commands/create.js +9 -14
- package/bin/commands/create.js.map +1 -1
- package/bin/commands/deploy.js +2 -0
- package/bin/commands/deploy.js.map +1 -1
- package/bin/commands/generate.js +8 -5
- package/bin/commands/generate.js.map +1 -1
- package/bin/index.js +2 -2
- package/bin/index.js.map +1 -1
- package/bin/templates/AGENTS.template.md +110 -94
- package/bin/templates/README.template.md +36 -33
- package/cli/templates/AGENTS.template.md +110 -94
- package/cli/templates/README.template.md +36 -33
- package/dist/connector.d.ts +58 -17
- package/dist/connector.d.ts.map +1 -1
- package/dist/connector.js +51 -13
- package/dist/connector.js.map +1 -1
- package/dist/docs/assets/hierarchy.js +1 -1
- package/dist/docs/assets/navigation.js +1 -1
- package/dist/docs/assets/search.js +1 -1
- package/dist/docs/classes/index.Connector.html +90 -60
- package/dist/docs/classes/index.FileNotFoundError.html +2 -2
- package/dist/docs/classes/index.Files.html +4 -4
- package/dist/docs/classes/index.Imap.html +10 -10
- package/dist/docs/classes/index.Options.html +2 -2
- package/dist/docs/classes/index.Smtp.html +6 -6
- package/dist/docs/classes/tool.ITool.html +2 -2
- package/dist/docs/classes/tool.Tool.html +23 -23
- package/dist/docs/classes/tools_ai.AI.html +5 -5
- package/dist/docs/classes/tools_callbacks.Callbacks.html +8 -8
- package/dist/docs/classes/tools_integrations.Integrations.html +15 -15
- package/dist/docs/classes/tools_network.Network.html +9 -9
- package/dist/docs/classes/tools_plot.Plot.html +34 -33
- package/dist/docs/classes/tools_store.Store.html +8 -8
- package/dist/docs/classes/tools_tasks.Tasks.html +6 -6
- package/dist/docs/classes/tools_twists.Twists.html +12 -11
- package/dist/docs/classes/twist.Twist.html +28 -28
- package/dist/docs/documents/Building_Connectors.html +42 -28
- package/dist/docs/documents/Built-in_Tools.html +170 -67
- package/dist/docs/documents/CLI_Reference.html +68 -47
- package/dist/docs/documents/Core_Concepts.html +52 -81
- package/dist/docs/documents/Getting_Started.html +28 -31
- package/dist/docs/documents/MULTI_USER_AUTH.html +45 -0
- package/dist/docs/documents/Runtime_Environment.html +13 -12
- package/dist/docs/documents/SYNC_STRATEGIES.html +373 -0
- package/dist/docs/enums/plot.ActionType.html +9 -9
- package/dist/docs/enums/plot.ActorType.html +4 -4
- package/dist/docs/enums/plot.ConferencingProvider.html +6 -6
- package/dist/docs/enums/plot.ThemeColor.html +9 -9
- package/dist/docs/enums/tag.Tag.html +3 -3
- package/dist/docs/enums/tools_ai.AIModel.html +3 -3
- package/dist/docs/enums/tools_integrations.AuthProvider.html +13 -13
- package/dist/docs/enums/tools_plot.ContactAccess.html +2 -2
- package/dist/docs/enums/tools_plot.FocusAccess.html +3 -3
- package/dist/docs/enums/tools_plot.LinkAccess.html +3 -3
- package/dist/docs/enums/tools_plot.ThreadAccess.html +4 -4
- package/dist/docs/functions/index.Uuid.Generate.html +1 -1
- package/dist/docs/functions/utils_hash.quickHash.html +1 -1
- package/dist/docs/hierarchy.html +1 -1
- package/dist/docs/index.html +7 -8
- package/dist/docs/interfaces/tools_ai.AIRequest.html +13 -13
- package/dist/docs/interfaces/tools_ai.AIResponse.html +9 -9
- package/dist/docs/interfaces/tools_ai.FilePart.html +5 -5
- package/dist/docs/interfaces/tools_ai.ImagePart.html +4 -4
- package/dist/docs/interfaces/tools_ai.ReasoningPart.html +4 -4
- package/dist/docs/interfaces/tools_ai.RedactedReasoningPart.html +3 -3
- package/dist/docs/interfaces/tools_ai.TextPart.html +3 -3
- package/dist/docs/interfaces/tools_ai.ToolCallPart.html +5 -5
- package/dist/docs/interfaces/tools_ai.ToolExecutionOptions.html +4 -4
- package/dist/docs/interfaces/tools_ai.ToolResultPart.html +5 -5
- package/dist/docs/interfaces/tools_twists.TwistSource.html +3 -3
- package/dist/docs/interfaces/utils_types.ToolShed.html +5 -5
- package/dist/docs/media/AGENTS.md +101 -74
- package/dist/docs/modules.html +1 -1
- package/dist/docs/types/index.BooleanDef.html +2 -2
- package/dist/docs/types/index.CreateLinkDraft.html +9 -9
- package/dist/docs/types/index.ImapAddress.html +3 -3
- package/dist/docs/types/index.ImapConnectOptions.html +6 -6
- package/dist/docs/types/index.ImapFetchOptions.html +4 -4
- package/dist/docs/types/index.ImapFlagOperation.html +1 -1
- package/dist/docs/types/index.ImapMailbox.html +5 -5
- package/dist/docs/types/index.ImapMailboxStatus.html +7 -7
- package/dist/docs/types/index.ImapMessage.html +14 -14
- package/dist/docs/types/index.ImapSearchCriteria.html +9 -9
- package/dist/docs/types/index.ImapSession.html +1 -1
- package/dist/docs/types/index.NewSchedule.html +13 -13
- package/dist/docs/types/index.NewScheduleContact.html +2 -2
- package/dist/docs/types/index.NewScheduleOccurrence.html +1 -1
- package/dist/docs/types/index.NoteWriteBackResult.html +3 -3
- package/dist/docs/types/index.NumberDef.html +2 -2
- package/dist/docs/types/index.OptionDef.html +1 -1
- package/dist/docs/types/index.OptionalScopeGroup.html +6 -6
- package/dist/docs/types/index.OptionsSchema.html +1 -1
- package/dist/docs/types/index.ReactionCapabilities.html +1 -1
- package/dist/docs/types/index.ResolvedOptions.html +1 -1
- package/dist/docs/types/index.ResolvedRecipient.html +5 -5
- package/dist/docs/types/index.Schedule.html +12 -12
- package/dist/docs/types/index.ScheduleContact.html +2 -2
- package/dist/docs/types/index.ScheduleContactRole.html +1 -1
- package/dist/docs/types/index.ScheduleContactStatus.html +1 -1
- package/dist/docs/types/index.ScheduleOccurrence.html +6 -6
- package/dist/docs/types/index.ScheduleOccurrenceUpdate.html +1 -1
- package/dist/docs/types/index.ScopeConfig.html +3 -3
- package/dist/docs/types/index.SelectDef.html +2 -2
- package/dist/docs/types/index.Serializable.html +1 -1
- package/dist/docs/types/index.SmtpAddress.html +3 -3
- package/dist/docs/types/index.SmtpConnectOptions.html +7 -7
- package/dist/docs/types/index.SmtpMessage.html +12 -12
- package/dist/docs/types/index.SmtpSendResult.html +4 -4
- package/dist/docs/types/index.SmtpSession.html +1 -1
- package/dist/docs/types/index.TextDef.html +2 -2
- package/dist/docs/types/index.Uuid.html +1 -1
- package/dist/docs/types/plot.Action.html +1 -1
- package/dist/docs/types/plot.Actor.html +5 -5
- package/dist/docs/types/plot.ActorId.html +4 -4
- package/dist/docs/types/plot.Contact.html +4 -4
- package/dist/docs/types/plot.ContentType.html +1 -1
- package/dist/docs/types/plot.Focus.html +8 -8
- package/dist/docs/types/plot.FocusUpdate.html +1 -1
- package/dist/docs/types/plot.Link.html +17 -17
- package/dist/docs/types/plot.LinkUpdate.html +1 -1
- package/dist/docs/types/plot.NewActor.html +1 -1
- package/dist/docs/types/plot.NewContact.html +1 -1
- package/dist/docs/types/plot.NewFocus.html +1 -1
- package/dist/docs/types/plot.NewLink.html +5 -2
- package/dist/docs/types/plot.NewLinkWithNotes.html +1 -1
- package/dist/docs/types/plot.NewNote.html +1 -1
- package/dist/docs/types/plot.NewReactions.html +1 -1
- package/dist/docs/types/plot.NewTags.html +1 -1
- package/dist/docs/types/plot.NewThread.html +1 -1
- package/dist/docs/types/plot.NewThreadWithNotes.html +1 -1
- package/dist/docs/types/plot.Note.html +1 -1
- package/dist/docs/types/plot.NoteUpdate.html +1 -1
- package/dist/docs/types/plot.PlanOperation.html +1 -1
- package/dist/docs/types/plot.Reaction.html +3 -3
- package/dist/docs/types/plot.Reactions.html +1 -1
- package/dist/docs/types/plot.Tags.html +1 -1
- package/dist/docs/types/plot.Thread.html +1 -1
- package/dist/docs/types/plot.ThreadAccessLevel.html +1 -1
- package/dist/docs/types/plot.ThreadCommon.html +6 -6
- package/dist/docs/types/plot.ThreadFilter.html +2 -2
- package/dist/docs/types/plot.ThreadMeta.html +1 -1
- package/dist/docs/types/plot.ThreadType.html +1 -1
- package/dist/docs/types/plot.ThreadUpdate.html +1 -1
- package/dist/docs/types/plot.ThreadWithNotes.html +1 -1
- package/dist/docs/types/tools_ai.AIAssistantMessage.html +2 -2
- package/dist/docs/types/tools_ai.AICapabilities.html +4 -4
- package/dist/docs/types/tools_ai.AIMessage.html +1 -1
- package/dist/docs/types/tools_ai.AIOptions.html +2 -2
- package/dist/docs/types/tools_ai.AISource.html +1 -1
- package/dist/docs/types/tools_ai.AISystemMessage.html +2 -2
- package/dist/docs/types/tools_ai.AITool.html +1 -1
- package/dist/docs/types/tools_ai.AIToolMessage.html +2 -2
- package/dist/docs/types/tools_ai.AIToolSet.html +1 -1
- package/dist/docs/types/tools_ai.AIUsage.html +5 -5
- package/dist/docs/types/tools_ai.AIUserMessage.html +2 -2
- package/dist/docs/types/tools_ai.DataContent.html +1 -1
- package/dist/docs/types/tools_ai.ModelPreferences.html +5 -5
- package/dist/docs/types/tools_callbacks.Callback.html +2 -2
- package/dist/docs/types/tools_integrations.ArchiveLinkFilter.html +5 -5
- package/dist/docs/types/tools_integrations.ArchiveNotesFilter.html +2 -2
- package/dist/docs/types/tools_integrations.AuthToken.html +6 -5
- package/dist/docs/types/tools_integrations.Authorization.html +4 -4
- package/dist/docs/types/tools_integrations.Channel.html +6 -6
- package/dist/docs/types/tools_integrations.ComposeConfig.html +4 -4
- package/dist/docs/types/tools_integrations.ContactRoleConfig.html +5 -5
- package/dist/docs/types/tools_integrations.LinkTypeConfig.html +21 -21
- package/dist/docs/types/tools_integrations.NewCustomEmoji.html +8 -8
- package/dist/docs/types/tools_integrations.StatusIcon.html +1 -1
- package/dist/docs/types/tools_integrations.SyncContext.html +4 -4
- package/dist/docs/types/tools_network.WebhookRequest.html +6 -6
- package/dist/docs/types/tools_plot.LinkFilter.html +5 -5
- package/dist/docs/types/tools_plot.LinkSearchResult.html +1 -1
- package/dist/docs/types/tools_plot.NoteIntentHandler.html +4 -4
- package/dist/docs/types/tools_plot.NoteSearchResult.html +1 -1
- package/dist/docs/types/tools_plot.SearchOptions.html +4 -4
- package/dist/docs/types/tools_plot.SearchResult.html +1 -1
- package/dist/docs/types/tools_twists.Log.html +2 -2
- package/dist/docs/types/tools_twists.TwistPermissions.html +1 -1
- package/dist/docs/types/utils_types.BuiltInTools.html +2 -2
- package/dist/docs/types/utils_types.ExtractBuildReturn.html +1 -1
- package/dist/docs/types/utils_types.InferOptions.html +1 -1
- package/dist/docs/types/utils_types.InferTools.html +1 -1
- package/dist/docs/types/utils_types.JSONValue.html +1 -1
- package/dist/docs/types/utils_types.PromiseValues.html +1 -1
- package/dist/docs/types/utils_types.ToolBuilder.html +1 -1
- package/dist/docs/variables/tools_plot.SEARCH_DEFAULT_LIMIT.html +1 -1
- package/dist/docs/variables/tools_plot.SEARCH_MAX_LIMIT.html +1 -1
- package/dist/facets.d.ts +30 -0
- package/dist/facets.d.ts.map +1 -0
- package/dist/facets.js +16 -0
- package/dist/facets.js.map +1 -0
- package/dist/llm-docs/connector.d.ts +1 -1
- package/dist/llm-docs/connector.d.ts.map +1 -1
- package/dist/llm-docs/connector.js +1 -1
- package/dist/llm-docs/connector.js.map +1 -1
- package/dist/llm-docs/facets.d.ts +9 -0
- package/dist/llm-docs/facets.d.ts.map +1 -0
- package/dist/llm-docs/facets.js +8 -0
- package/dist/llm-docs/facets.js.map +1 -0
- package/dist/llm-docs/index.d.ts.map +1 -1
- package/dist/llm-docs/index.js +2 -0
- package/dist/llm-docs/index.js.map +1 -1
- package/dist/llm-docs/plot.d.ts +1 -1
- package/dist/llm-docs/plot.d.ts.map +1 -1
- package/dist/llm-docs/plot.js +1 -1
- package/dist/llm-docs/plot.js.map +1 -1
- package/dist/llm-docs/tool.d.ts +1 -1
- package/dist/llm-docs/tool.d.ts.map +1 -1
- package/dist/llm-docs/tool.js +1 -1
- package/dist/llm-docs/tool.js.map +1 -1
- package/dist/llm-docs/tools/ai.d.ts +1 -1
- package/dist/llm-docs/tools/ai.d.ts.map +1 -1
- package/dist/llm-docs/tools/ai.js +1 -1
- package/dist/llm-docs/tools/ai.js.map +1 -1
- package/dist/llm-docs/tools/callbacks.d.ts +1 -1
- package/dist/llm-docs/tools/callbacks.d.ts.map +1 -1
- package/dist/llm-docs/tools/callbacks.js +1 -1
- package/dist/llm-docs/tools/callbacks.js.map +1 -1
- package/dist/llm-docs/tools/files.d.ts +1 -1
- package/dist/llm-docs/tools/files.d.ts.map +1 -1
- package/dist/llm-docs/tools/files.js +1 -1
- package/dist/llm-docs/tools/files.js.map +1 -1
- package/dist/llm-docs/tools/imap.d.ts +1 -1
- package/dist/llm-docs/tools/imap.d.ts.map +1 -1
- package/dist/llm-docs/tools/imap.js +1 -1
- package/dist/llm-docs/tools/imap.js.map +1 -1
- package/dist/llm-docs/tools/integrations.d.ts +1 -1
- package/dist/llm-docs/tools/integrations.d.ts.map +1 -1
- package/dist/llm-docs/tools/integrations.js +1 -1
- package/dist/llm-docs/tools/integrations.js.map +1 -1
- package/dist/llm-docs/tools/network.d.ts +1 -1
- package/dist/llm-docs/tools/network.d.ts.map +1 -1
- package/dist/llm-docs/tools/network.js +1 -1
- package/dist/llm-docs/tools/network.js.map +1 -1
- package/dist/llm-docs/tools/plot.d.ts +1 -1
- package/dist/llm-docs/tools/plot.d.ts.map +1 -1
- package/dist/llm-docs/tools/plot.js +1 -1
- package/dist/llm-docs/tools/plot.js.map +1 -1
- package/dist/llm-docs/tools/smtp.d.ts +1 -1
- package/dist/llm-docs/tools/smtp.d.ts.map +1 -1
- package/dist/llm-docs/tools/smtp.js +1 -1
- package/dist/llm-docs/tools/smtp.js.map +1 -1
- package/dist/llm-docs/tools/tasks.d.ts +1 -1
- package/dist/llm-docs/tools/tasks.d.ts.map +1 -1
- package/dist/llm-docs/tools/tasks.js +1 -1
- package/dist/llm-docs/tools/tasks.js.map +1 -1
- package/dist/llm-docs/tools/twists.d.ts +1 -1
- package/dist/llm-docs/tools/twists.d.ts.map +1 -1
- package/dist/llm-docs/tools/twists.js +1 -1
- package/dist/llm-docs/tools/twists.js.map +1 -1
- package/dist/llm-docs/twist-guide-template.d.ts +1 -1
- package/dist/llm-docs/twist-guide-template.d.ts.map +1 -1
- package/dist/llm-docs/twist-guide-template.js +1 -1
- package/dist/llm-docs/twist-guide-template.js.map +1 -1
- package/dist/llm-docs/twist.d.ts +1 -1
- package/dist/llm-docs/twist.d.ts.map +1 -1
- package/dist/llm-docs/twist.js +1 -1
- package/dist/llm-docs/twist.js.map +1 -1
- package/dist/plot.d.ts +15 -8
- package/dist/plot.d.ts.map +1 -1
- package/dist/plot.js.map +1 -1
- package/dist/tool.d.ts +4 -4
- package/dist/tool.js +4 -4
- package/dist/tools/ai.d.ts +12 -13
- package/dist/tools/ai.d.ts.map +1 -1
- package/dist/tools/ai.js +8 -9
- package/dist/tools/ai.js.map +1 -1
- package/dist/tools/callbacks.d.ts +1 -1
- package/dist/tools/files.d.ts +2 -2
- package/dist/tools/imap.d.ts +1 -1
- package/dist/tools/imap.js +1 -1
- package/dist/tools/integrations.d.ts +2 -1
- package/dist/tools/integrations.d.ts.map +1 -1
- package/dist/tools/network.d.ts +5 -5
- package/dist/tools/plot.d.ts +42 -37
- package/dist/tools/plot.d.ts.map +1 -1
- package/dist/tools/plot.js +16 -12
- package/dist/tools/plot.js.map +1 -1
- package/dist/tools/smtp.d.ts +1 -1
- package/dist/tools/smtp.js +1 -1
- package/dist/tools/tasks.d.ts +6 -8
- package/dist/tools/tasks.d.ts.map +1 -1
- package/dist/tools/tasks.js +5 -7
- package/dist/tools/tasks.js.map +1 -1
- package/dist/tools/twists.d.ts +15 -14
- package/dist/tools/twists.d.ts.map +1 -1
- package/dist/tools/twists.js +2 -2
- package/dist/tools/twists.js.map +1 -1
- package/dist/twist-guide.d.ts +1 -1
- package/dist/twist-guide.d.ts.map +1 -1
- package/dist/twist.d.ts +2 -2
- package/dist/twist.js +2 -2
- package/package.json +6 -1
- package/src/connector.ts +56 -16
- package/src/facets.ts +40 -0
- package/src/llm-docs/connector.ts +1 -1
- package/src/llm-docs/facets.ts +8 -0
- package/src/llm-docs/index.ts +2 -0
- package/src/llm-docs/plot.ts +1 -1
- package/src/llm-docs/tool.ts +1 -1
- package/src/llm-docs/tools/ai.ts +1 -1
- package/src/llm-docs/tools/callbacks.ts +1 -1
- package/src/llm-docs/tools/files.ts +1 -1
- package/src/llm-docs/tools/imap.ts +1 -1
- package/src/llm-docs/tools/integrations.ts +1 -1
- package/src/llm-docs/tools/network.ts +1 -1
- package/src/llm-docs/tools/plot.ts +1 -1
- package/src/llm-docs/tools/smtp.ts +1 -1
- package/src/llm-docs/tools/tasks.ts +1 -1
- package/src/llm-docs/tools/twists.ts +1 -1
- package/src/llm-docs/twist-guide-template.ts +1 -1
- package/src/llm-docs/twist.ts +1 -1
- package/src/plot.ts +15 -8
- package/src/tool.ts +4 -4
- package/src/tools/ai.ts +12 -13
- package/src/tools/callbacks.ts +1 -1
- package/src/tools/files.ts +2 -2
- package/src/tools/imap.ts +1 -1
- package/src/tools/integrations.ts +2 -1
- package/src/tools/network.ts +5 -5
- package/src/tools/plot.ts +42 -37
- package/src/tools/smtp.ts +1 -1
- package/src/tools/tasks.ts +6 -8
- package/src/tools/twists.ts +15 -14
- package/src/twist.ts +2 -2
- package/dist/docs/media/MULTI_USER_AUTH.md +0 -116
- package/dist/docs/media/SYNC_STRATEGIES.md +0 -818
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
<hr>
|
|
7
7
|
<h2 id="no-code-twists" class="tsd-anchor-link">No-Code Twists<a href="#no-code-twists" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><p>Create twists using natural language descriptions - no programming required!</p>
|
|
8
8
|
<h3 id="step-1-create-a-plot-twistmd-file" class="tsd-anchor-link">Step 1: Create a <a href="http://plot-twist.md">plot-twist.md</a> File<a href="#step-1-create-a-plot-twistmd-file" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p>Create a file named <code>plot-twist.md</code> in your project directory and describe what you want your twist to do:</p>
|
|
9
|
-
<pre><code class="markdown"><span class="hl-9"># My Calendar Twist</span><br/><br/><span class="hl-1">I want a twist that:</span><br/><br/><span class="hl-10">-</span><span class="hl-1"> Syncs my Google Calendar events into Plot as
|
|
9
|
+
<pre><code class="markdown"><span class="hl-9"># My Calendar Twist</span><br/><br/><span class="hl-1">I want a twist that:</span><br/><br/><span class="hl-10">-</span><span class="hl-1"> Syncs my Google Calendar events into Plot as threads</span><br/><span class="hl-10">-</span><span class="hl-1"> Creates tasks for upcoming meetings</span><br/><span class="hl-10">-</span><span class="hl-1"> Sends me a reminder 10 minutes before each meeting</span><br/><span class="hl-10">-</span><span class="hl-1"> Updates thread status when meetings are completed</span>
|
|
10
10
|
</code><button type="button">Copy</button></pre>
|
|
11
11
|
|
|
12
12
|
<p><strong>Be specific about:</strong></p>
|
|
13
13
|
<ul>
|
|
14
14
|
<li><strong>Data sources</strong> - Which services to connect (Google Calendar, GitHub, Slack, etc.)</li>
|
|
15
15
|
<li><strong>Actions</strong> - What the twist should do (create tasks, send notifications, update status)</li>
|
|
16
|
-
<li><strong>Triggers</strong> - When actions should happen (on new events, on schedule, when
|
|
16
|
+
<li><strong>Triggers</strong> - When actions should happen (on new events, on schedule, when threads change)</li>
|
|
17
17
|
</ul>
|
|
18
18
|
<h3 id="step-2-deploy-your-twist" class="tsd-anchor-link">Step 2: Deploy Your Twist<a href="#step-2-deploy-your-twist" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p>You'll need a <a href="https://plot.day">Plot account</a> to deploy twists.</p>
|
|
19
19
|
<pre><code class="bash"><span class="hl-7"># Login to Plot</span><br/><span class="hl-6">npx</span><span class="hl-1"> </span><span class="hl-3">@plotday/twister</span><span class="hl-1"> </span><span class="hl-3">login</span><br/><br/><span class="hl-7"># Deploy directly from your spec</span><br/><span class="hl-6">npx</span><span class="hl-1"> </span><span class="hl-3">@plotday/twister</span><span class="hl-1"> </span><span class="hl-3">deploy</span>
|
|
@@ -37,19 +37,19 @@
|
|
|
37
37
|
<li><strong>Display name</strong> (human-readable, e.g., "My Calendar Twist")</li>
|
|
38
38
|
</ul>
|
|
39
39
|
<p>This creates a new directory with:</p>
|
|
40
|
-
<pre><code><span class="hl-2">my</span><span class="hl-1">-</span><span class="hl-2">calendar</span><span class="hl-1">-</span><span class="hl-2">twist</span><span class="hl-1">/</span><br/><span class="hl-1">├── </span><span class="hl-2">src</span><span class="hl-1">/</span><br/><span class="hl-1">│ └── </span><span class="hl-2">index</span><span class="hl-1">.</span><span class="hl-2">ts</span><span class="hl-1"> # </span><span class="hl-2">Your</span><span class="hl-1"> </span><span class="hl-2">twist</span><span class="hl-1"> </span><span class="hl-2">code</span><br/><span class="hl-1">├── </span><span class="hl-2">package</span><span class="hl-1">.</span><span class="hl-2">json</span><br/><span class="hl-1">├── </span><span class="hl-2">tsconfig</span><span class="hl-1">.</span><span class="hl-2">json</span><br/><span class="hl-1"
|
|
40
|
+
<pre><code><span class="hl-2">my</span><span class="hl-1">-</span><span class="hl-2">calendar</span><span class="hl-1">-</span><span class="hl-2">twist</span><span class="hl-1">/</span><br/><span class="hl-1">├── </span><span class="hl-2">src</span><span class="hl-1">/</span><br/><span class="hl-1">│ └── </span><span class="hl-2">index</span><span class="hl-1">.</span><span class="hl-2">ts</span><span class="hl-1"> # </span><span class="hl-2">Your</span><span class="hl-1"> </span><span class="hl-2">twist</span><span class="hl-1"> </span><span class="hl-2">code</span><br/><span class="hl-1">├── </span><span class="hl-2">package</span><span class="hl-1">.</span><span class="hl-2">json</span><span class="hl-1"> # </span><span class="hl-2">Twist</span><span class="hl-1"> </span><span class="hl-2">metadata</span><span class="hl-1"> </span><span class="hl-2">and</span><span class="hl-1"> </span><span class="hl-2">dependencies</span><br/><span class="hl-1">├── </span><span class="hl-2">tsconfig</span><span class="hl-1">.</span><span class="hl-2">json</span><br/><span class="hl-1">├── </span><span class="hl-8">README</span><span class="hl-1">.</span><span class="hl-2">md</span><br/><span class="hl-1">├── </span><span class="hl-8">AGENTS</span><span class="hl-1">.</span><span class="hl-2">md</span><span class="hl-1"> # </span><span class="hl-2">Guide</span><span class="hl-1"> </span><span class="hl-2">for</span><span class="hl-1"> </span><span class="hl-8">AI</span><span class="hl-1"> </span><span class="hl-2">coding</span><span class="hl-1"> </span><span class="hl-2">assistants</span><br/><span class="hl-1">└── </span><span class="hl-8">CLAUDE</span><span class="hl-1">.</span><span class="hl-2">md</span>
|
|
41
41
|
</code><button>Copy</button></pre>
|
|
42
42
|
|
|
43
43
|
<h3 id="step-2-implement-your-twist" class="tsd-anchor-link">Step 2: Implement Your Twist<a href="#step-2-implement-your-twist" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p>Edit <code>src/index.ts</code> to add your twist logic:</p>
|
|
44
|
-
<pre><code class="typescript"><span class="hl-0">import</span><span class="hl-1"> {
|
|
44
|
+
<pre><code class="typescript"><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-0">type</span><span class="hl-1"> </span><span class="hl-2">Note</span><span class="hl-1">, </span><span class="hl-0">type</span><span class="hl-1"> </span><span class="hl-2">ToolBuilder</span><span class="hl-1">, </span><span class="hl-2">Twist</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">"@plotday/twister"</span><span class="hl-1">;</span><br/><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">Plot</span><span class="hl-1">, </span><span class="hl-2">ThreadAccess</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">"@plotday/twister/tools/plot"</span><span class="hl-1">;</span><br/><br/><span class="hl-0">export</span><span class="hl-1"> </span><span class="hl-0">default</span><span class="hl-1"> </span><span class="hl-4">class</span><span class="hl-1"> </span><span class="hl-5">MyTwist</span><span class="hl-1"> </span><span class="hl-4">extends</span><span class="hl-1"> </span><span class="hl-5">Twist</span><span class="hl-1"><</span><span class="hl-5">MyTwist</span><span class="hl-1">> {</span><br/><span class="hl-1"> </span><span class="hl-7">// Declare tool dependencies</span><br/><span class="hl-1"> </span><span class="hl-6">build</span><span class="hl-1">(</span><span class="hl-2">build</span><span class="hl-1">: </span><span class="hl-5">ToolBuilder</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-0">return</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">plot:</span><span class="hl-1"> </span><span class="hl-6">build</span><span class="hl-1">(</span><span class="hl-2">Plot</span><span class="hl-1">, {</span><br/><span class="hl-1"> </span><span class="hl-2">thread:</span><span class="hl-1"> { </span><span class="hl-2">access:</span><span class="hl-1"> </span><span class="hl-2">ThreadAccess</span><span class="hl-1">.</span><span class="hl-2">Create</span><span class="hl-1"> },</span><br/><span class="hl-1"> }),</span><br/><span class="hl-1"> };</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-7">// Called when the twist is installed</span><br/><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">activate</span><span class="hl-1">() {</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">tools</span><span class="hl-1">.</span><span class="hl-2">plot</span><span class="hl-1">.</span><span class="hl-6">createThread</span><span class="hl-1">({</span><br/><span class="hl-1"> </span><span class="hl-2">title:</span><span class="hl-1"> </span><span class="hl-3">"Welcome! Your twist is now active."</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">notes:</span><span class="hl-1"> [</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">content:</span><span class="hl-1"> </span><span class="hl-3">"Your twist is ready to use. You can now start creating threads and automating your workflow."</span><span class="hl-1">,</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> ],</span><br/><span class="hl-1"> });</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-7">// Called when a note is created on a thread this twist created</span><br/><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">onNoteCreated</span><span class="hl-1">(</span><span class="hl-2">note</span><span class="hl-1">: </span><span class="hl-5">Note</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-2">console</span><span class="hl-1">.</span><span class="hl-6">log</span><span class="hl-1">(</span><span class="hl-3">"Processing note:"</span><span class="hl-1">, </span><span class="hl-2">note</span><span class="hl-1">.</span><span class="hl-2">content</span><span class="hl-1">);</span><br/><span class="hl-1"> }</span><br/><span class="hl-1">}</span>
|
|
45
45
|
</code><button type="button">Copy</button></pre>
|
|
46
46
|
|
|
47
|
-
<h3 id="step-3-test-locally" class="tsd-anchor-link">Step 3: Test Locally<a href="#step-3-test-locally" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p>
|
|
48
|
-
<pre><code class="bash"><span class="hl-6">npm</span><span class="hl-1"> </span><span class="hl-3">run</span><span class="hl-1"> </span><span class="hl-3">
|
|
47
|
+
<h3 id="step-3-test-locally" class="tsd-anchor-link">Step 3: Test Locally<a href="#step-3-test-locally" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p>Check for build and lint errors:</p>
|
|
48
|
+
<pre><code class="bash"><span class="hl-6">npm</span><span class="hl-1"> </span><span class="hl-3">run</span><span class="hl-1"> </span><span class="hl-3">lint</span><br/><span class="hl-7"># or</span><br/><span class="hl-6">pnpm</span><span class="hl-1"> </span><span class="hl-3">lint</span>
|
|
49
49
|
</code><button type="button">Copy</button></pre>
|
|
50
50
|
|
|
51
51
|
<h3 id="step-4-deploy" class="tsd-anchor-link">Step 4: Deploy<a href="#step-4-deploy" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p>You'll need a <a href="https://plot.day">Plot account</a> to deploy twists.</p>
|
|
52
|
-
<pre><code class="bash"><span class="hl-7"># Login to Plot</span><br/><span class="hl-6">
|
|
52
|
+
<pre><code class="bash"><span class="hl-7"># Login to Plot</span><br/><span class="hl-6">npx</span><span class="hl-1"> </span><span class="hl-3">plot</span><span class="hl-1"> </span><span class="hl-3">login</span><br/><br/><span class="hl-7"># Deploy your twist</span><br/><span class="hl-6">npm</span><span class="hl-1"> </span><span class="hl-3">run</span><span class="hl-1"> </span><span class="hl-3">deploy</span>
|
|
53
53
|
</code><button type="button">Copy</button></pre>
|
|
54
54
|
|
|
55
55
|
<p>Your twist is now deployed and ready to activate in Plot!</p>
|
|
@@ -57,12 +57,12 @@
|
|
|
57
57
|
<h2 id="understanding-the-project-structure" class="tsd-anchor-link">Understanding the Project Structure<a href="#understanding-the-project-structure" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><h3 id="twist-file-srcindexts" class="tsd-anchor-link">Twist File (src/index.ts)<a href="#twist-file-srcindexts" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p>Your twist extends the <code>Twist</code> class and implements:</p>
|
|
58
58
|
<ul>
|
|
59
59
|
<li><strong><code>build()</code></strong> - Declares tool dependencies</li>
|
|
60
|
-
<li><strong><code>activate()</code></strong> - Initialization when
|
|
61
|
-
<li><strong><code>deactivate()</code></strong> - Cleanup when
|
|
60
|
+
<li><strong><code>activate()</code></strong> - Initialization when the twist is installed</li>
|
|
61
|
+
<li><strong><code>deactivate()</code></strong> - Cleanup when the twist is uninstalled</li>
|
|
62
62
|
<li><strong><code>upgrade()</code></strong> - Migration when deploying a new version</li>
|
|
63
63
|
</ul>
|
|
64
|
-
<h3 id="configuration-
|
|
65
|
-
<pre><code class="json"><span class="hl-1">{</span><br/><span class="hl-1"> </span><span class="hl-11">"name"</span><span class="hl-1">: </span><span class="hl-3">"my-calendar-twist"</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-11">"displayName"</span><span class="hl-1">: </span><span class="hl-3">"My Calendar Twist"</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-11">"
|
|
64
|
+
<h3 id="configuration-packagejson" class="tsd-anchor-link">Configuration (package.json)<a href="#configuration-packagejson" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p>Twist metadata lives in <code>package.json</code>, including a generated <code>plotTwistId</code> that identifies your twist for deployment:</p>
|
|
65
|
+
<pre><code class="json"><span class="hl-1">{</span><br/><span class="hl-1"> </span><span class="hl-11">"name"</span><span class="hl-1">: </span><span class="hl-3">"my-calendar-twist"</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-11">"displayName"</span><span class="hl-1">: </span><span class="hl-3">"My Calendar Twist"</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-11">"description"</span><span class="hl-1">: </span><span class="hl-3">"Syncs calendar events to Plot"</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-11">"plotTwistId"</span><span class="hl-1">: </span><span class="hl-3">"generated-uuid"</span><br/><span class="hl-1">}</span>
|
|
66
66
|
</code><button type="button">Copy</button></pre>
|
|
67
67
|
|
|
68
68
|
<h3 id="typescript-config-tsconfigjson" class="tsd-anchor-link">TypeScript Config (tsconfig.json)<a href="#typescript-config-tsconfigjson" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p>Extends the Twist Creator's base configuration:</p>
|
|
@@ -77,41 +77,38 @@
|
|
|
77
77
|
<li><strong><a href="Building_Connectors.html">Building Connectors</a></strong> - Build external service integrations</li>
|
|
78
78
|
<li><strong><a href="Runtime_Environment.html">Runtime Environment</a></strong> - Understand execution constraints and optimization</li>
|
|
79
79
|
</ul>
|
|
80
|
-
<h2 id="common-first-tasks" class="tsd-anchor-link">Common First Tasks<a href="#common-first-tasks" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><h3 id="understanding-
|
|
81
|
-
<p>Think of
|
|
82
|
-
<h3 id="creating-
|
|
83
|
-
<p><strong>Data Sync Tip:</strong> When syncing from external systems, use <code>
|
|
84
|
-
<pre><code class="typescript"><span class="hl-0">
|
|
80
|
+
<h2 id="common-first-tasks" class="tsd-anchor-link">Common First Tasks<a href="#common-first-tasks" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><h3 id="understanding-threads-and-notes" class="tsd-anchor-link">Understanding Threads and Notes<a href="#understanding-threads-and-notes" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p>A <strong>Thread</strong> represents something done or to be done (a task, event, or conversation), while <strong>Notes</strong> represent the updates and details on that thread.</p>
|
|
81
|
+
<p>Think of a <strong>Thread as a thread</strong> on a messaging platform, and <strong>Notes as the messages in that thread</strong>. Always create threads with an initial note, and add notes for updates rather than creating new threads.</p>
|
|
82
|
+
<h3 id="creating-threads" class="tsd-anchor-link">Creating Threads<a href="#creating-threads" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p>Always create threads with an initial note. The <code>notes</code> array can contain multiple notes (messages in the thread).</p>
|
|
83
|
+
<p><strong>Data Sync Tip:</strong> When syncing from external systems, build a connector and use <code>Link.sources</code> for automatic deduplication and <code>Note.key</code> for upsertable notes. See the <a href="SYNC_STRATEGIES.html">Sync Strategies</a> guide for detailed patterns.</p>
|
|
84
|
+
<pre><code class="typescript"><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">ActionType</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">"@plotday/twister"</span><span class="hl-1">;</span><br/><br/><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">tools</span><span class="hl-1">.</span><span class="hl-2">plot</span><span class="hl-1">.</span><span class="hl-6">createThread</span><span class="hl-1">({</span><br/><span class="hl-1"> </span><span class="hl-2">title:</span><span class="hl-1"> </span><span class="hl-3">"Review pull request"</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">notes:</span><span class="hl-1"> [</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">key:</span><span class="hl-1"> </span><span class="hl-3">"description"</span><span class="hl-1">, </span><span class="hl-7">// Using key enables upserts</span><br/><span class="hl-1"> </span><span class="hl-2">content:</span><span class="hl-1"> </span><span class="hl-3">"Please review the authentication changes and ensure they follow security best practices."</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">actions:</span><span class="hl-1"> [</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">type:</span><span class="hl-1"> </span><span class="hl-2">ActionType</span><span class="hl-1">.</span><span class="hl-2">external</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">title:</span><span class="hl-1"> </span><span class="hl-3">"View PR"</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">url:</span><span class="hl-1"> </span><span class="hl-3">"https://github.com/org/repo/pull/123"</span><span class="hl-1">,</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> ],</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> ],</span><br/><span class="hl-1">});</span>
|
|
85
85
|
</code><button type="button">Copy</button></pre>
|
|
86
86
|
|
|
87
|
-
<h4 id="scheduling-
|
|
88
|
-
<pre><code class="typescript"><span class="hl-7">//
|
|
87
|
+
<h4 id="scheduling-threads" class="tsd-anchor-link">Scheduling Threads<a href="#scheduling-threads" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h4><p>Threads appear on the user's agenda when they have a schedule. Pass <code>schedules</code> when creating the thread, or call <code>createSchedule()</code> later:</p>
|
|
88
|
+
<pre><code class="typescript"><span class="hl-7">// Scheduled (recurring) event</span><br/><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">tools</span><span class="hl-1">.</span><span class="hl-2">plot</span><span class="hl-1">.</span><span class="hl-6">createThread</span><span class="hl-1">({</span><br/><span class="hl-1"> </span><span class="hl-2">title:</span><span class="hl-1"> </span><span class="hl-3">"Team standup"</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">notes:</span><span class="hl-1"> [{ </span><span class="hl-2">content:</span><span class="hl-1"> </span><span class="hl-3">"Daily sync meeting"</span><span class="hl-1"> }],</span><br/><span class="hl-1"> </span><span class="hl-2">schedules:</span><span class="hl-1"> [</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">start:</span><span class="hl-1"> </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-6">Date</span><span class="hl-1">(</span><span class="hl-3">"2025-02-01T10:00:00Z"</span><span class="hl-1">),</span><br/><span class="hl-1"> </span><span class="hl-2">end:</span><span class="hl-1"> </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-6">Date</span><span class="hl-1">(</span><span class="hl-3">"2025-02-01T10:30:00Z"</span><span class="hl-1">),</span><br/><span class="hl-1"> </span><span class="hl-2">recurrenceRule:</span><span class="hl-1"> </span><span class="hl-3">"FREQ=DAILY;BYDAY=MO,TU,WE,TH,FR"</span><span class="hl-1">,</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> ],</span><br/><span class="hl-1">});</span>
|
|
89
89
|
</code><button type="button">Copy</button></pre>
|
|
90
90
|
|
|
91
91
|
<h3 id="storing-data" class="tsd-anchor-link">Storing Data<a href="#storing-data" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><pre><code class="typescript"><span class="hl-7">// Save</span><br/><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">set</span><span class="hl-1">(</span><span class="hl-3">"last_sync"</span><span class="hl-1">, </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-6">Date</span><span class="hl-1">().</span><span class="hl-6">toISOString</span><span class="hl-1">());</span><br/><br/><span class="hl-7">// Retrieve</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">lastSync</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">get</span><span class="hl-1"><</span><span class="hl-5">string</span><span class="hl-1">>(</span><span class="hl-3">"last_sync"</span><span class="hl-1">);</span>
|
|
92
92
|
</code><button type="button">Copy</button></pre>
|
|
93
93
|
|
|
94
|
-
<h3 id="scheduling-tasks" class="tsd-anchor-link">Scheduling Tasks<a href="#scheduling-tasks" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><pre><code class="typescript"><span class="hl-7">// Run immediately</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">callback</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">callback</span><span class="hl-1">(</span><span class="hl-
|
|
94
|
+
<h3 id="scheduling-tasks" class="tsd-anchor-link">Scheduling Tasks<a href="#scheduling-tasks" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><pre><code class="typescript"><span class="hl-7">// Run immediately (in a new execution with a fresh request limit)</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">callback</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">callback</span><span class="hl-1">(</span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">processData</span><span class="hl-1">);</span><br/><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">runTask</span><span class="hl-1">(</span><span class="hl-2">callback</span><span class="hl-1">);</span><br/><br/><span class="hl-7">// Schedule for later</span><br/><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">runTask</span><span class="hl-1">(</span><span class="hl-2">callback</span><span class="hl-1">, {</span><br/><span class="hl-1"> </span><span class="hl-2">runAt:</span><span class="hl-1"> </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-6">Date</span><span class="hl-1">(</span><span class="hl-3">"2025-02-01T10:00:00Z"</span><span class="hl-1">),</span><br/><span class="hl-1">});</span>
|
|
95
95
|
</code><button type="button">Copy</button></pre>
|
|
96
96
|
|
|
97
|
-
<h3 id="best-practices" class="tsd-anchor-link">Best Practices<a href="#best-practices" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><h4 id="always-include-notes-with-
|
|
98
|
-
<pre><code class="typescript"><span class="hl-7">// ✅ Good -
|
|
97
|
+
<h3 id="best-practices" class="tsd-anchor-link">Best Practices<a href="#best-practices" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><h4 id="always-include-notes-with-threads" class="tsd-anchor-link">Always Include Notes with Threads<a href="#always-include-notes-with-threads" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h4><p><strong>Important:</strong> Always create Threads with at least one initial Note. The <code>title</code> and <code>preview</code> are brief summaries that may be truncated in the UI. Detailed information should go in Notes.</p>
|
|
98
|
+
<pre><code class="typescript"><span class="hl-7">// ✅ Good - Thread with detailed Note</span><br/><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">tools</span><span class="hl-1">.</span><span class="hl-2">plot</span><span class="hl-1">.</span><span class="hl-6">createThread</span><span class="hl-1">({</span><br/><span class="hl-1"> </span><span class="hl-2">title:</span><span class="hl-1"> </span><span class="hl-3">"Deploy v2.0"</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">notes:</span><span class="hl-1"> [</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">content:</span><span class="hl-1"> </span><span class="hl-3">"Deployment checklist:</span><span class="hl-12">\n</span><span class="hl-3">- Run database migrations</span><span class="hl-12">\n</span><span class="hl-3">- Update environment variables</span><span class="hl-12">\n</span><span class="hl-3">- Deploy backend services</span><span class="hl-12">\n</span><span class="hl-3">- Deploy frontend</span><span class="hl-12">\n</span><span class="hl-3">- Run smoke tests"</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">actions:</span><span class="hl-1"> [</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">type:</span><span class="hl-1"> </span><span class="hl-2">ActionType</span><span class="hl-1">.</span><span class="hl-2">external</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">title:</span><span class="hl-1"> </span><span class="hl-3">"Deployment Guide"</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">url:</span><span class="hl-1"> </span><span class="hl-3">"https://docs.example.com/deploy"</span><span class="hl-1">,</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> ],</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> ],</span><br/><span class="hl-1">});</span><br/><br/><span class="hl-7">// ❌ Bad - No detailed information</span><br/><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">tools</span><span class="hl-1">.</span><span class="hl-2">plot</span><span class="hl-1">.</span><span class="hl-6">createThread</span><span class="hl-1">({</span><br/><span class="hl-1"> </span><span class="hl-2">title:</span><span class="hl-1"> </span><span class="hl-3">"Deploy v2.0"</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-7">// Missing Notes with context and steps</span><br/><span class="hl-1">});</span>
|
|
99
99
|
</code><button type="button">Copy</button></pre>
|
|
100
100
|
|
|
101
|
-
<h4 id="add-notes-to-existing-
|
|
102
|
-
<p><strong>Recommended Pattern:</strong>
|
|
103
|
-
<pre><code class="typescript"><span class="hl-7">//
|
|
101
|
+
<h4 id="add-notes-to-existing-threads-for-related-content" class="tsd-anchor-link">Add Notes to Existing Threads for Related Content<a href="#add-notes-to-existing-threads-for-related-content" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h4><p>For conversations, email threads, or workflows, add Notes to the existing Thread instead of creating new Threads.</p>
|
|
102
|
+
<p><strong>Recommended Pattern:</strong> Store the thread ID when you create the thread, then add notes by ID. A unique <code>Note.key</code> per message makes note writes upserts, so re-processing the same message never creates duplicates:</p>
|
|
103
|
+
<pre><code class="typescript"><span class="hl-2">async</span><span class="hl-1"> </span><span class="hl-6">onNewMessage</span><span class="hl-1">(</span><span class="hl-2">message</span><span class="hl-1">: </span><span class="hl-2">Message</span><span class="hl-1">, </span><span class="hl-2">conversationId</span><span class="hl-1">: </span><span class="hl-2">string</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-7">// Look up the thread for this conversation (created earlier)</span><br/><span class="hl-1"> </span><span class="hl-4">let</span><span class="hl-1"> </span><span class="hl-2">threadId</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">get</span><span class="hl-1"><</span><span class="hl-5">Uuid</span><span class="hl-1">>(</span><span class="hl-3">`thread_</span><span class="hl-4">${</span><span class="hl-2">conversationId</span><span class="hl-4">}</span><span class="hl-3">`</span><span class="hl-1">);</span><br/><br/><span class="hl-1"> </span><span class="hl-0">if</span><span class="hl-1"> (!</span><span class="hl-2">threadId</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-7">// First message - create the thread with the message as its initial note</span><br/><span class="hl-1"> </span><span class="hl-2">threadId</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">tools</span><span class="hl-1">.</span><span class="hl-2">plot</span><span class="hl-1">.</span><span class="hl-6">createThread</span><span class="hl-1">({</span><br/><span class="hl-1"> </span><span class="hl-2">title:</span><span class="hl-1"> </span><span class="hl-2">message</span><span class="hl-1">.</span><span class="hl-2">subject</span><span class="hl-1"> || </span><span class="hl-3">"New conversation"</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">notes:</span><span class="hl-1"> [</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">key:</span><span class="hl-1"> </span><span class="hl-3">`message-</span><span class="hl-4">${</span><span class="hl-2">message</span><span class="hl-13">.</span><span class="hl-2">id</span><span class="hl-4">}</span><span class="hl-3">`</span><span class="hl-1">, </span><span class="hl-7">// Unique key per message enables upserts</span><br/><span class="hl-1"> </span><span class="hl-2">content:</span><span class="hl-1"> </span><span class="hl-2">message</span><span class="hl-1">.</span><span class="hl-2">text</span><span class="hl-1">,</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> ],</span><br/><span class="hl-1"> });</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">set</span><span class="hl-1">(</span><span class="hl-3">`thread_</span><span class="hl-4">${</span><span class="hl-2">conversationId</span><span class="hl-4">}</span><span class="hl-3">`</span><span class="hl-1">, </span><span class="hl-2">threadId</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-0">return</span><span class="hl-1">;</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-7">// Follow-up message - add a note to the existing thread</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">tools</span><span class="hl-1">.</span><span class="hl-2">plot</span><span class="hl-1">.</span><span class="hl-6">createNote</span><span class="hl-1">({</span><br/><span class="hl-1"> </span><span class="hl-2">thread:</span><span class="hl-1"> { </span><span class="hl-2">id:</span><span class="hl-1"> </span><span class="hl-2">threadId</span><span class="hl-1"> },</span><br/><span class="hl-1"> </span><span class="hl-2">key:</span><span class="hl-1"> </span><span class="hl-3">`message-</span><span class="hl-4">${</span><span class="hl-2">message</span><span class="hl-13">.</span><span class="hl-2">id</span><span class="hl-4">}</span><span class="hl-3">`</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">content:</span><span class="hl-1"> </span><span class="hl-2">message</span><span class="hl-1">.</span><span class="hl-2">text</span><span class="hl-1">,</span><br/><span class="hl-1"> });</span><br/><span class="hl-1">}</span>
|
|
104
104
|
</code><button type="button">Copy</button></pre>
|
|
105
105
|
|
|
106
|
-
<p><strong>
|
|
107
|
-
<
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
<p>See <a href="../media/SYNC_STRATEGIES.md">Sync Strategies</a> for more patterns and guidance on choosing the right approach.</p>
|
|
111
|
-
<p>See <a href="Core_Concepts.html#best-practices-for-activities-and-notes">Core Concepts - Best Practices</a> for more details.</p>
|
|
106
|
+
<p><strong>For connectors:</strong> When syncing from an external service, you don't need to store thread IDs at all — save links with <code>integrations.saveLink()</code> using <code>Link.sources</code> for deduplication, and reference threads by source (<code>thread: { source: ... }</code>) when creating notes.</p>
|
|
107
|
+
<p>See <a href="SYNC_STRATEGIES.html">Sync Strategies</a> for more patterns and guidance on choosing the right approach.</p>
|
|
108
|
+
<p>See <a href="Core_Concepts.html#best-practices-for-threads-and-notes">Core Concepts - Best Practices</a> for more details.</p>
|
|
112
109
|
<h2 id="need-help" class="tsd-anchor-link">Need Help?<a href="#need-help" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><ul>
|
|
113
110
|
<li><strong>Documentation</strong>: Continue reading the guides</li>
|
|
114
111
|
<li><strong>Examples</strong>: Check the <a href="https://github.com/plotday/plot/tree/main/twists">examples directory</a></li>
|
|
115
112
|
<li><strong>Issues</strong>: <a href="https://github.com/plotday/plot/issues">Report bugs or request features</a></li>
|
|
116
113
|
</ul>
|
|
117
|
-
</div></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><details open class="tsd-accordion tsd-page-navigation"><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>On This Page</h3></summary><div class="tsd-accordion-details"><a href="#getting-started-with-plot-twists"><span>Getting <wbr/>Started with <wbr/>Plot <wbr/>Twists</span></a><ul><li><a href="#choose-your-path"><span>Choose <wbr/>Your <wbr/>Path</span></a></li><li><a href="#no-code-twists"><span>No-<wbr/>Code <wbr/>Twists</span></a></li><li><ul><li><a href="#step-1-create-a-plot-twistmd-file"><span>Step 1: <wbr/>Create a plot-<wbr/>twist.md <wbr/>File</span></a></li><li><a href="#step-2-deploy-your-twist"><span>Step 2: <wbr/>Deploy <wbr/>Your <wbr/>Twist</span></a></li><li><a href="#optional-generate-code-first"><span>Optional: <wbr/>Generate <wbr/>Code <wbr/>First</span></a></li></ul></li><li><a href="#developer-twists"><span>Developer <wbr/>Twists</span></a></li><li><ul><li><a href="#step-1-create-a-new-twist-project"><span>Step 1: <wbr/>Create a <wbr/>New <wbr/>Twist <wbr/>Project</span></a></li><li><a href="#step-2-implement-your-twist"><span>Step 2: <wbr/>Implement <wbr/>Your <wbr/>Twist</span></a></li><li><a href="#step-3-test-locally"><span>Step 3: <wbr/>Test <wbr/>Locally</span></a></li><li><a href="#step-4-deploy"><span>Step 4: <wbr/>Deploy</span></a></li></ul></li><li><a href="#understanding-the-project-structure"><span>Understanding the <wbr/>Project <wbr/>Structure</span></a></li><li><ul><li><a href="#twist-file-srcindexts"><span>Twist <wbr/>File (src/index.ts)</span></a></li><li><a href="#configuration-
|
|
114
|
+
</div></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><details open class="tsd-accordion tsd-page-navigation"><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>On This Page</h3></summary><div class="tsd-accordion-details"><a href="#getting-started-with-plot-twists"><span>Getting <wbr/>Started with <wbr/>Plot <wbr/>Twists</span></a><ul><li><a href="#choose-your-path"><span>Choose <wbr/>Your <wbr/>Path</span></a></li><li><a href="#no-code-twists"><span>No-<wbr/>Code <wbr/>Twists</span></a></li><li><ul><li><a href="#step-1-create-a-plot-twistmd-file"><span>Step 1: <wbr/>Create a plot-<wbr/>twist.md <wbr/>File</span></a></li><li><a href="#step-2-deploy-your-twist"><span>Step 2: <wbr/>Deploy <wbr/>Your <wbr/>Twist</span></a></li><li><a href="#optional-generate-code-first"><span>Optional: <wbr/>Generate <wbr/>Code <wbr/>First</span></a></li></ul></li><li><a href="#developer-twists"><span>Developer <wbr/>Twists</span></a></li><li><ul><li><a href="#step-1-create-a-new-twist-project"><span>Step 1: <wbr/>Create a <wbr/>New <wbr/>Twist <wbr/>Project</span></a></li><li><a href="#step-2-implement-your-twist"><span>Step 2: <wbr/>Implement <wbr/>Your <wbr/>Twist</span></a></li><li><a href="#step-3-test-locally"><span>Step 3: <wbr/>Test <wbr/>Locally</span></a></li><li><a href="#step-4-deploy"><span>Step 4: <wbr/>Deploy</span></a></li></ul></li><li><a href="#understanding-the-project-structure"><span>Understanding the <wbr/>Project <wbr/>Structure</span></a></li><li><ul><li><a href="#twist-file-srcindexts"><span>Twist <wbr/>File (src/index.ts)</span></a></li><li><a href="#configuration-packagejson"><span>Configuration (package.json)</span></a></li><li><a href="#typescript-config-tsconfigjson"><span>Type<wbr/>Script <wbr/>Config (tsconfig.json)</span></a></li></ul></li><li><a href="#next-steps"><span>Next <wbr/>Steps</span></a></li><li><a href="#common-first-tasks"><span>Common <wbr/>First <wbr/>Tasks</span></a></li><li><ul><li><a href="#understanding-threads-and-notes"><span>Understanding <wbr/>Threads and <wbr/>Notes</span></a></li><li><a href="#creating-threads"><span>Creating <wbr/>Threads</span></a></li><li><ul><li><a href="#scheduling-threads"><span>Scheduling <wbr/>Threads</span></a></li></ul></li><li><a href="#storing-data"><span>Storing <wbr/>Data</span></a></li><li><a href="#scheduling-tasks"><span>Scheduling <wbr/>Tasks</span></a></li><li><a href="#best-practices"><span>Best <wbr/>Practices</span></a></li><li><ul><li><a href="#always-include-notes-with-threads"><span>Always <wbr/>Include <wbr/>Notes with <wbr/>Threads</span></a></li><li><a href="#add-notes-to-existing-threads-for-related-content"><span>Add <wbr/>Notes to <wbr/>Existing <wbr/>Threads for <wbr/>Related <wbr/>Content</span></a></li></ul></li></ul></li><li><a href="#need-help"><span>Need <wbr/>Help?</span></a></li></ul></div></details></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>
|
|
@@ -0,0 +1,45 @@
|
|
|
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>MULTI_USER_AUTH | 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="" aria-current="page">MULTI_USER_AUTH</a></li></ul></div><div class="tsd-panel tsd-typography"><h1 id="multi-user-auth" class="tsd-anchor-link">Multi-User Auth<a href="#multi-user-auth" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h1><p>Connectors operate on threads that are often shared across users — the same Gmail thread, calendar event, or Linear issue appears as a single Plot thread for everyone involved. This guide covers the auth models and how the runtime routes per-user write-backs.</p>
|
|
2
|
+
<h2 id="auth-models" class="tsd-anchor-link">Auth Models<a href="#auth-models" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><table>
|
|
3
|
+
<thead>
|
|
4
|
+
<tr>
|
|
5
|
+
<th>Model</th>
|
|
6
|
+
<th>Use case</th>
|
|
7
|
+
<th>Example</th>
|
|
8
|
+
</tr>
|
|
9
|
+
</thead>
|
|
10
|
+
<tbody>
|
|
11
|
+
<tr>
|
|
12
|
+
<td>No auth</td>
|
|
13
|
+
<td>Twist doesn't need external credentials</td>
|
|
14
|
+
<td>Text-only twist</td>
|
|
15
|
+
</tr>
|
|
16
|
+
<tr>
|
|
17
|
+
<td>Individual auth (default)</td>
|
|
18
|
+
<td>Each user connects their own account</td>
|
|
19
|
+
<td>Google Calendar, Gmail, Linear</td>
|
|
20
|
+
</tr>
|
|
21
|
+
<tr>
|
|
22
|
+
<td>Shared auth (<code>shared: true</code>)</td>
|
|
23
|
+
<td>One credential, entered by the installer, used workspace-wide</td>
|
|
24
|
+
<td>Slack bot token, workspace API key</td>
|
|
25
|
+
</tr>
|
|
26
|
+
</tbody>
|
|
27
|
+
</table>
|
|
28
|
+
<h2 id="declaring-auth" class="tsd-anchor-link">Declaring Auth<a href="#declaring-auth" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><p>Connectors never build their own auth UI. Declare the provider and scopes as class properties and the runtime drives the OAuth flow from the connection setup modal:</p>
|
|
29
|
+
<pre><code class="typescript"><span class="hl-4">class</span><span class="hl-1"> </span><span class="hl-5">LinearConnector</span><span class="hl-1"> </span><span class="hl-4">extends</span><span class="hl-1"> </span><span class="hl-5">Connector</span><span class="hl-1"><</span><span class="hl-5">LinearConnector</span><span class="hl-1">> {</span><br/><span class="hl-1"> </span><span class="hl-4">readonly</span><span class="hl-1"> </span><span class="hl-2">provider</span><span class="hl-1"> = </span><span class="hl-2">AuthProvider</span><span class="hl-1">.</span><span class="hl-2">Linear</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-4">readonly</span><span class="hl-1"> </span><span class="hl-2">scopes</span><span class="hl-1"> = [</span><span class="hl-3">"read"</span><span class="hl-1">, </span><span class="hl-3">"write"</span><span class="hl-1">];</span><br/><span class="hl-1"> </span><span class="hl-7">// ...</span><br/><span class="hl-1">}</span>
|
|
30
|
+
</code><button type="button">Copy</button></pre>
|
|
31
|
+
|
|
32
|
+
<p>Key points:</p>
|
|
33
|
+
<ul>
|
|
34
|
+
<li><code>shared = true</code> — one credential is shared across all users in the workspace, entered once by the installer. The default (<code>false</code>) is per-user auth: each user connects their own account.</li>
|
|
35
|
+
<li><code>keyOption</code> — set to the name of a <code>secure: true</code> Options field to use API-key auth instead of OAuth. For individual connectors the key is stored per-user.</li>
|
|
36
|
+
<li>Read tokens with <code>this.tools.integrations.get(channelId)</code> — returns the token of the user who enabled sync on that channel, or <code>null</code> if the channel isn't enabled or the token is invalid.</li>
|
|
37
|
+
</ul>
|
|
38
|
+
<h2 id="per-user-auth-for-write-backs" class="tsd-anchor-link">Per-User Auth for Write-Backs<a href="#per-user-auth-for-write-backs" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><p>When a user acts on a shared thread — replying with a note, adding a reaction, changing a to-do or RSVP status — the runtime dispatches the change to <strong>the acting user's own connector instance</strong>, which is the only instance holding their OAuth token. Your callback (<code>onNoteCreated</code>, <code>onNoteUpdated</code>, <code>onNoteReactionChanged</code>, <code>onThreadToDo</code>, …) already runs under the acting user's auth: fetch the token through the connector's normal path and the external write is attributed to them automatically. No actor-switching step is required.</p>
|
|
39
|
+
<pre><code class="typescript"><span class="hl-2">async</span><span class="hl-1"> </span><span class="hl-6">onNoteCreated</span><span class="hl-1">(</span><span class="hl-2">note</span><span class="hl-1">: </span><span class="hl-2">Note</span><span class="hl-1">, </span><span class="hl-2">thread</span><span class="hl-1">: </span><span class="hl-2">Thread</span><span class="hl-1">): </span><span class="hl-5">Promise</span><span class="hl-1"><</span><span class="hl-2">NoteWriteBackResult</span><span class="hl-1"> | </span><span class="hl-4">void</span><span class="hl-1">> {</span><br/><span class="hl-1"> </span><span class="hl-7">// This instance belongs to the user who wrote the note, so this token is theirs.</span><br/><span class="hl-1"> const </span><span class="hl-2">token</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">tools</span><span class="hl-1">.</span><span class="hl-2">integrations</span><span class="hl-1">.</span><span class="hl-6">get</span><span class="hl-1">(</span><span class="hl-2">thread</span><span class="hl-1">.</span><span class="hl-2">meta</span><span class="hl-1">?.</span><span class="hl-2">channelId</span><span class="hl-1"> </span><span class="hl-0">as</span><span class="hl-1"> </span><span class="hl-5">string</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-6">if</span><span class="hl-1"> (!</span><span class="hl-2">token</span><span class="hl-1">) return;</span><br/><br/><span class="hl-1"> const </span><span class="hl-2">comment</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">addIssueComment</span><span class="hl-1">(</span><span class="hl-2">token</span><span class="hl-1">, </span><span class="hl-2">thread</span><span class="hl-1">.</span><span class="hl-2">meta</span><span class="hl-1">, </span><span class="hl-2">note</span><span class="hl-1">.</span><span class="hl-2">content</span><span class="hl-1"> ?? </span><span class="hl-3">""</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-7">// Returning { key, externalContent } lets the runtime set note.key AND</span><br/><span class="hl-1"> </span><span class="hl-7">// record the sync baseline so future re-syncs preserve Plot's markdown.</span><br/><span class="hl-1"> return { </span><span class="hl-15">key</span><span class="hl-1">: </span><span class="hl-3">`comment-</span><span class="hl-4">${</span><span class="hl-2">comment</span><span class="hl-13">.</span><span class="hl-2">id</span><span class="hl-4">}</span><span class="hl-3">`</span><span class="hl-1">, </span><span class="hl-15">externalContent</span><span class="hl-1">: </span><span class="hl-2">comment</span><span class="hl-1">.</span><span class="hl-2">body</span><span class="hl-1"> };</span><br/><span class="hl-1">}</span>
|
|
40
|
+
</code><button type="button">Copy</button></pre>
|
|
41
|
+
|
|
42
|
+
<h3 id="when-the-acting-user-has-no-connection" class="tsd-anchor-link">When the Acting User Has No Connection<a href="#when-the-acting-user-has-no-connection" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p>If the acting user has no connection of this type, the change is saved in Plot but no write-back dispatch fires — there is no connector instance with their credentials to deliver it to. The thread stays consistent in Plot; the external system simply doesn't receive that user's change.</p>
|
|
43
|
+
<p>This also means connectors don't need a "fall back to the installer's credentials" code path: dispatch routing already guarantees a write-back callback only runs with the acting user's own credentials.</p>
|
|
44
|
+
<h2 id="cross-user-thread-sharing" class="tsd-anchor-link">Cross-User Thread Sharing<a href="#cross-user-thread-sharing" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><p>Auth is per-user, but the synced data converges: when several users' connectors sync the same external item (the same <code>source</code>), they share a single Plot thread. Each user gains access when their own connector instance syncs the item — populating <code>thread.contacts</code> with recipients does not by itself admit them. See <code>connectors/AGENTS.md</code> → "<code>source</code> — idempotency + cross-user dedup" and "Attestation-based visibility" for the full contract.</p>
|
|
45
|
+
</div></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><details open class="tsd-accordion tsd-page-navigation"><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>On This Page</h3></summary><div class="tsd-accordion-details"><a href="#multi-user-auth"><span>Multi-<wbr/>User <wbr/>Auth</span></a><ul><li><a href="#auth-models"><span>Auth <wbr/>Models</span></a></li><li><a href="#declaring-auth"><span>Declaring <wbr/>Auth</span></a></li><li><a href="#per-user-auth-for-write-backs"><span>Per-<wbr/>User <wbr/>Auth for <wbr/>Write-<wbr/>Backs</span></a></li><li><ul><li><a href="#when-the-acting-user-has-no-connection"><span>When the <wbr/>Acting <wbr/>User <wbr/>Has <wbr/>No <wbr/>Connection</span></a></li></ul></li><li><a href="#cross-user-thread-sharing"><span>Cross-<wbr/>User <wbr/>Thread <wbr/>Sharing</span></a></li></ul></div></details></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>
|