@plotday/twister 0.57.0 → 0.58.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (328) hide show
  1. package/README.md +53 -44
  2. package/bin/commands/create.js +9 -14
  3. package/bin/commands/create.js.map +1 -1
  4. package/bin/commands/deploy.js +2 -0
  5. package/bin/commands/deploy.js.map +1 -1
  6. package/bin/commands/generate.js +8 -5
  7. package/bin/commands/generate.js.map +1 -1
  8. package/bin/index.js +2 -2
  9. package/bin/index.js.map +1 -1
  10. package/bin/templates/AGENTS.template.md +110 -94
  11. package/bin/templates/README.template.md +36 -33
  12. package/cli/templates/AGENTS.template.md +110 -94
  13. package/cli/templates/README.template.md +36 -33
  14. package/dist/connector.d.ts +24 -17
  15. package/dist/connector.d.ts.map +1 -1
  16. package/dist/connector.js +19 -12
  17. package/dist/connector.js.map +1 -1
  18. package/dist/docs/assets/hierarchy.js +1 -1
  19. package/dist/docs/assets/navigation.js +1 -1
  20. package/dist/docs/assets/search.js +1 -1
  21. package/dist/docs/classes/index.Connector.html +66 -60
  22. package/dist/docs/classes/index.FileNotFoundError.html +2 -2
  23. package/dist/docs/classes/index.Files.html +4 -4
  24. package/dist/docs/classes/index.Imap.html +10 -10
  25. package/dist/docs/classes/index.Options.html +2 -2
  26. package/dist/docs/classes/index.Smtp.html +6 -6
  27. package/dist/docs/classes/tool.ITool.html +2 -2
  28. package/dist/docs/classes/tool.Tool.html +23 -23
  29. package/dist/docs/classes/tools_ai.AI.html +5 -5
  30. package/dist/docs/classes/tools_callbacks.Callbacks.html +8 -8
  31. package/dist/docs/classes/tools_integrations.Integrations.html +15 -15
  32. package/dist/docs/classes/tools_network.Network.html +9 -9
  33. package/dist/docs/classes/tools_plot.Plot.html +34 -33
  34. package/dist/docs/classes/tools_store.Store.html +8 -8
  35. package/dist/docs/classes/tools_tasks.Tasks.html +6 -6
  36. package/dist/docs/classes/tools_twists.Twists.html +12 -11
  37. package/dist/docs/classes/twist.Twist.html +28 -28
  38. package/dist/docs/documents/Building_Connectors.html +42 -28
  39. package/dist/docs/documents/Built-in_Tools.html +170 -67
  40. package/dist/docs/documents/CLI_Reference.html +68 -47
  41. package/dist/docs/documents/Core_Concepts.html +52 -81
  42. package/dist/docs/documents/Getting_Started.html +28 -31
  43. package/dist/docs/documents/MULTI_USER_AUTH.html +45 -0
  44. package/dist/docs/documents/Runtime_Environment.html +13 -12
  45. package/dist/docs/documents/SYNC_STRATEGIES.html +373 -0
  46. package/dist/docs/enums/plot.ActionType.html +9 -9
  47. package/dist/docs/enums/plot.ActorType.html +4 -4
  48. package/dist/docs/enums/plot.ConferencingProvider.html +6 -6
  49. package/dist/docs/enums/plot.ThemeColor.html +9 -9
  50. package/dist/docs/enums/tag.Tag.html +3 -3
  51. package/dist/docs/enums/tools_ai.AIModel.html +3 -3
  52. package/dist/docs/enums/tools_integrations.AuthProvider.html +13 -13
  53. package/dist/docs/enums/tools_plot.ContactAccess.html +2 -2
  54. package/dist/docs/enums/tools_plot.FocusAccess.html +3 -3
  55. package/dist/docs/enums/tools_plot.LinkAccess.html +3 -3
  56. package/dist/docs/enums/tools_plot.ThreadAccess.html +4 -4
  57. package/dist/docs/functions/index.Uuid.Generate.html +1 -1
  58. package/dist/docs/functions/utils_hash.quickHash.html +1 -1
  59. package/dist/docs/hierarchy.html +1 -1
  60. package/dist/docs/index.html +7 -8
  61. package/dist/docs/interfaces/tools_ai.AIRequest.html +13 -13
  62. package/dist/docs/interfaces/tools_ai.AIResponse.html +9 -9
  63. package/dist/docs/interfaces/tools_ai.FilePart.html +5 -5
  64. package/dist/docs/interfaces/tools_ai.ImagePart.html +4 -4
  65. package/dist/docs/interfaces/tools_ai.ReasoningPart.html +4 -4
  66. package/dist/docs/interfaces/tools_ai.RedactedReasoningPart.html +3 -3
  67. package/dist/docs/interfaces/tools_ai.TextPart.html +3 -3
  68. package/dist/docs/interfaces/tools_ai.ToolCallPart.html +5 -5
  69. package/dist/docs/interfaces/tools_ai.ToolExecutionOptions.html +4 -4
  70. package/dist/docs/interfaces/tools_ai.ToolResultPart.html +5 -5
  71. package/dist/docs/interfaces/tools_twists.TwistSource.html +3 -3
  72. package/dist/docs/interfaces/utils_types.ToolShed.html +5 -5
  73. package/dist/docs/media/AGENTS.md +101 -74
  74. package/dist/docs/modules.html +1 -1
  75. package/dist/docs/types/index.BooleanDef.html +2 -2
  76. package/dist/docs/types/index.CreateLinkDraft.html +9 -9
  77. package/dist/docs/types/index.ImapAddress.html +3 -3
  78. package/dist/docs/types/index.ImapConnectOptions.html +6 -6
  79. package/dist/docs/types/index.ImapFetchOptions.html +4 -4
  80. package/dist/docs/types/index.ImapFlagOperation.html +1 -1
  81. package/dist/docs/types/index.ImapMailbox.html +5 -5
  82. package/dist/docs/types/index.ImapMailboxStatus.html +7 -7
  83. package/dist/docs/types/index.ImapMessage.html +14 -14
  84. package/dist/docs/types/index.ImapSearchCriteria.html +9 -9
  85. package/dist/docs/types/index.ImapSession.html +1 -1
  86. package/dist/docs/types/index.NewSchedule.html +13 -13
  87. package/dist/docs/types/index.NewScheduleContact.html +2 -2
  88. package/dist/docs/types/index.NewScheduleOccurrence.html +1 -1
  89. package/dist/docs/types/index.NoteWriteBackResult.html +3 -3
  90. package/dist/docs/types/index.NumberDef.html +2 -2
  91. package/dist/docs/types/index.OptionDef.html +1 -1
  92. package/dist/docs/types/index.OptionalScopeGroup.html +6 -6
  93. package/dist/docs/types/index.OptionsSchema.html +1 -1
  94. package/dist/docs/types/index.ReactionCapabilities.html +1 -1
  95. package/dist/docs/types/index.ResolvedOptions.html +1 -1
  96. package/dist/docs/types/index.ResolvedRecipient.html +5 -5
  97. package/dist/docs/types/index.Schedule.html +12 -12
  98. package/dist/docs/types/index.ScheduleContact.html +2 -2
  99. package/dist/docs/types/index.ScheduleContactRole.html +1 -1
  100. package/dist/docs/types/index.ScheduleContactStatus.html +1 -1
  101. package/dist/docs/types/index.ScheduleOccurrence.html +6 -6
  102. package/dist/docs/types/index.ScheduleOccurrenceUpdate.html +1 -1
  103. package/dist/docs/types/index.ScopeConfig.html +3 -3
  104. package/dist/docs/types/index.SelectDef.html +2 -2
  105. package/dist/docs/types/index.Serializable.html +1 -1
  106. package/dist/docs/types/index.SmtpAddress.html +3 -3
  107. package/dist/docs/types/index.SmtpConnectOptions.html +7 -7
  108. package/dist/docs/types/index.SmtpMessage.html +12 -12
  109. package/dist/docs/types/index.SmtpSendResult.html +4 -4
  110. package/dist/docs/types/index.SmtpSession.html +1 -1
  111. package/dist/docs/types/index.TextDef.html +2 -2
  112. package/dist/docs/types/index.Uuid.html +1 -1
  113. package/dist/docs/types/plot.Action.html +1 -1
  114. package/dist/docs/types/plot.Actor.html +5 -5
  115. package/dist/docs/types/plot.ActorId.html +4 -4
  116. package/dist/docs/types/plot.Contact.html +4 -4
  117. package/dist/docs/types/plot.ContentType.html +1 -1
  118. package/dist/docs/types/plot.Focus.html +8 -8
  119. package/dist/docs/types/plot.FocusUpdate.html +1 -1
  120. package/dist/docs/types/plot.Link.html +17 -17
  121. package/dist/docs/types/plot.LinkUpdate.html +1 -1
  122. package/dist/docs/types/plot.NewActor.html +1 -1
  123. package/dist/docs/types/plot.NewContact.html +1 -1
  124. package/dist/docs/types/plot.NewFocus.html +1 -1
  125. package/dist/docs/types/plot.NewLink.html +5 -2
  126. package/dist/docs/types/plot.NewLinkWithNotes.html +1 -1
  127. package/dist/docs/types/plot.NewNote.html +1 -1
  128. package/dist/docs/types/plot.NewReactions.html +1 -1
  129. package/dist/docs/types/plot.NewTags.html +1 -1
  130. package/dist/docs/types/plot.NewThread.html +1 -1
  131. package/dist/docs/types/plot.NewThreadWithNotes.html +1 -1
  132. package/dist/docs/types/plot.Note.html +1 -1
  133. package/dist/docs/types/plot.NoteUpdate.html +1 -1
  134. package/dist/docs/types/plot.PlanOperation.html +1 -1
  135. package/dist/docs/types/plot.Reaction.html +3 -3
  136. package/dist/docs/types/plot.Reactions.html +1 -1
  137. package/dist/docs/types/plot.Tags.html +1 -1
  138. package/dist/docs/types/plot.Thread.html +1 -1
  139. package/dist/docs/types/plot.ThreadAccessLevel.html +1 -1
  140. package/dist/docs/types/plot.ThreadCommon.html +6 -6
  141. package/dist/docs/types/plot.ThreadFilter.html +2 -2
  142. package/dist/docs/types/plot.ThreadMeta.html +1 -1
  143. package/dist/docs/types/plot.ThreadType.html +1 -1
  144. package/dist/docs/types/plot.ThreadUpdate.html +1 -1
  145. package/dist/docs/types/plot.ThreadWithNotes.html +1 -1
  146. package/dist/docs/types/tools_ai.AIAssistantMessage.html +2 -2
  147. package/dist/docs/types/tools_ai.AICapabilities.html +4 -4
  148. package/dist/docs/types/tools_ai.AIMessage.html +1 -1
  149. package/dist/docs/types/tools_ai.AIOptions.html +2 -2
  150. package/dist/docs/types/tools_ai.AISource.html +1 -1
  151. package/dist/docs/types/tools_ai.AISystemMessage.html +2 -2
  152. package/dist/docs/types/tools_ai.AITool.html +1 -1
  153. package/dist/docs/types/tools_ai.AIToolMessage.html +2 -2
  154. package/dist/docs/types/tools_ai.AIToolSet.html +1 -1
  155. package/dist/docs/types/tools_ai.AIUsage.html +5 -5
  156. package/dist/docs/types/tools_ai.AIUserMessage.html +2 -2
  157. package/dist/docs/types/tools_ai.DataContent.html +1 -1
  158. package/dist/docs/types/tools_ai.ModelPreferences.html +5 -5
  159. package/dist/docs/types/tools_callbacks.Callback.html +2 -2
  160. package/dist/docs/types/tools_integrations.ArchiveLinkFilter.html +5 -5
  161. package/dist/docs/types/tools_integrations.ArchiveNotesFilter.html +2 -2
  162. package/dist/docs/types/tools_integrations.AuthToken.html +6 -5
  163. package/dist/docs/types/tools_integrations.Authorization.html +4 -4
  164. package/dist/docs/types/tools_integrations.Channel.html +6 -6
  165. package/dist/docs/types/tools_integrations.ComposeConfig.html +4 -4
  166. package/dist/docs/types/tools_integrations.ContactRoleConfig.html +5 -5
  167. package/dist/docs/types/tools_integrations.LinkTypeConfig.html +21 -21
  168. package/dist/docs/types/tools_integrations.NewCustomEmoji.html +8 -8
  169. package/dist/docs/types/tools_integrations.StatusIcon.html +1 -1
  170. package/dist/docs/types/tools_integrations.SyncContext.html +4 -4
  171. package/dist/docs/types/tools_network.WebhookRequest.html +6 -6
  172. package/dist/docs/types/tools_plot.LinkFilter.html +5 -5
  173. package/dist/docs/types/tools_plot.LinkSearchResult.html +1 -1
  174. package/dist/docs/types/tools_plot.NoteIntentHandler.html +4 -4
  175. package/dist/docs/types/tools_plot.NoteSearchResult.html +1 -1
  176. package/dist/docs/types/tools_plot.SearchOptions.html +4 -4
  177. package/dist/docs/types/tools_plot.SearchResult.html +1 -1
  178. package/dist/docs/types/tools_twists.Log.html +2 -2
  179. package/dist/docs/types/tools_twists.TwistPermissions.html +1 -1
  180. package/dist/docs/types/utils_types.BuiltInTools.html +2 -2
  181. package/dist/docs/types/utils_types.ExtractBuildReturn.html +1 -1
  182. package/dist/docs/types/utils_types.InferOptions.html +1 -1
  183. package/dist/docs/types/utils_types.InferTools.html +1 -1
  184. package/dist/docs/types/utils_types.JSONValue.html +1 -1
  185. package/dist/docs/types/utils_types.PromiseValues.html +1 -1
  186. package/dist/docs/types/utils_types.ToolBuilder.html +1 -1
  187. package/dist/docs/variables/tools_plot.SEARCH_DEFAULT_LIMIT.html +1 -1
  188. package/dist/docs/variables/tools_plot.SEARCH_MAX_LIMIT.html +1 -1
  189. package/dist/facets.d.ts +30 -0
  190. package/dist/facets.d.ts.map +1 -0
  191. package/dist/facets.js +16 -0
  192. package/dist/facets.js.map +1 -0
  193. package/dist/llm-docs/connector.d.ts +1 -1
  194. package/dist/llm-docs/connector.d.ts.map +1 -1
  195. package/dist/llm-docs/connector.js +1 -1
  196. package/dist/llm-docs/connector.js.map +1 -1
  197. package/dist/llm-docs/facets.d.ts +9 -0
  198. package/dist/llm-docs/facets.d.ts.map +1 -0
  199. package/dist/llm-docs/facets.js +8 -0
  200. package/dist/llm-docs/facets.js.map +1 -0
  201. package/dist/llm-docs/index.d.ts.map +1 -1
  202. package/dist/llm-docs/index.js +2 -0
  203. package/dist/llm-docs/index.js.map +1 -1
  204. package/dist/llm-docs/plot.d.ts +1 -1
  205. package/dist/llm-docs/plot.d.ts.map +1 -1
  206. package/dist/llm-docs/plot.js +1 -1
  207. package/dist/llm-docs/plot.js.map +1 -1
  208. package/dist/llm-docs/tool.d.ts +1 -1
  209. package/dist/llm-docs/tool.d.ts.map +1 -1
  210. package/dist/llm-docs/tool.js +1 -1
  211. package/dist/llm-docs/tool.js.map +1 -1
  212. package/dist/llm-docs/tools/ai.d.ts +1 -1
  213. package/dist/llm-docs/tools/ai.d.ts.map +1 -1
  214. package/dist/llm-docs/tools/ai.js +1 -1
  215. package/dist/llm-docs/tools/ai.js.map +1 -1
  216. package/dist/llm-docs/tools/callbacks.d.ts +1 -1
  217. package/dist/llm-docs/tools/callbacks.d.ts.map +1 -1
  218. package/dist/llm-docs/tools/callbacks.js +1 -1
  219. package/dist/llm-docs/tools/callbacks.js.map +1 -1
  220. package/dist/llm-docs/tools/files.d.ts +1 -1
  221. package/dist/llm-docs/tools/files.d.ts.map +1 -1
  222. package/dist/llm-docs/tools/files.js +1 -1
  223. package/dist/llm-docs/tools/files.js.map +1 -1
  224. package/dist/llm-docs/tools/imap.d.ts +1 -1
  225. package/dist/llm-docs/tools/imap.d.ts.map +1 -1
  226. package/dist/llm-docs/tools/imap.js +1 -1
  227. package/dist/llm-docs/tools/imap.js.map +1 -1
  228. package/dist/llm-docs/tools/integrations.d.ts +1 -1
  229. package/dist/llm-docs/tools/integrations.d.ts.map +1 -1
  230. package/dist/llm-docs/tools/integrations.js +1 -1
  231. package/dist/llm-docs/tools/integrations.js.map +1 -1
  232. package/dist/llm-docs/tools/network.d.ts +1 -1
  233. package/dist/llm-docs/tools/network.d.ts.map +1 -1
  234. package/dist/llm-docs/tools/network.js +1 -1
  235. package/dist/llm-docs/tools/network.js.map +1 -1
  236. package/dist/llm-docs/tools/plot.d.ts +1 -1
  237. package/dist/llm-docs/tools/plot.d.ts.map +1 -1
  238. package/dist/llm-docs/tools/plot.js +1 -1
  239. package/dist/llm-docs/tools/plot.js.map +1 -1
  240. package/dist/llm-docs/tools/smtp.d.ts +1 -1
  241. package/dist/llm-docs/tools/smtp.d.ts.map +1 -1
  242. package/dist/llm-docs/tools/smtp.js +1 -1
  243. package/dist/llm-docs/tools/smtp.js.map +1 -1
  244. package/dist/llm-docs/tools/tasks.d.ts +1 -1
  245. package/dist/llm-docs/tools/tasks.d.ts.map +1 -1
  246. package/dist/llm-docs/tools/tasks.js +1 -1
  247. package/dist/llm-docs/tools/tasks.js.map +1 -1
  248. package/dist/llm-docs/tools/twists.d.ts +1 -1
  249. package/dist/llm-docs/tools/twists.d.ts.map +1 -1
  250. package/dist/llm-docs/tools/twists.js +1 -1
  251. package/dist/llm-docs/tools/twists.js.map +1 -1
  252. package/dist/llm-docs/twist-guide-template.d.ts +1 -1
  253. package/dist/llm-docs/twist-guide-template.d.ts.map +1 -1
  254. package/dist/llm-docs/twist-guide-template.js +1 -1
  255. package/dist/llm-docs/twist-guide-template.js.map +1 -1
  256. package/dist/llm-docs/twist.d.ts +1 -1
  257. package/dist/llm-docs/twist.d.ts.map +1 -1
  258. package/dist/llm-docs/twist.js +1 -1
  259. package/dist/llm-docs/twist.js.map +1 -1
  260. package/dist/plot.d.ts +15 -8
  261. package/dist/plot.d.ts.map +1 -1
  262. package/dist/plot.js.map +1 -1
  263. package/dist/tool.d.ts +4 -4
  264. package/dist/tool.js +4 -4
  265. package/dist/tools/ai.d.ts +12 -13
  266. package/dist/tools/ai.d.ts.map +1 -1
  267. package/dist/tools/ai.js +8 -9
  268. package/dist/tools/ai.js.map +1 -1
  269. package/dist/tools/callbacks.d.ts +1 -1
  270. package/dist/tools/files.d.ts +2 -2
  271. package/dist/tools/imap.d.ts +1 -1
  272. package/dist/tools/imap.js +1 -1
  273. package/dist/tools/integrations.d.ts +2 -1
  274. package/dist/tools/integrations.d.ts.map +1 -1
  275. package/dist/tools/network.d.ts +5 -5
  276. package/dist/tools/plot.d.ts +42 -37
  277. package/dist/tools/plot.d.ts.map +1 -1
  278. package/dist/tools/plot.js +16 -12
  279. package/dist/tools/plot.js.map +1 -1
  280. package/dist/tools/smtp.d.ts +1 -1
  281. package/dist/tools/smtp.js +1 -1
  282. package/dist/tools/tasks.d.ts +6 -8
  283. package/dist/tools/tasks.d.ts.map +1 -1
  284. package/dist/tools/tasks.js +5 -7
  285. package/dist/tools/tasks.js.map +1 -1
  286. package/dist/tools/twists.d.ts +15 -14
  287. package/dist/tools/twists.d.ts.map +1 -1
  288. package/dist/tools/twists.js +2 -2
  289. package/dist/tools/twists.js.map +1 -1
  290. package/dist/twist-guide.d.ts +1 -1
  291. package/dist/twist-guide.d.ts.map +1 -1
  292. package/dist/twist.d.ts +2 -2
  293. package/dist/twist.js +2 -2
  294. package/package.json +6 -1
  295. package/src/connector.ts +23 -16
  296. package/src/facets.ts +40 -0
  297. package/src/llm-docs/connector.ts +1 -1
  298. package/src/llm-docs/facets.ts +8 -0
  299. package/src/llm-docs/index.ts +2 -0
  300. package/src/llm-docs/plot.ts +1 -1
  301. package/src/llm-docs/tool.ts +1 -1
  302. package/src/llm-docs/tools/ai.ts +1 -1
  303. package/src/llm-docs/tools/callbacks.ts +1 -1
  304. package/src/llm-docs/tools/files.ts +1 -1
  305. package/src/llm-docs/tools/imap.ts +1 -1
  306. package/src/llm-docs/tools/integrations.ts +1 -1
  307. package/src/llm-docs/tools/network.ts +1 -1
  308. package/src/llm-docs/tools/plot.ts +1 -1
  309. package/src/llm-docs/tools/smtp.ts +1 -1
  310. package/src/llm-docs/tools/tasks.ts +1 -1
  311. package/src/llm-docs/tools/twists.ts +1 -1
  312. package/src/llm-docs/twist-guide-template.ts +1 -1
  313. package/src/llm-docs/twist.ts +1 -1
  314. package/src/plot.ts +15 -8
  315. package/src/tool.ts +4 -4
  316. package/src/tools/ai.ts +12 -13
  317. package/src/tools/callbacks.ts +1 -1
  318. package/src/tools/files.ts +2 -2
  319. package/src/tools/imap.ts +1 -1
  320. package/src/tools/integrations.ts +2 -1
  321. package/src/tools/network.ts +5 -5
  322. package/src/tools/plot.ts +42 -37
  323. package/src/tools/smtp.ts +1 -1
  324. package/src/tools/tasks.ts +6 -8
  325. package/src/tools/twists.ts +15 -14
  326. package/src/twist.ts +2 -2
  327. package/dist/docs/media/MULTI_USER_AUTH.md +0 -116
  328. package/dist/docs/media/SYNC_STRATEGIES.md +0 -818
