@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
|
@@ -22,8 +22,12 @@ connectors/<name>/
|
|
|
22
22
|
{
|
|
23
23
|
"name": "@plotday/connector-<name>",
|
|
24
24
|
"private": true,
|
|
25
|
+
"plotTwistId": "<uuid>",
|
|
25
26
|
"displayName": "Human Name",
|
|
26
27
|
"description": "One-line purpose statement",
|
|
28
|
+
"logoUrl": "https://api.iconify.design/logos/<name>-icon.svg",
|
|
29
|
+
"publisher": "Plot",
|
|
30
|
+
"publisherUrl": "https://plot.day",
|
|
27
31
|
"author": "Plot <team@plot.day> (https://plot.day)",
|
|
28
32
|
"license": "MIT",
|
|
29
33
|
"version": "0.1.0",
|
|
@@ -37,8 +41,7 @@ connectors/<name>/
|
|
|
37
41
|
"default": "./dist/index.js"
|
|
38
42
|
}
|
|
39
43
|
},
|
|
40
|
-
"
|
|
41
|
-
"scripts": { "build": "tsc", "clean": "rm -rf dist" },
|
|
44
|
+
"scripts": { "build": "tsc", "clean": "rm -rf dist", "lint": "plot lint", "deploy": "plot deploy" },
|
|
42
45
|
"dependencies": { "@plotday/twister": "workspace:^" },
|
|
43
46
|
"devDependencies": { "typescript": "^5.9.3" },
|
|
44
47
|
"repository": { "type": "git", "url": "https://github.com/plotday/plot.git", "directory": "connectors/<name>" },
|
|
@@ -48,6 +51,7 @@ connectors/<name>/
|
|
|
48
51
|
```
|
|
49
52
|
|
|
50
53
|
- `"@plotday/connector"` export condition resolves to TS source during workspace dev.
|
|
54
|
+
- `plotTwistId` is the connector's stable twist UUID — `plot create --connector` generates one; `plot deploy` reads it along with `displayName`, `description`, `logoUrl`/`logoUrlDark`, and `publisher`.
|
|
51
55
|
- Add third-party SDKs to `dependencies` (e.g. `"@linear/sdk": "^72.0.0"`).
|
|
52
56
|
- Add `@plotday/connector-google-contacts` as `"workspace:^"` if you sync contacts (Google connectors only).
|
|
53
57
|
|
|
@@ -68,47 +72,47 @@ Use `connectors/linear/` as the canonical reference. Minimum shape:
|
|
|
68
72
|
|
|
69
73
|
```typescript
|
|
70
74
|
import {
|
|
71
|
-
|
|
72
|
-
type
|
|
75
|
+
Connector,
|
|
76
|
+
type NewLinkWithNotes, type ToolBuilder,
|
|
73
77
|
} from "@plotday/twister";
|
|
74
|
-
import { type Callback, Callbacks } from "@plotday/twister/tools/callbacks";
|
|
75
78
|
import {
|
|
76
79
|
AuthProvider, Integrations,
|
|
77
80
|
type AuthToken, type Authorization, type Channel,
|
|
81
|
+
type StatusIcon, type SyncContext,
|
|
78
82
|
} from "@plotday/twister/tools/integrations";
|
|
79
83
|
import { Network, type WebhookRequest } from "@plotday/twister/tools/network";
|
|
80
|
-
import { Tasks } from "@plotday/twister/tools/tasks";
|
|
81
84
|
|
|
82
85
|
export class MyConnector extends Connector<MyConnector> {
|
|
83
|
-
static readonly PROVIDER = AuthProvider.Linear;
|
|
84
|
-
static readonly SCOPES = ["read", "write"];
|
|
85
|
-
static readonly Options: SyncToolOptions;
|
|
86
86
|
static readonly handleReplies = true; // only for bidirectional connectors
|
|
87
|
-
declare readonly Options: SyncToolOptions;
|
|
88
87
|
|
|
89
|
-
|
|
88
|
+
readonly provider = AuthProvider.Linear;
|
|
89
|
+
readonly scopes = ["read", "write"]; // or a ScopeConfig: { required, optional }
|
|
90
|
+
readonly linkTypes = [{
|
|
91
|
+
type: "issue",
|
|
92
|
+
label: "Issue",
|
|
93
|
+
statuses: [
|
|
94
|
+
{ status: "unstarted", label: "To Do", icon: "todo" as StatusIcon },
|
|
95
|
+
{ status: "completed", label: "Done", done: true, icon: "done" as StatusIcon },
|
|
96
|
+
],
|
|
97
|
+
}];
|
|
98
|
+
|
|
99
|
+
build(build: ToolBuilder) {
|
|
90
100
|
return {
|
|
91
|
-
integrations: build(Integrations,
|
|
92
|
-
providers: [{
|
|
93
|
-
provider: MyConnector.PROVIDER,
|
|
94
|
-
scopes: MyConnector.SCOPES,
|
|
95
|
-
getChannels: this.getChannels,
|
|
96
|
-
onChannelEnabled: this.onChannelEnabled,
|
|
97
|
-
onChannelDisabled: this.onChannelDisabled,
|
|
98
|
-
}],
|
|
99
|
-
}),
|
|
101
|
+
integrations: build(Integrations),
|
|
100
102
|
network: build(Network, { urls: ["https://api.example.com/*"] }),
|
|
101
|
-
callbacks: build(Callbacks),
|
|
102
|
-
tasks: build(Tasks),
|
|
103
103
|
};
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
async getChannels(_auth: Authorization, token: AuthToken): Promise<Channel[]> { /* list resources */ }
|
|
106
|
+
async getChannels(_auth: Authorization | null, token: AuthToken | null): Promise<Channel[]> { /* list resources */ }
|
|
107
107
|
|
|
108
|
-
async onChannelEnabled(channel: Channel): Promise<void> {
|
|
109
|
-
//
|
|
110
|
-
//
|
|
111
|
-
//
|
|
108
|
+
async onChannelEnabled(channel: Channel, context?: SyncContext): Promise<void> {
|
|
109
|
+
// Runs inline in the HTTP request handler — only this.set()/this.get()/
|
|
110
|
+
// this.callback()/this.runTask() belong here. Queue webhook setup +
|
|
111
|
+
// initial sync as SEPARATE tasks via this.runTask(), never inline.
|
|
112
|
+
// Can be re-dispatched (auto-enable, recovery: context.recovering) —
|
|
113
|
+
// overwrite stored state unconditionally, don't skip-if-present.
|
|
114
|
+
// Call integrations.channelSyncCompleted(channel.id) once the initial
|
|
115
|
+
// backfill finishes (from the last syncBatch, not from here).
|
|
112
116
|
}
|
|
113
117
|
|
|
114
118
|
async onChannelDisabled(channel: Channel): Promise<void> {
|
|
@@ -119,18 +123,22 @@ export class MyConnector extends Connector<MyConnector> {
|
|
|
119
123
|
export default MyConnector;
|
|
120
124
|
```
|
|
121
125
|
|
|
126
|
+
The runtime reads `provider`, `scopes`, and `linkTypes` from the class and drives OAuth and channel management automatically. The built-in `callbacks`, `store`, and `tasks` tools are always available (`this.callback()`, `this.set()`/`this.get()`/`this.clear()`, `this.runTask()`) and need no `build()` entry.
|
|
127
|
+
|
|
122
128
|
Required private helpers: `getClient(channelId)`, `setupWebhook(id)`, `startBatchSync(id)`, `syncBatch(id)`, `transformItem(item, id, initialSync)`, `onWebhook(req, id)`. See `linear/` for the full pattern.
|
|
123
129
|
|
|
124
130
|
## Integrations (auth + channels)
|
|
125
131
|
|
|
126
|
-
Auth is handled in the Flutter edit modal — you declare
|
|
132
|
+
Auth is handled in the Flutter edit modal — you declare `provider` and `scopes` as class properties, the runtime drives OAuth.
|
|
127
133
|
|
|
128
134
|
1. User clicks "Connect" → OAuth runs automatically.
|
|
129
135
|
2. Runtime calls your `getChannels()` to list resources.
|
|
130
136
|
3. User enables → `onChannelEnabled()`. User disables → `onChannelDisabled()`.
|
|
131
|
-
4. Read tokens via `this.tools.integrations.get(
|
|
137
|
+
4. Read tokens via `this.tools.integrations.get(channelId)`.
|
|
138
|
+
|
|
139
|
+
`AuthProvider` values: `Google`, `Microsoft`, `Notion`, `Slack`, `Atlassian`, `Linear`, `Monday`, `GitHub`, `Asana`, `HubSpot`, `Todoist`, `Airtable`.
|
|
132
140
|
|
|
133
|
-
`
|
|
141
|
+
`scopes` may be a flat array (all required) or a `ScopeConfig` (`{ required, optional }`) whose optional scope groups render as connect-time toggles; detect declined groups via the granted `token.scopes` and degrade gracefully (see `slack/` and `google-calendar/`). Connectors without OAuth (API keys, CalDAV credentials) omit `provider` and collect credentials via the `Options` tool with `secure: true` fields (see `attio/`, `fellow/`, `apple-calendar/`).
|
|
134
142
|
|
|
135
143
|
### Per-user auth for write-backs
|
|
136
144
|
|
|
@@ -145,7 +153,7 @@ Plot but is not dispatched — there is no instance to deliver to.
|
|
|
145
153
|
|
|
146
154
|
### Cross-connector auth sharing (Google)
|
|
147
155
|
|
|
148
|
-
|
|
156
|
+
Set `readonly scopes = Integrations.MergeScopes(MyGoogleConnector.SCOPES, GoogleContacts.SCOPES)` and add `googleContacts: build(GoogleContacts)` to your `build()` return (see `gmail/`, `google-drive/`). Alternatively declare the contacts scopes as an optional `ScopeConfig` group so the user can decline them (see `google-calendar/`).
|
|
149
157
|
|
|
150
158
|
## Architecture
|
|
151
159
|
|
|
@@ -156,25 +164,32 @@ Connectors persist data directly via `integrations.saveLink()` (building `NewLin
|
|
|
156
164
|
Functions are not serializable across worker boundaries. Convert to tokens, store primitives.
|
|
157
165
|
|
|
158
166
|
```typescript
|
|
167
|
+
import { type Callback } from "@plotday/twister/tools/callbacks";
|
|
168
|
+
|
|
159
169
|
// ❌ WRONG — passing a function as a callback arg
|
|
160
|
-
await this.callback(this.syncBatch,
|
|
161
|
-
// Error:
|
|
162
|
-
|
|
163
|
-
// ✅ CORRECT
|
|
164
|
-
const
|
|
165
|
-
await this.
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
170
|
+
await this.callback(this.syncBatch, this.onItem);
|
|
171
|
+
// Error: Found function at path "value[0]"
|
|
172
|
+
|
|
173
|
+
// ✅ CORRECT — callback args are serializable primitives only
|
|
174
|
+
const batch = await this.callback(this.syncBatch, resourceId);
|
|
175
|
+
await this.runTask(batch);
|
|
176
|
+
|
|
177
|
+
// To invoke something later (scheduled renewals, stored continuations),
|
|
178
|
+
// persist the token, not the function:
|
|
179
|
+
const token = await this.callback(this.renewWatch, resourceId);
|
|
180
|
+
await this.set(`renewal_${resourceId}`, token);
|
|
181
|
+
|
|
182
|
+
// Later:
|
|
183
|
+
const stored = await this.get<Callback>(`renewal_${resourceId}`);
|
|
184
|
+
if (!stored) throw new Error(`Callback not found for ${resourceId}`);
|
|
185
|
+
await this.run(stored);
|
|
173
186
|
```
|
|
174
187
|
|
|
175
188
|
Serializable: strings, numbers, booleans, `null`, plain objects, arrays, Dates (SuperJSON), callback tokens.
|
|
176
189
|
Not serializable: functions, `undefined` (use `null`), symbols, RPC stubs, circular refs.
|
|
177
190
|
|
|
191
|
+
(`tools.callbacks.createFromParent()` exists for tokenizing a function handed in from a parent twist/tool — regular connectors don't need it.)
|
|
192
|
+
|
|
178
193
|
## Callback backward compatibility
|
|
179
194
|
|
|
180
195
|
Deployed callbacks auto-upgrade to new connector versions. Signatures must stay compatible:
|
|
@@ -191,14 +206,12 @@ async syncBatch(batchNumber: number, resourceId: string, initialSync?: boolean)
|
|
|
191
206
|
}
|
|
192
207
|
```
|
|
193
208
|
|
|
194
|
-
For breaking changes, do migration in `
|
|
209
|
+
For breaking changes, do migration in `upgrade()` (called once per active instance when a new version deploys — e.g. clear stale locks, see `gmail/`, `google-calendar/`).
|
|
195
210
|
|
|
196
211
|
## Storage key conventions
|
|
197
212
|
|
|
198
213
|
| Key | Purpose |
|
|
199
214
|
|---|---|
|
|
200
|
-
| `item_callback_<id>` | Token for parent's `onItem` |
|
|
201
|
-
| `disable_callback_<id>` | Token for parent's `onChannelDisabled` |
|
|
202
215
|
| `sync_state_<id>` | Current batch pagination state |
|
|
203
216
|
| `sync_enabled_<id>` | Boolean tracking enabled state |
|
|
204
217
|
| `webhook_id_<id>` | External webhook registration id |
|
|
@@ -207,7 +220,7 @@ For breaking changes, do migration in `preUpgrade()` (e.g. clear stale locks).
|
|
|
207
220
|
|
|
208
221
|
## `source` — idempotency + cross-user dedup (CRITICAL)
|
|
209
222
|
|
|
210
|
-
`
|
|
223
|
+
`link.source` is the upsert key AND the cross-user dedup key: two instances emitting the same `source` converge on a single shared thread across users (that's how two users on the same Gmail message share one thread).
|
|
211
224
|
|
|
212
225
|
**Your `source` must be globally unique for the external item, not merely unique within a user's account.** If two different users' connectors could emit the same string for different items, include a qualifier (workspace, tenant, mailbox, project).
|
|
213
226
|
|
|
@@ -233,6 +246,8 @@ Pick the format up front — retrofits require a backfill migration.
|
|
|
233
246
|
|
|
234
247
|
**Mutable ids:** use the immutable id in `source`, store the mutable key in `meta` only (e.g. Jira issue id in `source`, issue key in `meta`).
|
|
235
248
|
|
|
249
|
+
**Cross-connector bundling:** `link.sources` (plural) carries additional canonical aliases — any element shared with another link's `sources` bundles the two onto one thread. E.g. calendar connectors emit an `icaluid:<iCalUID>` alias so meeting-notes connectors (Fellow, Granola) can attach to the event's thread.
|
|
250
|
+
|
|
236
251
|
### Attestation-based visibility
|
|
237
252
|
|
|
238
253
|
Populating `thread.contacts` with recipients does NOT automatically admit them. The runtime requires each user's own connector to sync the item before they get a `thread_priority` row. Users whose sync lands first go to `thread.pending_contacts` and are promoted on the next attester's sync. You just populate `contacts` with every recipient you see — the runtime's `upsert_thread` handles the rest.
|
|
@@ -266,12 +281,17 @@ Previews (`preview` fields) always use plain text — `snippet` or truncated tit
|
|
|
266
281
|
|
|
267
282
|
## Sync metadata injection
|
|
268
283
|
|
|
269
|
-
Every synced
|
|
284
|
+
Every synced link must carry provider and channel metadata — bulk operations (e.g. `integrations.archiveLinks({ channelId })` on disable) rely on it:
|
|
270
285
|
|
|
271
286
|
```typescript
|
|
272
|
-
|
|
287
|
+
link.channelId = resourceId; // first-class field on NewLink
|
|
288
|
+
link.meta = { ...link.meta, syncProvider: "myprovider" };
|
|
273
289
|
```
|
|
274
290
|
|
|
291
|
+
## Classifier facets (optional)
|
|
292
|
+
|
|
293
|
+
Messaging-style connectors may set `link.facets` (`format` / `automation` / `reach` from `@plotday/twister/facets`) as internal classifier signal. Set a dimension only when a heuristic is confident; leave it `null`/omitted otherwise. See `gmail/src/gmail-facets.ts` and `slack/src/slack-facets.ts`.
|
|
294
|
+
|
|
275
295
|
## Initial vs incremental sync (REQUIRED)
|
|
276
296
|
|
|
277
297
|
Missing this causes notification spam from bulk historical imports.
|
|
@@ -282,12 +302,12 @@ Missing this causes notification spam from bulk historical imports.
|
|
|
282
302
|
| `archived` | `false` | *omit* |
|
|
283
303
|
|
|
284
304
|
```typescript
|
|
285
|
-
const
|
|
305
|
+
const link = {
|
|
286
306
|
...(initialSync ? { unread: false, archived: false } : {}),
|
|
287
307
|
};
|
|
288
308
|
```
|
|
289
309
|
|
|
290
|
-
The flag must flow from entry point through every batch to the
|
|
310
|
+
The flag must flow from entry point through every batch to the link-creation site.
|
|
291
311
|
|
|
292
312
|
- **Pattern A — store in SyncState**: include `initialSync: boolean` in your state type; set `true` in `startBatchSync`, preserve across batches, webhooks pass `false`.
|
|
293
313
|
- **Pattern B — pass as callback arg**: make it the last, optional param (for backward compat) and propagate: `async syncBatch(batch: number, mode: "full"|"incremental", channelId: string, initialSync?: boolean)`. Used by connectors like Gmail.
|
|
@@ -325,11 +345,12 @@ if (taskToken) await this.set(`watch_renewal_task_${resourceId}`, taskToken);
|
|
|
325
345
|
## Bidirectional sync
|
|
326
346
|
|
|
327
347
|
```typescript
|
|
328
|
-
//
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
const
|
|
332
|
-
|
|
348
|
+
// Write back status/assignee changes the user makes in Plot on links this
|
|
349
|
+
// connector created (dispatched by the runtime)
|
|
350
|
+
async onLinkUpdated(link: Link): Promise<void> {
|
|
351
|
+
const externalId = link.meta?.externalId as string;
|
|
352
|
+
const client = await this.getClient(link.channelId ?? (link.meta?.resourceId as string));
|
|
353
|
+
await client.updateItem(externalId, { title: link.title, status: /* map link.status */ });
|
|
333
354
|
}
|
|
334
355
|
|
|
335
356
|
// Post a comment. Return a NoteWriteBackResult with externalContent so the
|
|
@@ -395,9 +416,9 @@ Opt a link type in by adding a `compose` block to its `LinkTypeConfig`:
|
|
|
395
416
|
type: "issue",
|
|
396
417
|
label: "Issue",
|
|
397
418
|
statuses: [
|
|
398
|
-
{ status: "backlog", label: "Backlog" },
|
|
399
|
-
{ status: "unstarted", label: "To Do" },
|
|
400
|
-
{ status: "completed", label: "Done", done: true },
|
|
419
|
+
{ status: "backlog", label: "Backlog", icon: "backlog" as StatusIcon },
|
|
420
|
+
{ status: "unstarted", label: "To Do", icon: "todo" as StatusIcon },
|
|
421
|
+
{ status: "completed", label: "Done", done: true, icon: "done" as StatusIcon },
|
|
401
422
|
],
|
|
402
423
|
compose: { status: "unstarted" }, // targets defaults to "channels"
|
|
403
424
|
}
|
|
@@ -432,7 +453,7 @@ async onCreateLink(draft: CreateLinkDraft): Promise<NewLinkWithNotes | null> {
|
|
|
432
453
|
}
|
|
433
454
|
```
|
|
434
455
|
|
|
435
|
-
`CreateLinkDraft`: `channelId`, `type`, `status
|
|
456
|
+
`CreateLinkDraft`: `channelId`, `type`, `status` (`null` for status-less link types), `title`, `noteContent`, `contacts: Actor[]`, plus — for `compose.targets: "contacts"`/`"addresses"` — `recipients?: ResolvedRecipient[]` (contacts pre-resolved to platform account IDs with their thread `role`) and `inviteEmails?: string[]` (free-form typed addresses). See `twister/src/connector.ts`.
|
|
436
457
|
|
|
437
458
|
Resolve category statuses (`"unstarted"`, etc.) to the provider's state id yourself — the draft's status is whatever the picker showed.
|
|
438
459
|
|
|
@@ -443,11 +464,16 @@ The returned link is written with `updated_by` set to the twist, so subsequent s
|
|
|
443
464
|
Contacts are created implicitly when you save threads/links — no `addContacts()` call, no `ContactAccess.Write`.
|
|
444
465
|
|
|
445
466
|
```typescript
|
|
446
|
-
const author: NewContact | undefined = creator
|
|
447
|
-
? {
|
|
467
|
+
const author: NewContact | undefined = creator
|
|
468
|
+
? {
|
|
469
|
+
...(creator.email ? { email: creator.email } : {}),
|
|
470
|
+
name: creator.name ?? "",
|
|
471
|
+
avatar: creator.avatarUrl ?? undefined,
|
|
472
|
+
source: { accountId: creator.id }, // platform identity, resolves without email
|
|
473
|
+
}
|
|
448
474
|
: undefined;
|
|
449
475
|
|
|
450
|
-
const
|
|
476
|
+
const link: NewLinkWithNotes = {
|
|
451
477
|
author,
|
|
452
478
|
assignee: assigneeContact ?? null,
|
|
453
479
|
notes: [{ author /* note-level author too */ }],
|
|
@@ -468,8 +494,8 @@ declare const Buffer: {
|
|
|
468
494
|
## Build & test
|
|
469
495
|
|
|
470
496
|
```bash
|
|
471
|
-
cd
|
|
472
|
-
cd
|
|
497
|
+
cd connectors/<name> && pnpm build
|
|
498
|
+
cd connectors/<name> && pnpm exec tsc --noEmit
|
|
473
499
|
pnpm install # from repo root
|
|
474
500
|
```
|
|
475
501
|
|
|
@@ -477,19 +503,20 @@ Add to `pnpm-workspace.yaml` if not already covered by a glob.
|
|
|
477
503
|
|
|
478
504
|
## Checklist
|
|
479
505
|
|
|
480
|
-
- [ ] Extend `Connector<YourConnector>`; declare `
|
|
481
|
-
- [ ] `build()` declares Integrations
|
|
506
|
+
- [ ] Extend `Connector<YourConnector>`; declare `readonly provider`, `readonly scopes`, `readonly linkTypes`
|
|
507
|
+
- [ ] `build()` declares Integrations and Network (plus GoogleContacts/Files if applicable) — `callbacks`/`store`/`tasks` are built-in
|
|
482
508
|
- [ ] Set `handleReplies = true` only if bidirectional
|
|
483
509
|
- [ ] For bidirectional note sync: `onNoteCreated` / `onNoteUpdated` return `NoteWriteBackResult` with `externalContent` matching what sync-in will emit for this note — no `Promise<string | void>` in new connectors
|
|
484
510
|
- [ ] For bidirectional note sync: implement `onNoteUpdated` if the external supports editing (document the gap if it doesn't)
|
|
485
511
|
- [ ] `onChannelEnabled` uses `runTask()` (NOT `run()`) for webhook setup and initial sync — blocks HTTP response otherwise
|
|
486
|
-
- [ ]
|
|
512
|
+
- [ ] `onChannelEnabled` is idempotent (overwrites state) — it re-fires on auto-enable and recovery (`context.recovering`)
|
|
513
|
+
- [ ] Call `integrations.channelSyncCompleted(channelId)` exactly once when the initial backfill finishes
|
|
487
514
|
- [ ] Never pass functions, RPC stubs, or `undefined` to `this.callback()` — use `null`
|
|
488
|
-
- [ ] Validate
|
|
515
|
+
- [ ] Validate stored callback tokens exist before `this.run()`
|
|
489
516
|
- [ ] Localhost guard in webhook setup; verify webhook signatures
|
|
490
517
|
- [ ] Canonical, globally-unique `source` using immutable ids; mutable keys in `meta` only
|
|
491
518
|
- [ ] `note.key` for note-level upserts
|
|
492
|
-
- [ ]
|
|
519
|
+
- [ ] Set `link.channelId` and inject `syncProvider` into `link.meta`
|
|
493
520
|
- [ ] `contentType: "html"` for HTML — never strip tags locally
|
|
494
521
|
- [ ] `created` on notes = external timestamp, not sync time
|
|
495
522
|
- [ ] `initialSync` propagated through every entry point and batch; set `unread: false, archived: false` on initial, omit on incremental
|
|
@@ -501,14 +528,14 @@ Add to `pnpm-workspace.yaml` if not already covered by a glob.
|
|
|
501
528
|
## Common pitfalls
|
|
502
529
|
|
|
503
530
|
1. Passing functions/`undefined`/RPC stubs to `this.callback()` → use tokens + `null`.
|
|
504
|
-
2. Forgetting sync metadata (`
|
|
531
|
+
2. Forgetting sync metadata (`link.channelId`, `meta.syncProvider`) → breaks bulk archive on disable.
|
|
505
532
|
3. Not propagating `initialSync` through the whole pipeline → notification spam.
|
|
506
533
|
4. Mutable ids in `source` (e.g. Jira issue key) → use immutable id, store key in `meta`.
|
|
507
534
|
5. `source` that's only unique within one user's account → breaks cross-user dedup; add workspace/tenant/mailbox qualifier.
|
|
508
535
|
6. Not breaking long loops into batches → each execution has ~1000 request limit.
|
|
509
536
|
7. Missing localhost guard → webhook registration fails silently.
|
|
510
537
|
8. Calling `plot.createThread()` from a connector → use `integrations.saveLink()`.
|
|
511
|
-
9. Breaking callback signatures → add optional params at end only; use `
|
|
538
|
+
9. Breaking callback signatures → add optional params at end only; use `upgrade()` for breaking migrations.
|
|
512
539
|
10. Not cleaning up on disable → orphan callbacks, webhooks, state.
|
|
513
540
|
11. Two-way sync without metadata correlation → embed Plot id in external metadata to prevent race-condition duplicates (see SYNC_STRATEGIES.md §6).
|
|
514
541
|
12. Stripping HTML locally → breaks encoding + loses links; use `contentType: "html"`.
|
|
@@ -533,4 +560,4 @@ Add to `pnpm-workspace.yaml` if not already covered by a glob.
|
|
|
533
560
|
| `jira/` | ProjectConnector | Immutable vs mutable ids; comment metadata dedup |
|
|
534
561
|
| `asana/` | ProjectConnector | HMAC webhook verification; section-based projects |
|
|
535
562
|
| `outlook-calendar/` | CalendarConnector | Microsoft Graph; subscription management |
|
|
536
|
-
| `google-contacts/` | Supporting | Contact sync;
|
|
563
|
+
| `google-contacts/` | Supporting | Contact sync; shared Google auth consumed by other connectors via `MergeScopes` |
|
package/dist/docs/modules.html
CHANGED
|
@@ -1 +1 @@
|
|
|
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>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"></ul><h1>Creating Plot Twists</h1></div><details class="tsd-panel-group tsd-member-group tsd-accordion" open><summary class="tsd-accordion-summary" data-key="section-Guides"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-chevronDown"></use></svg><h2>Guides</h2></summary><dl class="tsd-member-summaries"><dt class="tsd-member-summary" id="getting-started-1"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Document"><use href="assets/icons.svg#icon-8388608"></use></svg><a href="documents/Getting_Started.html">Getting Started</a><a href="#getting-started-1" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="core-concepts"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Document"><use href="assets/icons.svg#icon-8388608"></use></svg><a href="documents/Core_Concepts.html">Core Concepts</a><a href="#core-concepts" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="built-in-tools"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Document"><use href="assets/icons.svg#icon-8388608"></use></svg><a href="documents/Built-in_Tools.html">Built-in Tools</a><a href="#built-in-tools" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="building-connectors"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Document"><use href="assets/icons.svg#icon-8388608"></use></svg><a href="documents/Building_Connectors.html">Building Connectors</a><a href="#building-connectors" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="cli-reference"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Document"><use href="assets/icons.svg#icon-8388608"></use></svg><a href="documents/CLI_Reference.html">CLI Reference</a><a href="#cli-reference" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="runtime-environment"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Document"><use href="assets/icons.svg#icon-8388608"></use></svg><a href="documents/Runtime_Environment.html">Runtime Environment</a><a href="#runtime-environment" 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></span></dt><dd class="tsd-member-summary"></dd></dl></details><details class="tsd-panel-group tsd-member-group tsd-accordion" open><summary class="tsd-accordion-summary" data-key="section-Modules"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-chevronDown"></use></svg><h2>Modules</h2></summary><dl class="tsd-member-summaries"><dt class="tsd-member-summary" id="index"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><a href="modules/index.html">index</a><a href="#index" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="plot"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><a href="modules/plot.html">plot</a><a href="#plot" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="tag"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><a href="modules/tag.html">tag</a><a href="#tag" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="tool"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><a href="modules/tool.html">tool</a><a href="#tool" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="toolsai"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><a href="modules/tools_ai.html">tools/ai</a><a href="#toolsai" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="toolscallbacks"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><a href="modules/tools_callbacks.html">tools/callbacks</a><a href="#toolscallbacks" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="toolsintegrations"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><a href="modules/tools_integrations.html">tools/integrations</a><a href="#toolsintegrations" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="toolsnetwork"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><a href="modules/tools_network.html">tools/network</a><a href="#toolsnetwork" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="toolsplot"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><a href="modules/tools_plot.html">tools/plot</a><a href="#toolsplot" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="toolsstore"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><a href="modules/tools_store.html">tools/store</a><a href="#toolsstore" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="toolstasks"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><a href="modules/tools_tasks.html">tools/tasks</a><a href="#toolstasks" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="toolstwists"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><a href="modules/tools_twists.html">tools/twists</a><a href="#toolstwists" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="twist"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><a href="modules/twist.html">twist</a><a href="#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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="utilshash"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><a href="modules/utils_hash.html">utils/hash</a><a href="#utilshash" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="utilstypes"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><a href="modules/utils_types.html">utils/types</a><a href="#utilstypes" 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></span></dt><dd class="tsd-member-summary"></dd></dl></details></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"><details open class="tsd-accordion tsd-page-navigation-section"><summary class="tsd-accordion-summary" data-key="section-Guides"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-chevronDown"></use></svg>Guides</summary><div><a href="#getting-started-1"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Document"><use href="assets/icons.svg#icon-8388608"></use></svg><span>Getting <wbr/>Started</span></a><a href="#core-concepts"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Document"><use href="assets/icons.svg#icon-8388608"></use></svg><span>Core <wbr/>Concepts</span></a><a href="#built-in-tools"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Document"><use href="assets/icons.svg#icon-8388608"></use></svg><span>Built-<wbr/>in <wbr/>Tools</span></a><a href="#building-connectors"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Document"><use href="assets/icons.svg#icon-8388608"></use></svg><span>Building <wbr/>Connectors</span></a><a href="#cli-reference"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Document"><use href="assets/icons.svg#icon-8388608"></use></svg><span>CLI <wbr/>Reference</span></a><a href="#runtime-environment"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Document"><use href="assets/icons.svg#icon-8388608"></use></svg><span>Runtime <wbr/>Environment</span></a></div></details><details open class="tsd-accordion tsd-page-navigation-section"><summary class="tsd-accordion-summary" data-key="section-Modules"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-chevronDown"></use></svg>Modules</summary><div><a href="#index"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><span>index</span></a><a href="#plot"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><span>plot</span></a><a href="#tag"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><span>tag</span></a><a href="#tool"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><span>tool</span></a><a href="#toolsai"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><span>tools/ai</span></a><a href="#toolscallbacks"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><span>tools/callbacks</span></a><a href="#toolsintegrations"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><span>tools/integrations</span></a><a href="#toolsnetwork"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><span>tools/network</span></a><a href="#toolsplot"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><span>tools/plot</span></a><a href="#toolsstore"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><span>tools/store</span></a><a href="#toolstasks"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><span>tools/tasks</span></a><a href="#toolstwists"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><span>tools/twists</span></a><a href="#twist"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><span>twist</span></a><a href="#utilshash"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><span>utils/hash</span></a><a href="#utilstypes"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><span>utils/types</span></a></div></details></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" class="current">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>
|
|
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>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"></ul><h1>Creating Plot Twists</h1></div><details class="tsd-panel-group tsd-member-group tsd-accordion" open><summary class="tsd-accordion-summary" data-key="section-Documents"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-chevronDown"></use></svg><h2>Documents</h2></summary><dl class="tsd-member-summaries"><dt class="tsd-member-summary" id="sync_strategies"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Document"><use href="assets/icons.svg#icon-8388608"></use></svg><a href="documents/SYNC_STRATEGIES.html">SYNC_STRATEGIES</a><a href="#sync_strategies" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="multi_user_auth"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Document"><use href="assets/icons.svg#icon-8388608"></use></svg><a href="documents/MULTI_USER_AUTH.html">MULTI_USER_AUTH</a><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></span></dt><dd class="tsd-member-summary"></dd></dl></details><details class="tsd-panel-group tsd-member-group tsd-accordion" open><summary class="tsd-accordion-summary" data-key="section-Guides"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-chevronDown"></use></svg><h2>Guides</h2></summary><dl class="tsd-member-summaries"><dt class="tsd-member-summary" id="getting-started-1"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Document"><use href="assets/icons.svg#icon-8388608"></use></svg><a href="documents/Getting_Started.html">Getting Started</a><a href="#getting-started-1" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="core-concepts"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Document"><use href="assets/icons.svg#icon-8388608"></use></svg><a href="documents/Core_Concepts.html">Core Concepts</a><a href="#core-concepts" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="built-in-tools"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Document"><use href="assets/icons.svg#icon-8388608"></use></svg><a href="documents/Built-in_Tools.html">Built-in Tools</a><a href="#built-in-tools" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="building-connectors"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Document"><use href="assets/icons.svg#icon-8388608"></use></svg><a href="documents/Building_Connectors.html">Building Connectors</a><a href="#building-connectors" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="cli-reference"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Document"><use href="assets/icons.svg#icon-8388608"></use></svg><a href="documents/CLI_Reference.html">CLI Reference</a><a href="#cli-reference" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="runtime-environment"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Document"><use href="assets/icons.svg#icon-8388608"></use></svg><a href="documents/Runtime_Environment.html">Runtime Environment</a><a href="#runtime-environment" 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></span></dt><dd class="tsd-member-summary"></dd></dl></details><details class="tsd-panel-group tsd-member-group tsd-accordion" open><summary class="tsd-accordion-summary" data-key="section-Modules"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-chevronDown"></use></svg><h2>Modules</h2></summary><dl class="tsd-member-summaries"><dt class="tsd-member-summary" id="index"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><a href="modules/index.html">index</a><a href="#index" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="plot"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><a href="modules/plot.html">plot</a><a href="#plot" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="tag"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><a href="modules/tag.html">tag</a><a href="#tag" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="tool"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><a href="modules/tool.html">tool</a><a href="#tool" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="toolsai"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><a href="modules/tools_ai.html">tools/ai</a><a href="#toolsai" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="toolscallbacks"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><a href="modules/tools_callbacks.html">tools/callbacks</a><a href="#toolscallbacks" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="toolsintegrations"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><a href="modules/tools_integrations.html">tools/integrations</a><a href="#toolsintegrations" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="toolsnetwork"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><a href="modules/tools_network.html">tools/network</a><a href="#toolsnetwork" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="toolsplot"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><a href="modules/tools_plot.html">tools/plot</a><a href="#toolsplot" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="toolsstore"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><a href="modules/tools_store.html">tools/store</a><a href="#toolsstore" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="toolstasks"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><a href="modules/tools_tasks.html">tools/tasks</a><a href="#toolstasks" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="toolstwists"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><a href="modules/tools_twists.html">tools/twists</a><a href="#toolstwists" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="twist"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><a href="modules/twist.html">twist</a><a href="#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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="utilshash"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><a href="modules/utils_hash.html">utils/hash</a><a href="#utilshash" 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></span></dt><dd class="tsd-member-summary"></dd><dt class="tsd-member-summary" id="utilstypes"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><a href="modules/utils_types.html">utils/types</a><a href="#utilstypes" 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></span></dt><dd class="tsd-member-summary"></dd></dl></details></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"><details open class="tsd-accordion tsd-page-navigation-section"><summary class="tsd-accordion-summary" data-key="section-Documents"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-chevronDown"></use></svg>Documents</summary><div><a href="#sync_strategies"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Document"><use href="assets/icons.svg#icon-8388608"></use></svg><span>SYNC_<wbr/>STRATEGIES</span></a><a href="#multi_user_auth"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Document"><use href="assets/icons.svg#icon-8388608"></use></svg><span>MULTI_<wbr/>USER_<wbr/>AUTH</span></a></div></details><details open class="tsd-accordion tsd-page-navigation-section"><summary class="tsd-accordion-summary" data-key="section-Guides"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-chevronDown"></use></svg>Guides</summary><div><a href="#getting-started-1"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Document"><use href="assets/icons.svg#icon-8388608"></use></svg><span>Getting <wbr/>Started</span></a><a href="#core-concepts"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Document"><use href="assets/icons.svg#icon-8388608"></use></svg><span>Core <wbr/>Concepts</span></a><a href="#built-in-tools"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Document"><use href="assets/icons.svg#icon-8388608"></use></svg><span>Built-<wbr/>in <wbr/>Tools</span></a><a href="#building-connectors"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Document"><use href="assets/icons.svg#icon-8388608"></use></svg><span>Building <wbr/>Connectors</span></a><a href="#cli-reference"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Document"><use href="assets/icons.svg#icon-8388608"></use></svg><span>CLI <wbr/>Reference</span></a><a href="#runtime-environment"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Document"><use href="assets/icons.svg#icon-8388608"></use></svg><span>Runtime <wbr/>Environment</span></a></div></details><details open class="tsd-accordion tsd-page-navigation-section"><summary class="tsd-accordion-summary" data-key="section-Modules"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-chevronDown"></use></svg>Modules</summary><div><a href="#index"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><span>index</span></a><a href="#plot"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><span>plot</span></a><a href="#tag"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><span>tag</span></a><a href="#tool"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><span>tool</span></a><a href="#toolsai"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><span>tools/ai</span></a><a href="#toolscallbacks"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><span>tools/callbacks</span></a><a href="#toolsintegrations"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><span>tools/integrations</span></a><a href="#toolsnetwork"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><span>tools/network</span></a><a href="#toolsplot"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><span>tools/plot</span></a><a href="#toolsstore"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><span>tools/store</span></a><a href="#toolstasks"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><span>tools/tasks</span></a><a href="#toolstwists"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><span>tools/twists</span></a><a href="#twist"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><span>twist</span></a><a href="#utilshash"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><span>utils/hash</span></a><a href="#utilstypes"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Module"><use href="assets/icons.svg#icon-2"></use></svg><span>utils/types</span></a></div></details></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" class="current">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>
|