@@ -5,4 +5,4 @@
5
5
  * Generated from: prebuild.ts
6
6
  */
7
7
 
8
- export default "import type { NoteWriteBackResult } from \"./connector\";\nimport { type Action, type Actor, type ActorId, type Link, type Note, type Thread, Uuid } from \"./plot\";\nimport type { Tag } from \"./tag\";\nimport { type ITool } from \"./tool\";\nimport type { Callback } from \"./tools/callbacks\";\nimport type { Serializable } from \"./utils/serializable\";\nimport type { InferTools, ToolBuilder, ToolShed } from \"./utils/types\";\n\n/**\n * Base class for all twists.\n *\n * A twist is installed at the workspace level and is owned by a single user\n * (see `this.userId`). It has no inherent focus scope: threads, notes, and\n * links it creates are filed against the owner's focuses, with automatic\n * focus matching when no explicit target is provided.\n *\n * Override `build()` to declare tool dependencies and lifecycle methods to\n * handle events.\n *\n * @example\n * ```typescript\n * class FlatteringTwist extends Twist<FlatteringTwist> {\n * build(build: ToolBuilder) {\n * return {\n * plot: build(Plot),\n * };\n * }\n *\n * async activate() {\n * await this.tools.plot.createThread({\n * title: \"Hello, good looking!\",\n * });\n * }\n * }\n * ```\n */\nexport abstract class Twist<TSelf> {\n /**\n * When `true`, users may install multiple instances of this twist within\n * the same scope (personal workspace or team). Each instance must have a\n * distinct name.\n *\n * Defaults to `false` (single instance per scope).\n *\n * @example\n * ```typescript\n * class WorkflowTwist extends Twist<WorkflowTwist> {\n * static readonly multipleInstances = true;\n * // ...\n * }\n * ```\n */\n static readonly multipleInstances?: boolean;\n\n /**\n * The user ID (`twist_instance.owner_id`) that installed this twist.\n * Populated by the runtime before any lifecycle method runs.\n */\n protected userId!: Uuid;\n\n constructor(protected id: Uuid, private toolShed: ToolShed) {}\n\n /**\n * Gets the initialized tools for this twist.\n * @throws Error if called before initialization is complete\n */\n protected get tools(): InferTools<TSelf> {\n return this.toolShed.getTools<InferTools<TSelf>>();\n }\n\n /**\n * Declares tool dependencies for this twist.\n * Return an object mapping tool names to build() promises.\n *\n * @param build - The build function to use for declaring dependencies\n * @returns Object mapping tool names to tool promises\n *\n * @example\n * ```typescript\n * build(build: ToolBuilder) {\n * return {\n * plot: build(Plot),\n * calendar: build(GoogleCalendar, { apiKey: \"...\" }),\n * };\n * }\n * ```\n */\n abstract build(build: ToolBuilder): Record<string, Promise<ITool>>;\n\n /**\n * Creates a persistent callback to a method on this twist.\n *\n * ExtraArgs are strongly typed to match the method's signature. They must be serializable.\n *\n * @param fn - The method to callback\n * @param extraArgs - Additional arguments to pass (type-checked, must be serializable)\n * @returns Promise resolving to a persistent callback token\n *\n * @example\n * ```typescript\n * const callback = await this.callback(this.onWebhook, \"calendar\", 123);\n * ```\n */\n protected callback<\n TArgs extends Serializable[],\n Fn extends (...args: TArgs) => any\n >(fn: Fn, ...extraArgs: TArgs): Promise<Callback>;\n // Overload when caller provides the first argument\n protected callback<\n TArgs extends Serializable[],\n Fn extends (arg1: any, ...extraArgs: TArgs) => any\n >(fn: Fn, ...extraArgs: TArgs): Promise<Callback>;\n protected async callback<\n TArgs extends Serializable[],\n Fn extends (...args: any[]) => any\n >(fn: Fn, ...extraArgs: TArgs): Promise<Callback> {\n return this.tools.callbacks.create(fn, ...extraArgs);\n }\n\n /**\n * Like callback(), but for an Action, which receives the action as the first argument.\n *\n * @param fn - The method to callback\n * @param extraArgs - Additional arguments to pass after the action\n * @returns Promise resolving to a persistent callback token\n *\n * @example\n * ```typescript\n * const callback = await this.actionCallback(this.doSomething, 123);\n * const action: Action = {\n * type: ActionType.callback,\n * title: \"Do Something\",\n * callback,\n * };\n * ```\n */\n protected async actionCallback<\n TArgs extends Serializable[],\n Fn extends (action: Action, ...extraArgs: TArgs) => any\n >(fn: Fn, ...extraArgs: TArgs): Promise<Callback> {\n return this.tools.callbacks.create(fn, ...extraArgs);\n }\n\n /**\n * Deletes a specific callback by its token.\n *\n * @param token - The callback token to delete\n * @returns Promise that resolves when the callback is deleted\n */\n protected async deleteCallback(token: Callback): Promise<void> {\n return this.tools.callbacks.delete(token);\n }\n\n /**\n * Deletes all callbacks for this twist.\n *\n * @returns Promise that resolves when all callbacks are deleted\n */\n protected async deleteAllCallbacks(): Promise<void> {\n return this.tools.callbacks.deleteAll();\n }\n\n /**\n * Executes a callback by its token inline in the current execution.\n *\n * **Use `this.runTask()` instead for batch continuations and long-running work.**\n * `this.run()` executes inline, sharing the current request count (~1000 limit)\n * and blocking the HTTP response. This causes timeouts when used in lifecycle\n * methods like `onChannelEnabled` or `syncBatch` continuations.\n *\n * `this.run()` is appropriate when you need the callback's **return value** —\n * e.g., running a parent callback token that returns data. For fire-and-forget\n * work, always prefer `this.runTask()`.\n *\n * @param token - The callback token to execute\n * @param args - Optional arguments to pass to the callback\n * @returns Promise resolving to the callback result\n */\n protected async run(token: Callback, ...args: []): Promise<any> {\n return this.tools.callbacks.run(token, ...args);\n }\n\n /**\n * Retrieves a value from persistent storage by key.\n *\n * Values are automatically deserialized using SuperJSON, which\n * properly restores Date objects, Maps, Sets, and other complex types.\n *\n * @template T - The expected type of the stored value (must be Serializable)\n * @param key - The storage key to retrieve\n * @returns Promise resolving to the stored value or null\n */\n protected async get<T extends import(\"./index\").Serializable>(\n key: string\n ): Promise<T | null> {\n return this.tools.store.get(key);\n }\n\n /**\n * Stores a value in persistent storage.\n *\n * The value will be serialized using SuperJSON and stored persistently.\n * SuperJSON automatically handles Date objects, Maps, Sets, undefined values,\n * and other complex types that standard JSON doesn't support.\n *\n * **Important**: Functions and Symbols cannot be stored.\n * **For function references**: Use callbacks instead of storing functions directly.\n *\n * @example\n * ```typescript\n * // ✅ Date objects are preserved\n * await this.set(\"sync_state\", {\n * lastSync: new Date(),\n * minDate: new Date(2024, 0, 1)\n * });\n *\n * // ✅ undefined is now supported\n * await this.set(\"data\", { name: \"test\", optional: undefined });\n *\n * // ❌ WRONG: Cannot store functions directly\n * await this.set(\"handler\", this.myHandler);\n *\n * // ✅ CORRECT: Create a callback token first\n * const token = await this.callback(this.myHandler, \"arg1\", \"arg2\");\n * await this.set(\"handler_token\", token);\n *\n * // Later, execute the callback\n * const token = await this.get<string>(\"handler_token\");\n * await this.run(token, args);\n * ```\n *\n * @template T - The type of value being stored (must be Serializable)\n * @param key - The storage key to use\n * @param value - The value to store (must be SuperJSON-serializable)\n * @returns Promise that resolves when the value is stored\n */\n protected async set<T extends import(\"./index\").Serializable>(\n key: string,\n value: T\n ): Promise<void> {\n return this.tools.store.set(key, value);\n }\n\n /**\n * Removes a specific key from persistent storage.\n *\n * @param key - The storage key to remove\n * @returns Promise that resolves when the key is removed\n */\n protected async clear(key: string): Promise<void> {\n return this.tools.store.clear(key);\n }\n\n /**\n * Removes all keys from this twist's storage.\n *\n * @returns Promise that resolves when all keys are removed\n */\n protected async clearAll(): Promise<void> {\n return this.tools.store.clearAll();\n }\n\n /**\n * Queues a callback to execute in a separate worker context.\n *\n * @param callback - The callback token created with `this.callback()`\n * @param options - Optional configuration for the execution\n * @param options.runAt - If provided, schedules execution at this time; otherwise runs immediately\n * @returns Promise resolving to a cancellation token (only for scheduled executions)\n */\n protected async runTask(\n callback: Callback,\n options?: { runAt?: Date }\n ): Promise<string | void> {\n return this.tools.tasks.runTask(callback, options);\n }\n\n /**\n * Cancels a previously scheduled execution.\n *\n * @param token - The cancellation token returned by runTask() with runAt option\n * @returns Promise that resolves when the cancellation is processed\n */\n protected async cancelTask(token: string): Promise<void> {\n return this.tools.tasks.cancelTask(token);\n }\n\n /**\n * Cancels all scheduled executions for this twist.\n *\n * @returns Promise that resolves when all cancellations are processed\n */\n protected async cancelAllTasks(): Promise<void> {\n return this.tools.tasks.cancelAllTasks();\n }\n\n /**\n * Called when the twist is installed by a user.\n *\n * This method should contain initialization logic such as seeding\n * initial threads, configuring webhooks, or establishing external\n * connections. When it runs, `this.userId` is already populated with\n * the installing user's ID.\n *\n * @param context - Optional context containing the actor who triggered activation\n * @returns Promise that resolves when activation is complete\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n activate(context?: { actor: Actor }): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Called when a new version of the twist is deployed.\n *\n * This method should contain migration logic for updating old data structures\n * or setting up new resources that weren't needed by the previous version.\n * It is called once per active twist_instance with the new version.\n *\n * @returns Promise that resolves when upgrade is complete\n */\n upgrade(): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Called when the twist's options configuration changes.\n *\n * Override to react to option changes, e.g. archiving items when a sync\n * type is toggled off, or starting sync when a type is toggled on.\n *\n * @param oldOptions - The previously resolved options\n * @param newOptions - The newly resolved options\n * @returns Promise that resolves when the change is handled\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onOptionsChanged(\n oldOptions: Record<string, any>,\n newOptions: Record<string, any>\n ): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Called when the twist is uninstalled.\n *\n * This method should contain cleanup logic such as removing webhooks,\n * cleaning up external resources, or performing final data operations.\n *\n * @returns Promise that resolves when deactivation is complete\n */\n deactivate(): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Called when a thread created by this twist is updated.\n * Override to implement two-way sync with an external system.\n *\n * @param thread - The updated thread\n * @param changes - Tag additions and removals on the thread\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onThreadUpdated(\n thread: Thread,\n changes: {\n tagsAdded: Record<Tag, ActorId[]>;\n tagsRemoved: Record<Tag, ActorId[]>;\n }\n ): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Called when a note is created on a thread created by this twist.\n * Override to implement two-way sync (e.g. syncing notes as comments).\n *\n * Notes created by the twist itself are filtered out to prevent loops.\n *\n * Returning a string sets the note's `key` for future upsert matching,\n * linking the Plot note to its external counterpart so that subsequent\n * syncs (reactions, edits) update the existing note instead of creating duplicates.\n *\n * @param note - The newly created note\n * @returns Optional note key for external deduplication\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onNoteCreated(note: Note, ...args: any[]): Promise<string | NoteWriteBackResult | void> {\n return Promise.resolve();\n }\n\n /**\n * Called when a link is created in a connected source channel.\n * Requires `link: true` in Plot options.\n *\n * @param link - The newly created link\n * @param notes - Notes on the link's thread\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onLinkCreated(link: Link, notes: Note[]): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Called when a link in a connected source channel is updated.\n * Requires `link: true` in Plot options.\n *\n * @param link - The updated link\n * @param notes - Notes on the link's thread (optional)\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onLinkUpdated(link: Link, notes?: Note[]): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Called when a note is created on a thread with a link from a connected channel.\n * Requires `link: true` in Plot options.\n *\n * @param note - The newly created note\n * @param link - The link associated with the thread\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onLinkNoteCreated(note: Note, link: Link): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Waits for tool initialization to complete.\n * Called automatically by the entrypoint before lifecycle methods.\n * @internal\n */\n async waitForReady(): Promise<void> {\n await this.toolShed.waitForReady();\n }\n}\n";
8
+ export default "import type { NoteWriteBackResult } from \"./connector\";\nimport { type Action, type Actor, type ActorId, type Link, type Note, type Thread, Uuid } from \"./plot\";\nimport type { Tag } from \"./tag\";\nimport { type ITool } from \"./tool\";\nimport type { Callback } from \"./tools/callbacks\";\nimport type { Serializable } from \"./utils/serializable\";\nimport type { InferTools, ToolBuilder, ToolShed } from \"./utils/types\";\n\n/**\n * Base class for all twists.\n *\n * A twist is installed at the workspace level and is owned by a single user\n * (see `this.userId`). It has no inherent focus scope: threads, notes, and\n * links it creates are filed against the owner's focuses, with automatic\n * focus matching when no explicit target is provided.\n *\n * Override `build()` to declare tool dependencies and lifecycle methods to\n * handle events.\n *\n * @example\n * ```typescript\n * class FlatteringTwist extends Twist<FlatteringTwist> {\n * build(build: ToolBuilder) {\n * return {\n * plot: build(Plot),\n * };\n * }\n *\n * async activate() {\n * await this.tools.plot.createThread({\n * title: \"Hello, good looking!\",\n * });\n * }\n * }\n * ```\n */\nexport abstract class Twist<TSelf> {\n /**\n * When `true`, users may install multiple instances of this twist within\n * the same scope (personal workspace or team). Each instance must have a\n * distinct name.\n *\n * Defaults to `false` (single instance per scope).\n *\n * @example\n * ```typescript\n * class WorkflowTwist extends Twist<WorkflowTwist> {\n * static readonly multipleInstances = true;\n * // ...\n * }\n * ```\n */\n static readonly multipleInstances?: boolean;\n\n /**\n * The user ID (`twist_instance.owner_id`) that installed this twist.\n * Populated by the runtime before any lifecycle method runs.\n */\n protected userId!: Uuid;\n\n constructor(protected id: Uuid, private toolShed: ToolShed) {}\n\n /**\n * Gets the initialized tools for this twist.\n * @throws Error if called before initialization is complete\n */\n protected get tools(): InferTools<TSelf> {\n return this.toolShed.getTools<InferTools<TSelf>>();\n }\n\n /**\n * Declares tool dependencies for this twist.\n * Return an object mapping tool names to build() promises.\n *\n * @param build - The build function to use for declaring dependencies\n * @returns Object mapping tool names to tool promises\n *\n * @example\n * ```typescript\n * build(build: ToolBuilder) {\n * return {\n * plot: build(Plot),\n * calendar: build(GoogleCalendar, { apiKey: \"...\" }),\n * };\n * }\n * ```\n */\n abstract build(build: ToolBuilder): Record<string, Promise<ITool>>;\n\n /**\n * Creates a persistent callback to a method on this twist.\n *\n * ExtraArgs are strongly typed to match the method's signature. They must be serializable.\n *\n * @param fn - The method to callback\n * @param extraArgs - Additional arguments to pass (type-checked, must be serializable)\n * @returns Promise resolving to a persistent callback token\n *\n * @example\n * ```typescript\n * const callback = await this.callback(this.onWebhook, \"calendar\", 123);\n * ```\n */\n protected callback<\n TArgs extends Serializable[],\n Fn extends (...args: TArgs) => any\n >(fn: Fn, ...extraArgs: TArgs): Promise<Callback>;\n // Overload when caller provides the first argument\n protected callback<\n TArgs extends Serializable[],\n Fn extends (arg1: any, ...extraArgs: TArgs) => any\n >(fn: Fn, ...extraArgs: TArgs): Promise<Callback>;\n protected async callback<\n TArgs extends Serializable[],\n Fn extends (...args: any[]) => any\n >(fn: Fn, ...extraArgs: TArgs): Promise<Callback> {\n return this.tools.callbacks.create(fn, ...extraArgs);\n }\n\n /**\n * Like callback(), but for an Action, which receives the action as the first argument.\n *\n * @param fn - The method to callback\n * @param extraArgs - Additional arguments to pass after the action\n * @returns Promise resolving to a persistent callback token\n *\n * @example\n * ```typescript\n * const callback = await this.actionCallback(this.doSomething, 123);\n * const action: Action = {\n * type: ActionType.callback,\n * title: \"Do Something\",\n * callback,\n * };\n * ```\n */\n protected async actionCallback<\n TArgs extends Serializable[],\n Fn extends (action: Action, ...extraArgs: TArgs) => any\n >(fn: Fn, ...extraArgs: TArgs): Promise<Callback> {\n return this.tools.callbacks.create(fn, ...extraArgs);\n }\n\n /**\n * Deletes a specific callback by its token.\n *\n * @param token - The callback token to delete\n * @returns Promise that resolves when the callback is deleted\n */\n protected async deleteCallback(token: Callback): Promise<void> {\n return this.tools.callbacks.delete(token);\n }\n\n /**\n * Deletes all callbacks for this twist.\n *\n * @returns Promise that resolves when all callbacks are deleted\n */\n protected async deleteAllCallbacks(): Promise<void> {\n return this.tools.callbacks.deleteAll();\n }\n\n /**\n * Executes a callback by its token inline in the current execution.\n *\n * **Use `this.runTask()` instead for batch continuations and long-running work.**\n * `this.run()` executes inline, sharing the current request count (~1000 limit)\n * and blocking the HTTP response. This causes timeouts when used in lifecycle\n * methods like `onChannelEnabled` or `syncBatch` continuations.\n *\n * `this.run()` is appropriate when you need the callback's **return value** —\n * e.g., running a parent callback token that returns data. For fire-and-forget\n * work, always prefer `this.runTask()`.\n *\n * @param token - The callback token to execute\n * @param args - Optional arguments to pass to the callback\n * @returns Promise resolving to the callback result\n */\n protected async run(token: Callback, ...args: []): Promise<any> {\n return this.tools.callbacks.run(token, ...args);\n }\n\n /**\n * Retrieves a value from persistent storage by key.\n *\n * Values are automatically deserialized using SuperJSON, which\n * properly restores Date objects, Maps, Sets, and other complex types.\n *\n * @template T - The expected type of the stored value (must be Serializable)\n * @param key - The storage key to retrieve\n * @returns Promise resolving to the stored value or null\n */\n protected async get<T extends import(\"./index\").Serializable>(\n key: string\n ): Promise<T | null> {\n return this.tools.store.get(key);\n }\n\n /**\n * Stores a value in persistent storage.\n *\n * The value will be serialized using SuperJSON and stored persistently.\n * SuperJSON automatically handles Date objects, Maps, Sets, undefined values,\n * and other complex types that standard JSON doesn't support.\n *\n * **Important**: Functions and Symbols cannot be stored.\n * **For function references**: Use callbacks instead of storing functions directly.\n *\n * @example\n * ```typescript\n * // ✅ Date objects are preserved\n * await this.set(\"sync_state\", {\n * lastSync: new Date(),\n * minDate: new Date(2024, 0, 1)\n * });\n *\n * // ✅ undefined is now supported\n * await this.set(\"data\", { name: \"test\", optional: undefined });\n *\n * // ❌ WRONG: Cannot store functions directly\n * await this.set(\"handler\", this.myHandler);\n *\n * // ✅ CORRECT: Create a callback token first\n * const token = await this.callback(this.myHandler, \"arg1\", \"arg2\");\n * await this.set(\"handler_token\", token);\n *\n * // Later, execute the callback\n * const token = await this.get<Callback>(\"handler_token\");\n * await this.run(token);\n * ```\n *\n * @template T - The type of value being stored (must be Serializable)\n * @param key - The storage key to use\n * @param value - The value to store (must be SuperJSON-serializable)\n * @returns Promise that resolves when the value is stored\n */\n protected async set<T extends import(\"./index\").Serializable>(\n key: string,\n value: T\n ): Promise<void> {\n return this.tools.store.set(key, value);\n }\n\n /**\n * Removes a specific key from persistent storage.\n *\n * @param key - The storage key to remove\n * @returns Promise that resolves when the key is removed\n */\n protected async clear(key: string): Promise<void> {\n return this.tools.store.clear(key);\n }\n\n /**\n * Removes all keys from this twist's storage.\n *\n * @returns Promise that resolves when all keys are removed\n */\n protected async clearAll(): Promise<void> {\n return this.tools.store.clearAll();\n }\n\n /**\n * Queues a callback to execute in a separate worker context.\n *\n * @param callback - The callback token created with `this.callback()`\n * @param options - Optional configuration for the execution\n * @param options.runAt - If provided, schedules execution at this time; otherwise runs immediately\n * @returns Promise resolving to a cancellation token (only for scheduled executions)\n */\n protected async runTask(\n callback: Callback,\n options?: { runAt?: Date }\n ): Promise<string | void> {\n return this.tools.tasks.runTask(callback, options);\n }\n\n /**\n * Cancels a previously scheduled execution.\n *\n * @param token - The cancellation token returned by runTask() with runAt option\n * @returns Promise that resolves when the cancellation is processed\n */\n protected async cancelTask(token: string): Promise<void> {\n return this.tools.tasks.cancelTask(token);\n }\n\n /**\n * Cancels all scheduled executions for this twist.\n *\n * @returns Promise that resolves when all cancellations are processed\n */\n protected async cancelAllTasks(): Promise<void> {\n return this.tools.tasks.cancelAllTasks();\n }\n\n /**\n * Called when the twist is installed by a user.\n *\n * This method should contain initialization logic such as seeding\n * initial threads, configuring webhooks, or establishing external\n * connections. When it runs, `this.userId` is already populated with\n * the installing user's ID.\n *\n * @param context - Optional context containing the actor who triggered activation\n * @returns Promise that resolves when activation is complete\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n activate(context?: { actor: Actor }): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Called when a new version of the twist is deployed.\n *\n * This method should contain migration logic for updating old data structures\n * or setting up new resources that weren't needed by the previous version.\n * It is called once per active twist_instance with the new version.\n *\n * @returns Promise that resolves when upgrade is complete\n */\n upgrade(): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Called when the twist's options configuration changes.\n *\n * Override to react to option changes, e.g. archiving items when a sync\n * type is toggled off, or starting sync when a type is toggled on.\n *\n * @param oldOptions - The previously resolved options\n * @param newOptions - The newly resolved options\n * @returns Promise that resolves when the change is handled\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onOptionsChanged(\n oldOptions: Record<string, any>,\n newOptions: Record<string, any>\n ): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Called when the twist is uninstalled.\n *\n * This method should contain cleanup logic such as removing webhooks,\n * cleaning up external resources, or performing final data operations.\n *\n * @returns Promise that resolves when deactivation is complete\n */\n deactivate(): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Called when a thread created by this twist is updated.\n * Override to implement two-way sync with an external system.\n *\n * @param thread - The updated thread\n * @param changes - Tag additions and removals on the thread\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onThreadUpdated(\n thread: Thread,\n changes: {\n tagsAdded: Record<Tag, ActorId[]>;\n tagsRemoved: Record<Tag, ActorId[]>;\n }\n ): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Called when a note is created on a thread created by this twist.\n * Override to implement two-way sync (e.g. syncing notes as comments).\n *\n * Notes created by the twist itself are filtered out to prevent loops.\n *\n * Returning a string sets the note's `key` for future upsert matching,\n * linking the Plot note to its external counterpart so that subsequent\n * syncs (reactions, edits) update the existing note instead of creating duplicates.\n *\n * @param note - The newly created note\n * @returns Optional note key for external deduplication\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onNoteCreated(note: Note, ...args: any[]): Promise<string | NoteWriteBackResult | void> {\n return Promise.resolve();\n }\n\n /**\n * Called when a link is created in a connected source channel.\n * Requires `link: true` in Plot options.\n *\n * @param link - The newly created link\n * @param notes - Notes on the link's thread\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onLinkCreated(link: Link, notes: Note[]): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Called when a link in a connected source channel is updated.\n * Requires `link: true` in Plot options.\n *\n * @param link - The updated link\n * @param notes - Notes on the link's thread (optional)\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onLinkUpdated(link: Link, notes?: Note[]): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Called when a note is created on a thread with a link from a connected channel.\n * Requires `link: true` in Plot options.\n *\n * @param note - The newly created note\n * @param link - The link associated with the thread\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onLinkNoteCreated(note: Note, link: Link): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Waits for tool initialization to complete.\n * Called automatically by the entrypoint before lifecycle methods.\n * @internal\n */\n async waitForReady(): Promise<void> {\n await this.toolShed.waitForReady();\n }\n}\n";
package/src/plot.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { ThreadFacets } from "./facets";
1
2
  import type { NewSchedule, NewScheduleOccurrence, Schedule } from "./schedule";
2
3
  import { type Tag } from "./tag";
3
4
  import { type Callback } from "./tools/callbacks";
@@ -21,7 +22,7 @@ export { type AuthProvider } from "./tools/integrations";
21
22
  * - **Required fields**: No `?`, cannot be `undefined`
22
23
  * - Example: `id: Uuid`, `title: string`
23
24
  * - **Nullable fields**: Use `| null` to allow explicit clearing
24
- * - Example: `assignee: ActorId | null`, `done: Date | null`
25
+ * - Example: `key: string | null`, `status: string | null`
25
26
  * - `null` = field is explicitly unset/cleared
26
27
  * - Non-null value = field has a value
27
28
  * - **Optional nullable fields**: Use `?` with `| null` for permission-based access
@@ -68,9 +69,9 @@ export { type AuthProvider } from "./tools/integrations";
68
69
  * Represents a unique user, contact, or twist in Plot.
69
70
  *
70
71
  * ActorIds are used throughout Plot for:
71
- * - Activity authors and assignees
72
- * - Tag creators (actor_id in activity_tag/note_tag)
73
- * - Mentions in activities and notes
72
+ * - Thread and note authors, link assignees
73
+ * - Tag creators (actor_id in thread_tag/note_tag)
74
+ * - Mentions in notes
74
75
  * - Any entity that can perform actions in Plot
75
76
  */
76
77
  export type ActorId = string & { readonly __brand: "ActorId" };
@@ -100,7 +101,7 @@ export enum ThemeColor {
100
101
  /**
101
102
  * Represents a focus within Plot.
102
103
  *
103
- * A focus is similar to a project or area-of-life. All Activity is in a Focus.
104
+ * A focus is similar to a project or area-of-life. Every thread is in a focus.
104
105
  * Focuses are flat — they have no parent and no children. Threads not matched
105
106
  * to any focus live in the Inbox.
106
107
  */
@@ -402,8 +403,8 @@ export type NewTags = { [K in Tag]?: NewActor[] };
402
403
  * Anything matching a known provider prefix is treated as a custom-emoji
403
404
  * reference; everything else is rendered as the Unicode it contains.
404
405
  *
405
- * Reactions are the open-set counterpart to {@link Tag}'s count range
406
- * (`1000+`). Use reactions for emoji that round-trip with chat platforms;
406
+ * Reactions are the open-set replacement for {@link Tag}'s retired count
407
+ * range (`1000+`). Use reactions for emoji that round-trip with chat platforms;
407
408
  * use tags for Plot-managed compute/toggle state (todo, pinned, urgent,
408
409
  * ...).
409
410
  */
@@ -921,7 +922,7 @@ export enum ActorType {
921
922
  * Represents contact information for creating a new contact.
922
923
  *
923
924
  * Contacts are used throughout Plot for representing people associated
924
- * with activities, such as event attendees or task assignees.
925
+ * with threads, such as event attendees or task assignees.
925
926
  *
926
927
  * @example
927
928
  * ```typescript
@@ -1069,6 +1070,12 @@ export type NewLink = Partial<
1069
1070
  * thread that includes `icaluid:<uid>` in its own `sources`.
1070
1071
  */
1071
1072
  sources?: string[];
1073
+ /**
1074
+ * Heuristic facets describing this item (format / automation / reach),
1075
+ * used as internal classifier signal. Omit a dimension (or set null) when
1076
+ * no heuristic is confident. See `@plotday/twister/facets`.
1077
+ */
1078
+ facets?: ThreadFacets;
1072
1079
  /** The person that created the item. By default, it will be the twist itself. */
1073
1080
  author?: NewActor;
1074
1081
  /** The person assigned to the item. */
package/src/tool.ts CHANGED
@@ -13,7 +13,7 @@ import type {
13
13
  export type { ToolBuilder };
14
14
 
15
15
  /**
16
- * Abstrtact parent for both built-in tools and regular Tools.
16
+ * Abstract parent for both built-in tools and regular Tools.
17
17
  * Regular tools extend Tool.
18
18
  */
19
19
  export abstract class ITool {}
@@ -194,8 +194,8 @@ export abstract class Tool<TSelf> implements ITool {
194
194
  * await this.set("handler_token", token);
195
195
  *
196
196
  * // Later, execute the callback
197
- * const token = await this.get<string>("handler_token");
198
- * await this.run(token, args);
197
+ * const token = await this.get<Callback>("handler_token");
198
+ * await this.run(token);
199
199
  * ```
200
200
  *
201
201
  * @template T - The type of value being stored (must be Serializable)
@@ -257,7 +257,7 @@ export abstract class Tool<TSelf> implements ITool {
257
257
  * @example
258
258
  * ```typescript
259
259
  * // Break large loop into batches
260
- * const callback = await this.callback("processBatch", { page: 1 });
260
+ * const callback = await this.callback(this.processBatch, 1);
261
261
  * await this.runTask(callback); // New execution with fresh request limit
262
262
  * ```
263
263
  */
package/src/tools/ai.ts CHANGED
@@ -21,12 +21,11 @@ import { ITool } from "..";
21
21
  * ```typescript
22
22
  * import { Type } from "typebox";
23
23
  *
24
- * class SmartEmailTool extends Tool {
25
- * private ai: AI;
26
- *
27
- * constructor(id: string, tools: ToolBuilder) {
28
- * super();
29
- * this.ai = tools.get(AI);
24
+ * class SmartEmailTool extends Tool<SmartEmailTool> {
25
+ * build(build: ToolBuilder) {
26
+ * return {
27
+ * ai: build(AI),
28
+ * };
30
29
  * }
31
30
  *
32
31
  * async categorizeEmail(emailContent: string) {
@@ -42,7 +41,7 @@ import { ITool } from "..";
42
41
  * reasoning: Type.Optional(Type.String())
43
42
  * });
44
43
  *
45
- * const response = await this.ai.prompt({
44
+ * const response = await this.tools.ai.prompt({
46
45
  * model: { speed: "fast", cost: "medium" },
47
46
  * system: "Classify emails into categories: work, personal, spam, or promotional.",
48
47
  * prompt: `Categorize this email: ${emailContent}`,
@@ -53,7 +52,7 @@ import { ITool } from "..";
53
52
  * }
54
53
  *
55
54
  * async generateResponse(emailContent: string) {
56
- * const response = await this.ai.prompt({
55
+ * const response = await this.tools.ai.prompt({
57
56
  * model: { speed: "fast", cost: "medium" },
58
57
  * system: "Generate professional email responses that are helpful and concise.",
59
58
  * prompt: `Write a response to: ${emailContent}`
@@ -67,7 +66,7 @@ import { ITool } from "..";
67
66
  export abstract class AI extends ITool {
68
67
  /**
69
68
  * Returns which AI capabilities are currently available.
70
- * Check this before calling prompt() or embed() to gracefully
69
+ * Check this before calling prompt() to gracefully
71
70
  * handle cases where AI is disabled by the user.
72
71
  *
73
72
  * Built-in tools are accessed as RPC stubs, so from a twist this call
@@ -195,7 +194,7 @@ export type AICapabilities = {
195
194
  * prompt: "Analyze this data..."
196
195
  * });
197
196
  *
198
- * // Most capable - uses Claude Sonnet 4.5 or Opus 4.1
197
+ * // Most capable - uses models like GPT-5, Claude Sonnet 4.6, or Gemini 2.5 Pro
199
198
  * const response = await ai.prompt({
200
199
  * model: { speed: "capable", cost: "high" },
201
200
  * prompt: "Solve this complex reasoning problem..."
@@ -203,7 +202,7 @@ export type AICapabilities = {
203
202
  *
204
203
  * // Request a specific model with a hint
205
204
  * const response = await ai.prompt({
206
- * model: { speed: "balanced", cost: "medium", hint: AIModel.CLAUDE_SONNET_45 },
205
+ * model: { speed: "balanced", cost: "medium", hint: AIModel.CLAUDE_SONNET_46 },
207
206
  * prompt: "..."
208
207
  * });
209
208
  * ```
@@ -238,7 +237,7 @@ export type ModelPreferences = {
238
237
  * Models are organized by provider:
239
238
  * - **OpenAI**: Latest GPT models via AI Gateway
240
239
  * - **Anthropic**: Claude models via AI Gateway (prefix with "anthropic/")
241
- * - **Google**: Gemini models via AI Gateway (prefix with "google-ai-studio/")
240
+ * - **Google**: Gemini models via AI Gateway (prefix with "google/")
242
241
  * - **Workers AI**: Models running on Cloudflare's network (free/low cost)
243
242
  */
244
243
  export enum AIModel {
@@ -513,7 +512,7 @@ export type AIUsage = {
513
512
  */
514
513
  outputTokens?: number;
515
514
  /**
516
- * The total number of tokens used (promptTokens + completionTokens).
515
+ * The total number of tokens used (inputTokens + outputTokens).
517
516
  */
518
517
  totalTokens?: number;
519
518
  /**
@@ -7,7 +7,7 @@ import { Serializable } from "../utils/types";
7
7
  * Callbacks enable tools and twists to create persistent references to functions
8
8
  * that can survive worker restarts and be invoked across different execution contexts.
9
9
  *
10
- * This is a branded strin
10
+ * This is a branded string
11
11
  * type to prevent mixing callback tokens with regular strings.
12
12
  *
13
13
  * @example
@@ -14,8 +14,8 @@ import { ITool } from "..";
14
14
  */
15
15
  export abstract class Files extends ITool {
16
16
  /**
17
- * Read a file uploaded by a client and attached to a note in a focus
18
- * where this twist is installed.
17
+ * Read a file uploaded by a client and attached to a note on a thread
18
+ * in one of the twist owner's focuses.
19
19
  *
20
20
  * @param fileId The id from an ActionType.file action.
21
21
  * @returns Bytes plus original metadata.
package/src/tools/imap.ts CHANGED
@@ -129,7 +129,7 @@ export type ImapFlagOperation = "add" | "remove" | "set";
129
129
  * @example
130
130
  * ```typescript
131
131
  * class AppleMailConnector extends Connector<AppleMailConnector> {
132
- * build(build: ConnectorBuilder) {
132
+ * build(build: ToolBuilder) {
133
133
  * return {
134
134
  * options: build(Options, {
135
135
  * email: { type: "text", label: "Apple ID Email", default: "" },
@@ -685,8 +685,9 @@ export type AuthToken = {
685
685
  *
686
686
  * For Slack (AuthProvider.Slack):
687
687
  * - authed_user_id: The authenticated user's Slack ID
688
- * - bot_user_id: The bot user's Slack ID
688
+ * - team_id: The Slack workspace/team ID
689
689
  * - team_name: The Slack workspace/team name
690
+ * - enterprise_id: The Enterprise Grid org ID (when applicable)
690
691
  */
691
692
  provider?: Record<string, string>;
692
693
  };
@@ -233,9 +233,9 @@ export abstract class Network extends ITool {
233
233
  * Deletes an existing webhook endpoint.
234
234
  *
235
235
  * Removes the webhook endpoint and stops processing requests.
236
- * Works with all webhook types (standard, Slack, and Gmail).
236
+ * Works with all webhook types (standard, Slack, and Pub/Sub).
237
237
  *
238
- * **For Gmail webhooks:** Also deletes the associated Google Pub/Sub topic and subscription.
238
+ * **For Pub/Sub webhooks (Gmail and Workspace Events):** Also deletes the associated Google Pub/Sub topic and subscription.
239
239
  *
240
240
  * **For Slack webhooks:** Removes the callback registration for the specific team.
241
241
  *
@@ -243,9 +243,9 @@ export abstract class Network extends ITool {
243
243
  * to the deleted webhook will return 404.
244
244
  *
245
245
  * @param url - The webhook identifier returned from `createWebhook()`.
246
- * This can be a URL (standard webhooks), a Pub/Sub topic name (Gmail),
247
- * or an opaque identifier (Slack). Always pass the exact value returned
248
- * from `createWebhook()`.
246
+ * This can be a URL (standard webhooks), a Pub/Sub topic name
247
+ * (Gmail/Workspace Events), or an opaque identifier (Slack).
248
+ * Always pass the exact value returned from `createWebhook()`.
249
249
  * @returns Promise that resolves when the webhook is deleted
250
250
  */
251
251
  abstract deleteWebhook(url: string): Promise<void>;
package/src/tools/plot.ts CHANGED
@@ -146,22 +146,26 @@ export type SearchOptions = {
146
146
  *
147
147
  * @example
148
148
  * ```typescript
149
- * class MyTwist extends Twist {
150
- * private plot: Plot;
151
- *
152
- * constructor(id: string, tools: ToolBuilder) {
153
- * super();
154
- * this.plot = tools.get(Plot);
149
+ * class MyTwist extends Twist<MyTwist> {
150
+ * build(build: ToolBuilder) {
151
+ * return {
152
+ * plot: build(Plot, {
153
+ * thread: { access: ThreadAccess.Create },
154
+ * }),
155
+ * };
155
156
  * }
156
157
  *
157
158
  * async activate() {
158
- * // Create a welcome thread
159
- * await this.plot.createThread({
159
+ * // Create a welcome thread with an opening note
160
+ * await this.tools.plot.createThread({
160
161
  * title: "Welcome to Plot!",
161
- * actions: [{
162
- * title: "Get Started",
163
- * type: ActionType.external,
164
- * url: "https://plot.day/docs"
162
+ * notes: [{
163
+ * content: "Get started with Plot:",
164
+ * actions: [{
165
+ * type: ActionType.external,
166
+ * title: "Get Started",
167
+ * url: "https://plot.day/docs"
168
+ * }]
165
169
  * }]
166
170
  * });
167
171
  * }
@@ -330,8 +334,9 @@ export abstract class Plot extends ITool {
330
334
  * remain unchanged. This enables partial updates without needing to fetch and resend
331
335
  * the entire thread object.
332
336
  *
333
- * For tags, provide a Record<number, boolean> where true adds a tag and false removes it.
334
- * Tags not included in the update remain unchanged.
337
+ * For the twist's own tags, use `twistTags`: a record mapping tag ID to a
338
+ * boolean, where true adds the tag and false removes it. Tags not included
339
+ * in the update remain unchanged.
335
340
  *
336
341
  * Set `focus` to move the thread to a different focus.
337
342
  *
@@ -343,18 +348,18 @@ export abstract class Plot extends ITool {
343
348
  *
344
349
  * @example
345
350
  * ```typescript
346
- * // Mark a task as complete
347
- * await this.plot.updateThread({
348
- * id: "task-123",
349
- * done: new Date()
351
+ * // Archive a thread
352
+ * await this.tools.plot.updateThread({
353
+ * id: threadId,
354
+ * archived: true
350
355
  * });
351
356
  *
352
- * // Add and remove tags
353
- * await this.plot.updateThread({
354
- * id: "thread-789",
355
- * tags: {
356
- * 1: true, // Add tag with ID 1
357
- * 2: false // Remove tag with ID 2
357
+ * // Add and remove the twist's tags
358
+ * await this.tools.plot.updateThread({
359
+ * id: threadId,
360
+ * twistTags: {
361
+ * [Tag.Todo]: true, // Add the to-do tag
362
+ * [Tag.Done]: false // Remove the done tag
358
363
  * }
359
364
  * });
360
365
  * ```
@@ -388,16 +393,16 @@ export abstract class Plot extends ITool {
388
393
  * @example
389
394
  * ```typescript
390
395
  * // Create a note with content
391
- * await this.plot.createNote({
396
+ * await this.tools.plot.createNote({
392
397
  * thread: { id: "thread-123" },
393
- * note: "Discussion notes from the meeting...",
398
+ * content: "Discussion notes from the meeting...",
394
399
  * contentType: "markdown"
395
400
  * });
396
401
  *
397
402
  * // Create a note with actions
398
- * await this.plot.createNote({
403
+ * await this.tools.plot.createNote({
399
404
  * thread: { id: "thread-456" },
400
- * note: "Meeting recording available",
405
+ * content: "Meeting recording available",
401
406
  * actions: [{
402
407
  * type: ActionType.external,
403
408
  * title: "View Recording",
@@ -422,14 +427,14 @@ export abstract class Plot extends ITool {
422
427
  * @example
423
428
  * ```typescript
424
429
  * // Create multiple notes in one batch
425
- * await this.plot.createNotes([
430
+ * await this.tools.plot.createNotes([
426
431
  * {
427
432
  * thread: { id: "thread-123" },
428
- * note: "First message in thread"
433
+ * content: "First message in thread"
429
434
  * },
430
435
  * {
431
436
  * thread: { id: "thread-123" },
432
- * note: "Second message in thread"
437
+ * content: "Second message in thread"
433
438
  * }
434
439
  * ]);
435
440
  * ```
@@ -454,16 +459,16 @@ export abstract class Plot extends ITool {
454
459
  * @example
455
460
  * ```typescript
456
461
  * // Update note content
457
- * await this.plot.updateNote({
462
+ * await this.tools.plot.updateNote({
458
463
  * id: "note-123",
459
- * note: "Updated content with more details"
464
+ * content: "Updated content with more details"
460
465
  * });
461
466
  *
462
467
  * // Add tags to a note
463
- * await this.plot.updateNote({
468
+ * await this.tools.plot.updateNote({
464
469
  * id: "note-456",
465
470
  * twistTags: {
466
- * [Tag.Important]: true
471
+ * [Tag.Todo]: true
467
472
  * }
468
473
  * });
469
474
  * ```
@@ -573,10 +578,10 @@ export abstract class Plot extends ITool {
573
578
  * @example
574
579
  * ```typescript
575
580
  * // Schedule a timed event
576
- * const threadId = await this.plot.createThread({
581
+ * const threadId = await this.tools.plot.createThread({
577
582
  * title: "Team standup"
578
583
  * });
579
- * await this.plot.createSchedule({
584
+ * await this.tools.plot.createSchedule({
580
585
  * threadId,
581
586
  * start: new Date("2025-01-15T10:00:00Z"),
582
587
  * end: new Date("2025-01-15T10:30:00Z"),
package/src/tools/smtp.ts CHANGED
@@ -76,7 +76,7 @@ export type SmtpSendResult = {
76
76
  * @example
77
77
  * ```typescript
78
78
  * class AppleMailConnector extends Connector<AppleMailConnector> {
79
- * build(build: ConnectorBuilder) {
79
+ * build(build: ToolBuilder) {
80
80
  * return {
81
81
  * options: build(Options, {
82
82
  * email: { type: "text", label: "Apple ID Email", default: "" },
@@ -30,18 +30,18 @@ import type { Callback } from "./callbacks";
30
30
  *
31
31
  * @example
32
32
  * ```typescript
33
- * class SyncTool extends Tool {
33
+ * class SyncTool extends Tool<SyncTool> {
34
34
  * async startBatchSync(totalItems: number) {
35
35
  * // Store initial state using built-in set method
36
36
  * await this.set("sync_progress", { processed: 0, total: totalItems });
37
37
  *
38
38
  * // Create callback and queue first batch
39
- * const callback = await this.callback("processBatch", { batchNumber: 1 });
39
+ * const callback = await this.callback(this.processBatch, 1);
40
40
  * // runTask creates NEW execution with fresh ~1000 request limit
41
41
  * await this.runTask(callback);
42
42
  * }
43
43
  *
44
- * async processBatch(args: any, context: { batchNumber: number }) {
44
+ * async processBatch(batchNumber: number) {
45
45
  * // Process one batch of items (sized to stay under request limit)
46
46
  * const progress = await this.get("sync_progress");
47
47
  *
@@ -61,9 +61,7 @@ import type { Callback } from "./callbacks";
61
61
  *
62
62
  * if (progress.processed < progress.total) {
63
63
  * // Queue next batch - creates NEW execution with fresh request limit
64
- * const callback = await this.callback("processBatch", {
65
- * batchNumber: context.batchNumber + 1
66
- * });
64
+ * const callback = await this.callback(this.processBatch, batchNumber + 1);
67
65
  * await this.runTask(callback);
68
66
  * }
69
67
  * }
@@ -72,7 +70,7 @@ import type { Callback } from "./callbacks";
72
70
  * const tomorrow = new Date();
73
71
  * tomorrow.setDate(tomorrow.getDate() + 1);
74
72
  *
75
- * const callback = await this.callback("cleanupOldData");
73
+ * const callback = await this.callback(this.cleanupOldData);
76
74
  * // Schedule for future execution
77
75
  * return await this.runTask(callback, { runAt: tomorrow });
78
76
  * }
@@ -103,7 +101,7 @@ export abstract class Tasks extends ITool {
103
101
  * @example
104
102
  * ```typescript
105
103
  * // Break large loop into batches to stay under request limit
106
- * const callback = await this.callback("syncBatch", { page: 1 });
104
+ * const callback = await this.callback(this.syncBatch, 1);
107
105
  * await this.runTask(callback); // Fresh execution with ~1000 requests
108
106
  * ```
109
107
  */
@@ -61,10 +61,10 @@ export type TwistPermissions = Record<string, Record<string, string[]>>;
61
61
  *
62
62
  * @example
63
63
  * ```typescript
64
- * class TwistBuilderTwist extends Twist {
64
+ * class TwistBuilderTwist extends Twist<TwistBuilderTwist> {
65
65
  * build(build: ToolBuilder) {
66
66
  * return {
67
- * twists: build.get(Twists)
67
+ * twists: build(Twists)
68
68
  * }
69
69
  * }
70
70
  *
@@ -77,14 +77,15 @@ export type TwistPermissions = Record<string, Record<string, string[]>>;
77
77
  */
78
78
  export abstract class Twists extends ITool {
79
79
  /**
80
- * Creates a new twist ID and grants access to people in the current focus.
80
+ * Creates a new twist package ID. Ownership of the ID is claimed lazily
81
+ * on first deploy — no upfront registration happens beyond generating it.
81
82
  *
82
83
  * @returns Promise resolving to the generated twist ID
83
84
  * @throws When twist creation fails
84
85
  *
85
86
  * @example
86
87
  * ```typescript
87
- * const twistId = await twist.create();
88
+ * const twistId = await this.tools.twists.create();
88
89
  * console.log(`Your twist ID: ${twistId}`);
89
90
  * ```
90
91
  */
@@ -103,15 +104,15 @@ export abstract class Twists extends ITool {
103
104
  *
104
105
  * @example
105
106
  * ```typescript
106
- * const source = await twist.generate(`
107
+ * const source = await this.tools.twists.generate(`
107
108
  * # Calendar Sync Twist
108
109
  *
109
- * This twist syncs Google Calendar events to Plot activities.
110
+ * This twist syncs Google Calendar events to Plot threads.
110
111
  *
111
112
  * ## Features
112
113
  * - Authenticate with Google
113
114
  * - Sync calendar events
114
- * - Create activities from events
115
+ * - Create threads from events
115
116
  * `);
116
117
  *
117
118
  * // source.dependencies: { "@plotday/twister": "workspace:^", ... }
@@ -143,7 +144,7 @@ export abstract class Twists extends ITool {
143
144
  * @example
144
145
  * ```typescript
145
146
  * // Deploy with a module
146
- * const result = await twist.deploy({
147
+ * const result = await this.tools.twists.deploy({
147
148
  * twistId: 'abc-123-...',
148
149
  * module: 'export default class MyTwist extends Twist {...}',
149
150
  * environment: 'personal',
@@ -153,8 +154,8 @@ export abstract class Twists extends ITool {
153
154
  * console.log(`Deployed version ${result.version}`);
154
155
  *
155
156
  * // Deploy with source
156
- * const source = await twist.generate(spec);
157
- * const result = await twist.deploy({
157
+ * const source = await this.tools.twists.generate(spec);
158
+ * const result = await this.tools.twists.deploy({
158
159
  * twistId: 'abc-123-...',
159
160
  * source,
160
161
  * environment: 'personal',
@@ -162,7 +163,7 @@ export abstract class Twists extends ITool {
162
163
  * });
163
164
  *
164
165
  * // Validate with dryRun
165
- * const result = await twist.deploy({
166
+ * const result = await this.tools.twists.deploy({
166
167
  * twistId: 'abc-123-...',
167
168
  * source,
168
169
  * dryRun: true,
@@ -209,11 +210,11 @@ export abstract class Twists extends ITool {
209
210
  * @example
210
211
  * ```typescript
211
212
  * // Create twist and callback
212
- * const twistId = await this.twist.create();
213
- * const callback = await this.callback.create("onLogs");
213
+ * const twistId = await this.tools.twists.create();
214
+ * const callback = await this.callback(this.onLogs);
214
215
  *
215
216
  * // Subscribe to logs
216
- * await this.twist.watchLogs(twistId, callback);
217
+ * await this.tools.twists.watchLogs(twistId, callback);
217
218
  *
218
219
  * // Implement handler
219
220
  * async onLogs(logs: Log[]) {
package/src/twist.ts CHANGED
@@ -225,8 +225,8 @@ export abstract class Twist<TSelf> {
225
225
  * await this.set("handler_token", token);
226
226
  *
227
227
  * // Later, execute the callback
228
- * const token = await this.get<string>("handler_token");
229
- * await this.run(token, args);
228
+ * const token = await this.get<Callback>("handler_token");
229
+ * await this.run(token);
230
230
  * ```
231
231
  *
232
232
  * @template T - The type of value being stored (must be Serializable)