@plotday/twister 0.60.0 → 0.61.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 (97) hide show
  1. package/dist/connector.d.ts +44 -1
  2. package/dist/connector.d.ts.map +1 -1
  3. package/dist/connector.js +21 -0
  4. package/dist/connector.js.map +1 -1
  5. package/dist/docs/assets/hierarchy.js +1 -1
  6. package/dist/docs/assets/navigation.js +1 -1
  7. package/dist/docs/assets/search.js +1 -1
  8. package/dist/docs/classes/index.Connector.html +68 -36
  9. package/dist/docs/classes/index.FileNotFoundError.html +1 -1
  10. package/dist/docs/classes/index.Files.html +1 -1
  11. package/dist/docs/classes/index.Imap.html +1 -1
  12. package/dist/docs/classes/index.Options.html +1 -1
  13. package/dist/docs/classes/index.Smtp.html +1 -1
  14. package/dist/docs/classes/tool.ITool.html +1 -1
  15. package/dist/docs/classes/tool.Tool.html +23 -7
  16. package/dist/docs/classes/tools_ai.AI.html +1 -1
  17. package/dist/docs/classes/tools_callbacks.Callbacks.html +1 -1
  18. package/dist/docs/classes/tools_integrations.Integrations.html +1 -1
  19. package/dist/docs/classes/tools_network.Network.html +1 -1
  20. package/dist/docs/classes/tools_plot.Plot.html +1 -1
  21. package/dist/docs/classes/tools_store.Store.html +1 -1
  22. package/dist/docs/classes/tools_tasks.Tasks.html +32 -2
  23. package/dist/docs/classes/tools_twists.Twists.html +1 -1
  24. package/dist/docs/classes/twist.Twist.html +27 -11
  25. package/dist/docs/documents/Built-in_Tools.html +15 -1
  26. package/dist/docs/documents/Runtime_Environment.html +10 -2
  27. package/dist/docs/enums/plot.ActorType.html +4 -4
  28. package/dist/docs/hierarchy.html +1 -1
  29. package/dist/docs/media/AGENTS.md +44 -2
  30. package/dist/docs/modules/index.html +1 -1
  31. package/dist/docs/modules/plot.html +1 -1
  32. package/dist/docs/types/index.CreateLinkDraft.html +9 -9
  33. package/dist/docs/types/index.NoteWriteBackResult.html +21 -2
  34. package/dist/docs/types/index.OptionalScopeGroup.html +6 -6
  35. package/dist/docs/types/index.ResolvedRecipient.html +5 -5
  36. package/dist/docs/types/index.ScopeConfig.html +2 -2
  37. package/dist/docs/types/plot.Actor.html +5 -5
  38. package/dist/docs/types/plot.AutoThreadConfig.html +9 -0
  39. package/dist/docs/types/plot.AutoThreadMode.html +14 -0
  40. package/dist/docs/types/plot.Contact.html +4 -4
  41. package/dist/docs/types/plot.ContentType.html +1 -1
  42. package/dist/docs/types/plot.DeliveryError.html +17 -0
  43. package/dist/docs/types/plot.Link.html +17 -17
  44. package/dist/docs/types/plot.LinkUpdate.html +1 -1
  45. package/dist/docs/types/plot.NewActor.html +1 -1
  46. package/dist/docs/types/plot.NewContact.html +1 -1
  47. package/dist/docs/types/plot.NewLink.html +12 -2
  48. package/dist/docs/types/plot.NewLinkWithNotes.html +11 -3
  49. package/dist/docs/types/plot.NewNote.html +1 -1
  50. package/dist/docs/types/plot.Note.html +2 -5
  51. package/dist/docs/types/plot.NoteUpdate.html +1 -1
  52. package/dist/docs/types/plot.PlanOperation.html +1 -1
  53. package/dist/llm-docs/connector.d.ts +1 -1
  54. package/dist/llm-docs/connector.d.ts.map +1 -1
  55. package/dist/llm-docs/connector.js +1 -1
  56. package/dist/llm-docs/connector.js.map +1 -1
  57. package/dist/llm-docs/plot.d.ts +1 -1
  58. package/dist/llm-docs/plot.d.ts.map +1 -1
  59. package/dist/llm-docs/plot.js +1 -1
  60. package/dist/llm-docs/plot.js.map +1 -1
  61. package/dist/llm-docs/tool.d.ts +1 -1
  62. package/dist/llm-docs/tool.d.ts.map +1 -1
  63. package/dist/llm-docs/tool.js +1 -1
  64. package/dist/llm-docs/tool.js.map +1 -1
  65. package/dist/llm-docs/tools/tasks.d.ts +1 -1
  66. package/dist/llm-docs/tools/tasks.d.ts.map +1 -1
  67. package/dist/llm-docs/tools/tasks.js +1 -1
  68. package/dist/llm-docs/tools/tasks.js.map +1 -1
  69. package/dist/llm-docs/twist.d.ts +1 -1
  70. package/dist/llm-docs/twist.d.ts.map +1 -1
  71. package/dist/llm-docs/twist.js +1 -1
  72. package/dist/llm-docs/twist.js.map +1 -1
  73. package/dist/plot.d.ts +77 -0
  74. package/dist/plot.d.ts.map +1 -1
  75. package/dist/plot.js.map +1 -1
  76. package/dist/tool.d.ts +25 -0
  77. package/dist/tool.d.ts.map +1 -1
  78. package/dist/tool.js +27 -0
  79. package/dist/tool.js.map +1 -1
  80. package/dist/tools/tasks.d.ts +46 -0
  81. package/dist/tools/tasks.d.ts.map +1 -1
  82. package/dist/tools/tasks.js.map +1 -1
  83. package/dist/twist.d.ts +25 -0
  84. package/dist/twist.d.ts.map +1 -1
  85. package/dist/twist.js +27 -0
  86. package/dist/twist.js.map +1 -1
  87. package/package.json +1 -1
  88. package/src/connector.ts +46 -1
  89. package/src/llm-docs/connector.ts +1 -1
  90. package/src/llm-docs/plot.ts +1 -1
  91. package/src/llm-docs/tool.ts +1 -1
  92. package/src/llm-docs/tools/tasks.ts +1 -1
  93. package/src/llm-docs/twist.ts +1 -1
  94. package/src/plot.ts +80 -0
  95. package/src/tool.ts +33 -0
  96. package/src/tools/tasks.ts +52 -0
  97. package/src/twist.ts +33 -0
@@ -23,6 +23,8 @@ handle events.</p>
23
23
  <a href="#runtask" class="tsd-index-link tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>run<wbr/>Task</span></a>
24
24
  <a href="#canceltask" class="tsd-index-link tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>cancel<wbr/>Task</span></a>
25
25
  <a href="#cancelalltasks" class="tsd-index-link tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>cancel<wbr/>All<wbr/>Tasks</span></a>
26
+ <a href="#scheduletask" class="tsd-index-link tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>schedule<wbr/>Task</span></a>
27
+ <a href="#cancelscheduledtask" class="tsd-index-link tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>cancel<wbr/>Scheduled<wbr/>Task</span></a>
26
28
  <a href="#activate" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>activate</span></a>
27
29
  <a href="#upgrade" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>upgrade</span></a>
28
30
  <a href="#onoptionschanged" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>on<wbr/>Options<wbr/>Changed</span></a>
@@ -117,33 +119,47 @@ and other complex types that standard JSON doesn't support.</p>
117
119
  </div></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span></h4><p>Promise that resolves when the cancellation is processed</p>
118
120
  <aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twister/twister/src/twist.ts#L284">twist.ts:284</a></li></ul></aside></div></li></ul></section><section class="tsd-panel tsd-member tsd-is-protected"><h3 class="tsd-anchor-link" id="cancelalltasks"><code class="tsd-tag">Protected</code><span>cancel<wbr/>All<wbr/>Tasks</span><a href="#cancelalltasks" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><ul class="tsd-signatures tsd-is-protected"><li class=""><div class="tsd-signature tsd-anchor-link" id="cancelalltasks-1"><span class="tsd-kind-call-signature">cancelAllTasks</span><span class="tsd-signature-symbol">()</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span><a href="#cancelalltasks-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></div><div class="tsd-description"><div class="tsd-comment tsd-typography"><p>Cancels all scheduled executions for this twist.</p>
119
121
  </div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span></h4><p>Promise that resolves when all cancellations are processed</p>
120
- <aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twister/twister/src/twist.ts#L293">twist.ts:293</a></li></ul></aside></div></li></ul></section><section class="tsd-panel tsd-member"><h3 class="tsd-anchor-link" id="activate"><span>activate</span><a href="#activate" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><ul class="tsd-signatures"><li class=""><div class="tsd-signature tsd-anchor-link" id="activate-1"><span class="tsd-kind-call-signature">activate</span><span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">context</span><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">{</span> <span class="tsd-kind-property">actor</span><span class="tsd-signature-symbol">:</span> <a href="../types/plot.Actor.html" class="tsd-signature-type tsd-kind-type-alias">Actor</a> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span><a href="#activate-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></div><div class="tsd-description"><div class="tsd-comment tsd-typography"><p>Called when the twist is installed by a user.</p>
122
+ <aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twister/twister/src/twist.ts#L293">twist.ts:293</a></li></ul></aside></div></li></ul></section><section class="tsd-panel tsd-member tsd-is-protected"><h3 class="tsd-anchor-link" id="scheduletask"><code class="tsd-tag">Protected</code><span>schedule<wbr/>Task</span><a href="#scheduletask" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><ul class="tsd-signatures tsd-is-protected"><li class=""><div class="tsd-signature tsd-anchor-link" id="scheduletask-1"><span class="tsd-kind-call-signature">scheduleTask</span><span class="tsd-signature-symbol">(</span><br/>    <span class="tsd-kind-parameter">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">,</span><br/>    <span class="tsd-kind-parameter">callback</span><span class="tsd-signature-symbol">:</span> <a href="../types/tools_callbacks.Callback.html" class="tsd-signature-type tsd-kind-type-alias">Callback</a><span class="tsd-signature-symbol">,</span><br/>    <span class="tsd-kind-parameter">options</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">{</span> <span class="tsd-kind-property">runAt</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Date</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">,</span><br/><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span><a href="#scheduletask-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></div><div class="tsd-description"><div class="tsd-comment tsd-typography"><p>Schedules a <strong>singleton</strong> task keyed by <code>key</code>: re-scheduling under the same
123
+ key atomically replaces any pending task, so at most one is ever live.</p>
124
+ <p>Prefer this over <code>runTask({ runAt })</code> for recurring/self-renewing jobs
125
+ (watch renewals, polling, deferred cleanup) — it removes the error-prone
126
+ &quot;store token, cancel before re-scheduling&quot; bookkeeping that otherwise leaks
127
+ parallel task chains. See Tasks.scheduleTask.</p>
128
+ </div><div class="tsd-parameters"><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameter-list"><li><span><span class="tsd-kind-parameter">key</span>: <span class="tsd-signature-type">string</span></span><div class="tsd-comment tsd-typography"><p>Stable identifier scoped to what the task renews</p>
129
+ </div></li><li><span><span class="tsd-kind-parameter">callback</span>: <a href="../types/tools_callbacks.Callback.html" class="tsd-signature-type tsd-kind-type-alias">Callback</a></span><div class="tsd-comment tsd-typography"><p>The callback token created with <code>this.callback()</code></p>
130
+ </div></li><li><span><span class="tsd-kind-parameter">options</span>: <span class="tsd-signature-symbol">{</span> <span class="tsd-kind-property">runAt</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Date</span> <span class="tsd-signature-symbol">}</span></span><ul class="tsd-parameters"><li class="tsd-parameter"><h5><span class="tsd-kind-property">runAt</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">Date</span></h5><div class="tsd-comment tsd-typography"><p>When to run (required)</p>
131
+ </div></li></ul></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span></h4><p>Promise resolving to the scheduled task's cancellation token</p>
132
+ <aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twister/twister/src/twist.ts#L311">twist.ts:311</a></li></ul></aside></div></li></ul></section><section class="tsd-panel tsd-member tsd-is-protected"><h3 class="tsd-anchor-link" id="cancelscheduledtask"><code class="tsd-tag">Protected</code><span>cancel<wbr/>Scheduled<wbr/>Task</span><a href="#cancelscheduledtask" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><ul class="tsd-signatures tsd-is-protected"><li class=""><div class="tsd-signature tsd-anchor-link" id="cancelscheduledtask-1"><span class="tsd-kind-call-signature">cancelScheduledTask</span><span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span><a href="#cancelscheduledtask-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></div><div class="tsd-description"><div class="tsd-comment tsd-typography"><p>Cancels the singleton task previously scheduled under <code>key</code> (if any).
133
+ No-op if none exists or it already ran. See Tasks.cancelScheduledTask.</p>
134
+ </div><div class="tsd-parameters"><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameter-list"><li><span><span class="tsd-kind-parameter">key</span>: <span class="tsd-signature-type">string</span></span><div class="tsd-comment tsd-typography"><p>The same key passed to <a href="#scheduletask" class="tsd-kind-method">scheduleTask</a></p>
135
+ </div></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span></h4><p>Promise that resolves when the cancellation is processed</p>
136
+ <aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twister/twister/src/twist.ts#L326">twist.ts:326</a></li></ul></aside></div></li></ul></section><section class="tsd-panel tsd-member"><h3 class="tsd-anchor-link" id="activate"><span>activate</span><a href="#activate" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><ul class="tsd-signatures"><li class=""><div class="tsd-signature tsd-anchor-link" id="activate-1"><span class="tsd-kind-call-signature">activate</span><span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">context</span><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">{</span> <span class="tsd-kind-property">actor</span><span class="tsd-signature-symbol">:</span> <a href="../types/plot.Actor.html" class="tsd-signature-type tsd-kind-type-alias">Actor</a> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span><a href="#activate-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></div><div class="tsd-description"><div class="tsd-comment tsd-typography"><p>Called when the twist is installed by a user.</p>
121
137
  <p>This method should contain initialization logic such as seeding
122
138
  initial threads, configuring webhooks, or establishing external
123
139
  connections. When it runs, <code>this.userId</code> is already populated with
124
140
  the installing user's ID.</p>
125
141
  </div><div class="tsd-parameters"><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameter-list"><li><span><code class="tsd-tag">Optional</code><span class="tsd-kind-parameter">context</span>: <span class="tsd-signature-symbol">{</span> <span class="tsd-kind-property">actor</span><span class="tsd-signature-symbol">:</span> <a href="../types/plot.Actor.html" class="tsd-signature-type tsd-kind-type-alias">Actor</a> <span class="tsd-signature-symbol">}</span></span><div class="tsd-comment tsd-typography"><p>Optional context containing the actor who triggered activation</p>
126
142
  </div></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span></h4><p>Promise that resolves when activation is complete</p>
127
- <aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twister/twister/src/twist.ts#L309">twist.ts:309</a></li></ul></aside></div></li></ul></section><section class="tsd-panel tsd-member"><h3 class="tsd-anchor-link" id="upgrade"><span>upgrade</span><a href="#upgrade" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><ul class="tsd-signatures"><li class=""><div class="tsd-signature tsd-anchor-link" id="upgrade-1"><span class="tsd-kind-call-signature">upgrade</span><span class="tsd-signature-symbol">()</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span><a href="#upgrade-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></div><div class="tsd-description"><div class="tsd-comment tsd-typography"><p>Called when a new version of the twist is deployed.</p>
143
+ <aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twister/twister/src/twist.ts#L342">twist.ts:342</a></li></ul></aside></div></li></ul></section><section class="tsd-panel tsd-member"><h3 class="tsd-anchor-link" id="upgrade"><span>upgrade</span><a href="#upgrade" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><ul class="tsd-signatures"><li class=""><div class="tsd-signature tsd-anchor-link" id="upgrade-1"><span class="tsd-kind-call-signature">upgrade</span><span class="tsd-signature-symbol">()</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span><a href="#upgrade-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></div><div class="tsd-description"><div class="tsd-comment tsd-typography"><p>Called when a new version of the twist is deployed.</p>
128
144
  <p>This method should contain migration logic for updating old data structures
129
145
  or setting up new resources that weren't needed by the previous version.
130
146
  It is called once per active twist_instance with the new version.</p>
131
147
  </div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span></h4><p>Promise that resolves when upgrade is complete</p>
132
- <aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twister/twister/src/twist.ts#L322">twist.ts:322</a></li></ul></aside></div></li></ul></section><section class="tsd-panel tsd-member"><h3 class="tsd-anchor-link" id="onoptionschanged"><span>on<wbr/>Options<wbr/>Changed</span><a href="#onoptionschanged" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><ul class="tsd-signatures"><li class=""><div class="tsd-signature tsd-anchor-link" id="onoptionschanged-1"><span class="tsd-kind-call-signature">onOptionsChanged</span><span class="tsd-signature-symbol">(</span><br/>    <span class="tsd-kind-parameter">oldOptions</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Record</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">,</span> <span class="tsd-signature-type">any</span><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol">,</span><br/>    <span class="tsd-kind-parameter">newOptions</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Record</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">,</span> <span class="tsd-signature-type">any</span><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol">,</span><br/><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span><a href="#onoptionschanged-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></div><div class="tsd-description"><div class="tsd-comment tsd-typography"><p>Called when the twist's options configuration changes.</p>
148
+ <aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twister/twister/src/twist.ts#L355">twist.ts:355</a></li></ul></aside></div></li></ul></section><section class="tsd-panel tsd-member"><h3 class="tsd-anchor-link" id="onoptionschanged"><span>on<wbr/>Options<wbr/>Changed</span><a href="#onoptionschanged" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><ul class="tsd-signatures"><li class=""><div class="tsd-signature tsd-anchor-link" id="onoptionschanged-1"><span class="tsd-kind-call-signature">onOptionsChanged</span><span class="tsd-signature-symbol">(</span><br/>    <span class="tsd-kind-parameter">oldOptions</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Record</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">,</span> <span class="tsd-signature-type">any</span><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol">,</span><br/>    <span class="tsd-kind-parameter">newOptions</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Record</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">,</span> <span class="tsd-signature-type">any</span><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol">,</span><br/><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span><a href="#onoptionschanged-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></div><div class="tsd-description"><div class="tsd-comment tsd-typography"><p>Called when the twist's options configuration changes.</p>
133
149
  <p>Override to react to option changes, e.g. archiving items when a sync
134
150
  type is toggled off, or starting sync when a type is toggled on.</p>
135
151
  </div><div class="tsd-parameters"><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameter-list"><li><span><span class="tsd-kind-parameter">oldOptions</span>: <span class="tsd-signature-type">Record</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">,</span> <span class="tsd-signature-type">any</span><span class="tsd-signature-symbol">&gt;</span></span><div class="tsd-comment tsd-typography"><p>The previously resolved options</p>
136
152
  </div></li><li><span><span class="tsd-kind-parameter">newOptions</span>: <span class="tsd-signature-type">Record</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">,</span> <span class="tsd-signature-type">any</span><span class="tsd-signature-symbol">&gt;</span></span><div class="tsd-comment tsd-typography"><p>The newly resolved options</p>
137
153
  </div></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span></h4><p>Promise that resolves when the change is handled</p>
138
- <aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twister/twister/src/twist.ts#L337">twist.ts:337</a></li></ul></aside></div></li></ul></section><section class="tsd-panel tsd-member"><h3 class="tsd-anchor-link" id="deactivate"><span>deactivate</span><a href="#deactivate" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><ul class="tsd-signatures"><li class=""><div class="tsd-signature tsd-anchor-link" id="deactivate-1"><span class="tsd-kind-call-signature">deactivate</span><span class="tsd-signature-symbol">()</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span><a href="#deactivate-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></div><div class="tsd-description"><div class="tsd-comment tsd-typography"><p>Called when the twist is uninstalled.</p>
154
+ <aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twister/twister/src/twist.ts#L370">twist.ts:370</a></li></ul></aside></div></li></ul></section><section class="tsd-panel tsd-member"><h3 class="tsd-anchor-link" id="deactivate"><span>deactivate</span><a href="#deactivate" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><ul class="tsd-signatures"><li class=""><div class="tsd-signature tsd-anchor-link" id="deactivate-1"><span class="tsd-kind-call-signature">deactivate</span><span class="tsd-signature-symbol">()</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span><a href="#deactivate-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></div><div class="tsd-description"><div class="tsd-comment tsd-typography"><p>Called when the twist is uninstalled.</p>
139
155
  <p>This method should contain cleanup logic such as removing webhooks,
140
156
  cleaning up external resources, or performing final data operations.</p>
141
157
  </div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span></h4><p>Promise that resolves when deactivation is complete</p>
142
- <aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twister/twister/src/twist.ts#L352">twist.ts:352</a></li></ul></aside></div></li></ul></section><section class="tsd-panel tsd-member"><h3 class="tsd-anchor-link" id="onthreadupdated"><span>on<wbr/>Thread<wbr/>Updated</span><a href="#onthreadupdated" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><ul class="tsd-signatures"><li class=""><div class="tsd-signature tsd-anchor-link" id="onthreadupdated-1"><span class="tsd-kind-call-signature">onThreadUpdated</span><span class="tsd-signature-symbol">(</span><br/>    <span class="tsd-kind-parameter">thread</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">ThreadFields</span><span class="tsd-signature-symbol">,</span><br/>    <span class="tsd-kind-parameter">changes</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">{</span><br/>        <span class="tsd-kind-property">tagsAdded</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Record</span><span class="tsd-signature-symbol">&lt;</span><a href="../enums/tag.Tag.html" class="tsd-signature-type tsd-kind-enum">Tag</a><span class="tsd-signature-symbol">,</span> <a href="../types/plot.ActorId.html" class="tsd-signature-type tsd-kind-type-alias">ActorId</a><span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol">;</span><br/>        <span class="tsd-kind-property">tagsRemoved</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Record</span><span class="tsd-signature-symbol">&lt;</span><a href="../enums/tag.Tag.html" class="tsd-signature-type tsd-kind-enum">Tag</a><span class="tsd-signature-symbol">,</span> <a href="../types/plot.ActorId.html" class="tsd-signature-type tsd-kind-type-alias">ActorId</a><span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol">;</span><br/>    <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">,</span><br/><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span><a href="#onthreadupdated-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></div><div class="tsd-description"><div class="tsd-comment tsd-typography"><p>Called when a thread created by this twist is updated.
158
+ <aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twister/twister/src/twist.ts#L385">twist.ts:385</a></li></ul></aside></div></li></ul></section><section class="tsd-panel tsd-member"><h3 class="tsd-anchor-link" id="onthreadupdated"><span>on<wbr/>Thread<wbr/>Updated</span><a href="#onthreadupdated" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><ul class="tsd-signatures"><li class=""><div class="tsd-signature tsd-anchor-link" id="onthreadupdated-1"><span class="tsd-kind-call-signature">onThreadUpdated</span><span class="tsd-signature-symbol">(</span><br/>    <span class="tsd-kind-parameter">thread</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">ThreadFields</span><span class="tsd-signature-symbol">,</span><br/>    <span class="tsd-kind-parameter">changes</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">{</span><br/>        <span class="tsd-kind-property">tagsAdded</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Record</span><span class="tsd-signature-symbol">&lt;</span><a href="../enums/tag.Tag.html" class="tsd-signature-type tsd-kind-enum">Tag</a><span class="tsd-signature-symbol">,</span> <a href="../types/plot.ActorId.html" class="tsd-signature-type tsd-kind-type-alias">ActorId</a><span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol">;</span><br/>        <span class="tsd-kind-property">tagsRemoved</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Record</span><span class="tsd-signature-symbol">&lt;</span><a href="../enums/tag.Tag.html" class="tsd-signature-type tsd-kind-enum">Tag</a><span class="tsd-signature-symbol">,</span> <a href="../types/plot.ActorId.html" class="tsd-signature-type tsd-kind-type-alias">ActorId</a><span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol">;</span><br/>    <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">,</span><br/><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span><a href="#onthreadupdated-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></div><div class="tsd-description"><div class="tsd-comment tsd-typography"><p>Called when a thread created by this twist is updated.
143
159
  Override to implement two-way sync with an external system.</p>
144
160
  </div><div class="tsd-parameters"><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameter-list"><li><span><span class="tsd-kind-parameter">thread</span>: <span class="tsd-signature-type">ThreadFields</span></span><div class="tsd-comment tsd-typography"><p>The updated thread</p>
145
161
  </div></li><li><span><span class="tsd-kind-parameter">changes</span>: <span class="tsd-signature-symbol">{</span> <span class="tsd-kind-property">tagsAdded</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Record</span><span class="tsd-signature-symbol">&lt;</span><a href="../enums/tag.Tag.html" class="tsd-signature-type tsd-kind-enum">Tag</a><span class="tsd-signature-symbol">,</span> <a href="../types/plot.ActorId.html" class="tsd-signature-type tsd-kind-type-alias">ActorId</a><span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol">;</span> <span class="tsd-kind-property">tagsRemoved</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Record</span><span class="tsd-signature-symbol">&lt;</span><a href="../enums/tag.Tag.html" class="tsd-signature-type tsd-kind-enum">Tag</a><span class="tsd-signature-symbol">,</span> <a href="../types/plot.ActorId.html" class="tsd-signature-type tsd-kind-type-alias">ActorId</a><span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol">&gt;</span> <span class="tsd-signature-symbol">}</span></span><div class="tsd-comment tsd-typography"><p>Tag additions and removals on the thread</p>
146
- </div></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span></h4><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twister/twister/src/twist.ts#L364">twist.ts:364</a></li></ul></aside></div></li></ul></section><section class="tsd-panel tsd-member"><h3 class="tsd-anchor-link" id="onnotecreated"><span>on<wbr/>Note<wbr/>Created</span><a href="#onnotecreated" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><ul class="tsd-signatures"><li class=""><div class="tsd-signature tsd-anchor-link" id="onnotecreated-1"><span class="tsd-kind-call-signature">onNoteCreated</span><span class="tsd-signature-symbol">(</span><br/>    <span class="tsd-kind-parameter">note</span><span class="tsd-signature-symbol">:</span> <a href="../types/plot.Note.html" class="tsd-signature-type tsd-kind-type-alias">Note</a><span class="tsd-signature-symbol">,</span><br/>    <span class="tsd-signature-symbol">...</span><span class="tsd-kind-parameter">args</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">any</span><span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol">,</span><br/><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">void</span> <span class="tsd-signature-symbol">|</span> <a href="../types/index.NoteWriteBackResult.html" class="tsd-signature-type tsd-kind-type-alias">NoteWriteBackResult</a><span class="tsd-signature-symbol">&gt;</span><a href="#onnotecreated-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></div><div class="tsd-description"><div class="tsd-comment tsd-typography"><p>Called when a note is created on a thread created by this twist.
162
+ </div></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span></h4><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twister/twister/src/twist.ts#L397">twist.ts:397</a></li></ul></aside></div></li></ul></section><section class="tsd-panel tsd-member"><h3 class="tsd-anchor-link" id="onnotecreated"><span>on<wbr/>Note<wbr/>Created</span><a href="#onnotecreated" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><ul class="tsd-signatures"><li class=""><div class="tsd-signature tsd-anchor-link" id="onnotecreated-1"><span class="tsd-kind-call-signature">onNoteCreated</span><span class="tsd-signature-symbol">(</span><br/>    <span class="tsd-kind-parameter">note</span><span class="tsd-signature-symbol">:</span> <a href="../types/plot.Note.html" class="tsd-signature-type tsd-kind-type-alias">Note</a><span class="tsd-signature-symbol">,</span><br/>    <span class="tsd-signature-symbol">...</span><span class="tsd-kind-parameter">args</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">any</span><span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol">,</span><br/><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">void</span> <span class="tsd-signature-symbol">|</span> <a href="../types/index.NoteWriteBackResult.html" class="tsd-signature-type tsd-kind-type-alias">NoteWriteBackResult</a><span class="tsd-signature-symbol">&gt;</span><a href="#onnotecreated-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></div><div class="tsd-description"><div class="tsd-comment tsd-typography"><p>Called when a note is created on a thread created by this twist.
147
163
  Override to implement two-way sync (e.g. syncing notes as comments).</p>
148
164
  <p>Notes created by the twist itself are filtered out to prevent loops.</p>
149
165
  <p>Returning a string sets the note's <code>key</code> for future upsert matching,
@@ -151,19 +167,19 @@ linking the Plot note to its external counterpart so that subsequent
151
167
  syncs (reactions, edits) update the existing note instead of creating duplicates.</p>
152
168
  </div><div class="tsd-parameters"><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameter-list"><li><span><span class="tsd-kind-parameter">note</span>: <a href="../types/plot.Note.html" class="tsd-signature-type tsd-kind-type-alias">Note</a></span><div class="tsd-comment tsd-typography"><p>The newly created note</p>
153
169
  </div></li><li><span><span class="tsd-signature-symbol">...</span><span class="tsd-kind-parameter">args</span>: <span class="tsd-signature-type">any</span><span class="tsd-signature-symbol">[]</span></span></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">void</span> <span class="tsd-signature-symbol">|</span> <a href="../types/index.NoteWriteBackResult.html" class="tsd-signature-type tsd-kind-type-alias">NoteWriteBackResult</a><span class="tsd-signature-symbol">&gt;</span></h4><p>Optional note key for external deduplication</p>
154
- <aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twister/twister/src/twist.ts#L388">twist.ts:388</a></li></ul></aside></div></li></ul></section><section class="tsd-panel tsd-member"><h3 class="tsd-anchor-link" id="onlinkcreated"><span>on<wbr/>Link<wbr/>Created</span><a href="#onlinkcreated" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><ul class="tsd-signatures"><li class=""><div class="tsd-signature tsd-anchor-link" id="onlinkcreated-1"><span class="tsd-kind-call-signature">onLinkCreated</span><span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">link</span><span class="tsd-signature-symbol">:</span> <a href="../types/plot.Link.html" class="tsd-signature-type tsd-kind-type-alias">Link</a><span class="tsd-signature-symbol">,</span> <span class="tsd-kind-parameter">notes</span><span class="tsd-signature-symbol">:</span> <a href="../types/plot.Note.html" class="tsd-signature-type tsd-kind-type-alias">Note</a><span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span><a href="#onlinkcreated-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></div><div class="tsd-description"><div class="tsd-comment tsd-typography"><p>Called when a link is created in a connected source channel.
170
+ <aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twister/twister/src/twist.ts#L421">twist.ts:421</a></li></ul></aside></div></li></ul></section><section class="tsd-panel tsd-member"><h3 class="tsd-anchor-link" id="onlinkcreated"><span>on<wbr/>Link<wbr/>Created</span><a href="#onlinkcreated" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><ul class="tsd-signatures"><li class=""><div class="tsd-signature tsd-anchor-link" id="onlinkcreated-1"><span class="tsd-kind-call-signature">onLinkCreated</span><span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">link</span><span class="tsd-signature-symbol">:</span> <a href="../types/plot.Link.html" class="tsd-signature-type tsd-kind-type-alias">Link</a><span class="tsd-signature-symbol">,</span> <span class="tsd-kind-parameter">notes</span><span class="tsd-signature-symbol">:</span> <a href="../types/plot.Note.html" class="tsd-signature-type tsd-kind-type-alias">Note</a><span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span><a href="#onlinkcreated-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></div><div class="tsd-description"><div class="tsd-comment tsd-typography"><p>Called when a link is created in a connected source channel.
155
171
  Requires <code>link: true</code> in Plot options.</p>
156
172
  </div><div class="tsd-parameters"><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameter-list"><li><span><span class="tsd-kind-parameter">link</span>: <a href="../types/plot.Link.html" class="tsd-signature-type tsd-kind-type-alias">Link</a></span><div class="tsd-comment tsd-typography"><p>The newly created link</p>
157
173
  </div></li><li><span><span class="tsd-kind-parameter">notes</span>: <a href="../types/plot.Note.html" class="tsd-signature-type tsd-kind-type-alias">Note</a><span class="tsd-signature-symbol">[]</span></span><div class="tsd-comment tsd-typography"><p>Notes on the link's thread</p>
158
- </div></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span></h4><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twister/twister/src/twist.ts#L400">twist.ts:400</a></li></ul></aside></div></li></ul></section><section class="tsd-panel tsd-member"><h3 class="tsd-anchor-link" id="onlinkupdated"><span>on<wbr/>Link<wbr/>Updated</span><a href="#onlinkupdated" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><ul class="tsd-signatures"><li class=""><div class="tsd-signature tsd-anchor-link" id="onlinkupdated-1"><span class="tsd-kind-call-signature">onLinkUpdated</span><span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">link</span><span class="tsd-signature-symbol">:</span> <a href="../types/plot.Link.html" class="tsd-signature-type tsd-kind-type-alias">Link</a><span class="tsd-signature-symbol">,</span> <span class="tsd-kind-parameter">notes</span><span class="tsd-signature-symbol">?:</span> <a href="../types/plot.Note.html" class="tsd-signature-type tsd-kind-type-alias">Note</a><span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span><a href="#onlinkupdated-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></div><div class="tsd-description"><div class="tsd-comment tsd-typography"><p>Called when a link in a connected source channel is updated.
174
+ </div></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span></h4><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twister/twister/src/twist.ts#L433">twist.ts:433</a></li></ul></aside></div></li></ul></section><section class="tsd-panel tsd-member"><h3 class="tsd-anchor-link" id="onlinkupdated"><span>on<wbr/>Link<wbr/>Updated</span><a href="#onlinkupdated" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><ul class="tsd-signatures"><li class=""><div class="tsd-signature tsd-anchor-link" id="onlinkupdated-1"><span class="tsd-kind-call-signature">onLinkUpdated</span><span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">link</span><span class="tsd-signature-symbol">:</span> <a href="../types/plot.Link.html" class="tsd-signature-type tsd-kind-type-alias">Link</a><span class="tsd-signature-symbol">,</span> <span class="tsd-kind-parameter">notes</span><span class="tsd-signature-symbol">?:</span> <a href="../types/plot.Note.html" class="tsd-signature-type tsd-kind-type-alias">Note</a><span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span><a href="#onlinkupdated-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></div><div class="tsd-description"><div class="tsd-comment tsd-typography"><p>Called when a link in a connected source channel is updated.
159
175
  Requires <code>link: true</code> in Plot options.</p>
160
176
  </div><div class="tsd-parameters"><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameter-list"><li><span><span class="tsd-kind-parameter">link</span>: <a href="../types/plot.Link.html" class="tsd-signature-type tsd-kind-type-alias">Link</a></span><div class="tsd-comment tsd-typography"><p>The updated link</p>
161
177
  </div></li><li><span><code class="tsd-tag">Optional</code><span class="tsd-kind-parameter">notes</span>: <a href="../types/plot.Note.html" class="tsd-signature-type tsd-kind-type-alias">Note</a><span class="tsd-signature-symbol">[]</span></span><div class="tsd-comment tsd-typography"><p>Notes on the link's thread (optional)</p>
162
- </div></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span></h4><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twister/twister/src/twist.ts#L412">twist.ts:412</a></li></ul></aside></div></li></ul></section><section class="tsd-panel tsd-member"><h3 class="tsd-anchor-link" id="onlinknotecreated"><span>on<wbr/>Link<wbr/>Note<wbr/>Created</span><a href="#onlinknotecreated" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><ul class="tsd-signatures"><li class=""><div class="tsd-signature tsd-anchor-link" id="onlinknotecreated-1"><span class="tsd-kind-call-signature">onLinkNoteCreated</span><span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">note</span><span class="tsd-signature-symbol">:</span> <a href="../types/plot.Note.html" class="tsd-signature-type tsd-kind-type-alias">Note</a><span class="tsd-signature-symbol">,</span> <span class="tsd-kind-parameter">link</span><span class="tsd-signature-symbol">:</span> <a href="../types/plot.Link.html" class="tsd-signature-type tsd-kind-type-alias">Link</a><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span><a href="#onlinknotecreated-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></div><div class="tsd-description"><div class="tsd-comment tsd-typography"><p>Called when a note is created on a thread with a link from a connected channel.
178
+ </div></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span></h4><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twister/twister/src/twist.ts#L445">twist.ts:445</a></li></ul></aside></div></li></ul></section><section class="tsd-panel tsd-member"><h3 class="tsd-anchor-link" id="onlinknotecreated"><span>on<wbr/>Link<wbr/>Note<wbr/>Created</span><a href="#onlinknotecreated" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><ul class="tsd-signatures"><li class=""><div class="tsd-signature tsd-anchor-link" id="onlinknotecreated-1"><span class="tsd-kind-call-signature">onLinkNoteCreated</span><span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">note</span><span class="tsd-signature-symbol">:</span> <a href="../types/plot.Note.html" class="tsd-signature-type tsd-kind-type-alias">Note</a><span class="tsd-signature-symbol">,</span> <span class="tsd-kind-parameter">link</span><span class="tsd-signature-symbol">:</span> <a href="../types/plot.Link.html" class="tsd-signature-type tsd-kind-type-alias">Link</a><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span><a href="#onlinknotecreated-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></div><div class="tsd-description"><div class="tsd-comment tsd-typography"><p>Called when a note is created on a thread with a link from a connected channel.
163
179
  Requires <code>link: true</code> in Plot options.</p>
164
180
  </div><div class="tsd-parameters"><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameter-list"><li><span><span class="tsd-kind-parameter">note</span>: <a href="../types/plot.Note.html" class="tsd-signature-type tsd-kind-type-alias">Note</a></span><div class="tsd-comment tsd-typography"><p>The newly created note</p>
165
181
  </div></li><li><span><span class="tsd-kind-parameter">link</span>: <a href="../types/plot.Link.html" class="tsd-signature-type tsd-kind-type-alias">Link</a></span><div class="tsd-comment tsd-typography"><p>The link associated with the thread</p>
166
- </div></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span></h4><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twister/twister/src/twist.ts#L424">twist.ts:424</a></li></ul></aside></div></li></ul></section></section></details><details class="tsd-panel-group tsd-member-group tsd-accordion" open><summary class="tsd-accordion-summary" data-key="section-Properties"><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>Properties</h2></summary><section><section class="tsd-panel tsd-member"><h3 class="tsd-anchor-link" id="multipleinstances"><code class="tsd-tag">Static</code> <code class="tsd-tag">Optional</code> <code class="tsd-tag">Readonly</code><span>multiple<wbr/>Instances</span><a href="#multipleinstances" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><div class="tsd-signature"><span class="tsd-kind-property">multipleInstances</span><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">boolean</span></div><div class="tsd-comment tsd-typography"><p>When <code>true</code>, users may install multiple instances of this twist within
182
+ </div></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span></h4><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twister/twister/src/twist.ts#L457">twist.ts:457</a></li></ul></aside></div></li></ul></section></section></details><details class="tsd-panel-group tsd-member-group tsd-accordion" open><summary class="tsd-accordion-summary" data-key="section-Properties"><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>Properties</h2></summary><section><section class="tsd-panel tsd-member"><h3 class="tsd-anchor-link" id="multipleinstances"><code class="tsd-tag">Static</code> <code class="tsd-tag">Optional</code> <code class="tsd-tag">Readonly</code><span>multiple<wbr/>Instances</span><a href="#multipleinstances" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><div class="tsd-signature"><span class="tsd-kind-property">multipleInstances</span><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">boolean</span></div><div class="tsd-comment tsd-typography"><p>When <code>true</code>, users may install multiple instances of this twist within
167
183
  the same scope (personal workspace or team). Each instance must have a
168
184
  distinct name.</p>
169
185
  <p>Defaults to <code>false</code> (single instance per scope).</p>
@@ -172,4 +188,4 @@ distinct name.</p>
172
188
 
173
189
  </div></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twister/twister/src/twist.ts#L53">twist.ts:53</a></li></ul></aside></section><section class="tsd-panel tsd-member tsd-is-protected"><h3 class="tsd-anchor-link" id="userid"><code class="tsd-tag">Protected</code><span>user<wbr/>Id</span><a href="#userid" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><div class="tsd-signature"><span class="tsd-kind-property">userId</span><span class="tsd-signature-symbol">:</span> <a href="../types/index.Uuid.html" class="tsd-signature-type tsd-kind-type-alias">Uuid</a></div><div class="tsd-comment tsd-typography"><p>The user ID (<code>twist_instance.owner_id</code>) that installed this twist.
174
190
  Populated by the runtime before any lifecycle method runs.</p>
175
- </div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twister/twister/src/twist.ts#L59">twist.ts:59</a></li></ul></aside></section><section class="tsd-panel tsd-member tsd-is-protected"><h3 class="tsd-anchor-link" id="id"><code class="tsd-tag">Protected</code><span>id</span><a href="#id" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><div class="tsd-signature"><span class="tsd-kind-property">id</span><span class="tsd-signature-symbol">:</span> <a href="../types/index.Uuid.html" class="tsd-signature-type tsd-kind-type-alias">Uuid</a></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twister/twister/src/twist.ts#L61">twist.ts:61</a></li></ul></aside></section></section></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-Accessors"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>Accessors</summary><div><a href="#tools" class="tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Accessor"><use href="../assets/icons.svg#icon-262144"></use></svg><span>tools</span></a></div></details><details open class="tsd-accordion tsd-page-navigation-section"><summary class="tsd-accordion-summary" data-key="section-Constructors"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>Constructors</summary><div><a href="#constructor"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Constructor"><use href="../assets/icons.svg#icon-512"></use></svg><span>constructor</span></a></div></details><details open class="tsd-accordion tsd-page-navigation-section"><summary class="tsd-accordion-summary" data-key="section-Methods"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>Methods</summary><div><a href="#build"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>build</span></a><a href="#callback" class="tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>callback</span></a><a href="#actioncallback" class="tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>action<wbr/>Callback</span></a><a href="#deletecallback" class="tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>delete<wbr/>Callback</span></a><a href="#deleteallcallbacks" class="tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>delete<wbr/>All<wbr/>Callbacks</span></a><a href="#run" class="tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>run</span></a><a href="#get" class="tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>get</span></a><a href="#set" class="tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>set</span></a><a href="#clear" class="tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>clear</span></a><a href="#clearall" class="tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>clear<wbr/>All</span></a><a href="#runtask" class="tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>run<wbr/>Task</span></a><a href="#canceltask" class="tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>cancel<wbr/>Task</span></a><a href="#cancelalltasks" class="tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>cancel<wbr/>All<wbr/>Tasks</span></a><a href="#activate"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>activate</span></a><a href="#upgrade"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>upgrade</span></a><a href="#onoptionschanged"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>on<wbr/>Options<wbr/>Changed</span></a><a href="#deactivate"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>deactivate</span></a><a href="#onthreadupdated"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>on<wbr/>Thread<wbr/>Updated</span></a><a href="#onnotecreated"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>on<wbr/>Note<wbr/>Created</span></a><a href="#onlinkcreated"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>on<wbr/>Link<wbr/>Created</span></a><a href="#onlinkupdated"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>on<wbr/>Link<wbr/>Updated</span></a><a href="#onlinknotecreated"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>on<wbr/>Link<wbr/>Note<wbr/>Created</span></a></div></details><details open class="tsd-accordion tsd-page-navigation-section"><summary class="tsd-accordion-summary" data-key="section-Properties"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>Properties</summary><div><a href="#multipleinstances"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Property"><use href="../assets/icons.svg#icon-1024"></use></svg><span>multiple<wbr/>Instances</span></a><a href="#userid" class="tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Property"><use href="../assets/icons.svg#icon-1024"></use></svg><span>user<wbr/>Id</span></a><a href="#id" class="tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Property"><use href="../assets/icons.svg#icon-1024"></use></svg><span>id</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">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>
191
+ </div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twister/twister/src/twist.ts#L59">twist.ts:59</a></li></ul></aside></section><section class="tsd-panel tsd-member tsd-is-protected"><h3 class="tsd-anchor-link" id="id"><code class="tsd-tag">Protected</code><span>id</span><a href="#id" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><div class="tsd-signature"><span class="tsd-kind-property">id</span><span class="tsd-signature-symbol">:</span> <a href="../types/index.Uuid.html" class="tsd-signature-type tsd-kind-type-alias">Uuid</a></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twister/twister/src/twist.ts#L61">twist.ts:61</a></li></ul></aside></section></section></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-Accessors"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>Accessors</summary><div><a href="#tools" class="tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Accessor"><use href="../assets/icons.svg#icon-262144"></use></svg><span>tools</span></a></div></details><details open class="tsd-accordion tsd-page-navigation-section"><summary class="tsd-accordion-summary" data-key="section-Constructors"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>Constructors</summary><div><a href="#constructor"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Constructor"><use href="../assets/icons.svg#icon-512"></use></svg><span>constructor</span></a></div></details><details open class="tsd-accordion tsd-page-navigation-section"><summary class="tsd-accordion-summary" data-key="section-Methods"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>Methods</summary><div><a href="#build"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>build</span></a><a href="#callback" class="tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>callback</span></a><a href="#actioncallback" class="tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>action<wbr/>Callback</span></a><a href="#deletecallback" class="tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>delete<wbr/>Callback</span></a><a href="#deleteallcallbacks" class="tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>delete<wbr/>All<wbr/>Callbacks</span></a><a href="#run" class="tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>run</span></a><a href="#get" class="tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>get</span></a><a href="#set" class="tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>set</span></a><a href="#clear" class="tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>clear</span></a><a href="#clearall" class="tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>clear<wbr/>All</span></a><a href="#runtask" class="tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>run<wbr/>Task</span></a><a href="#canceltask" class="tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>cancel<wbr/>Task</span></a><a href="#cancelalltasks" class="tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>cancel<wbr/>All<wbr/>Tasks</span></a><a href="#scheduletask" class="tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>schedule<wbr/>Task</span></a><a href="#cancelscheduledtask" class="tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>cancel<wbr/>Scheduled<wbr/>Task</span></a><a href="#activate"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>activate</span></a><a href="#upgrade"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>upgrade</span></a><a href="#onoptionschanged"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>on<wbr/>Options<wbr/>Changed</span></a><a href="#deactivate"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>deactivate</span></a><a href="#onthreadupdated"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>on<wbr/>Thread<wbr/>Updated</span></a><a href="#onnotecreated"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>on<wbr/>Note<wbr/>Created</span></a><a href="#onlinkcreated"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>on<wbr/>Link<wbr/>Created</span></a><a href="#onlinkupdated"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>on<wbr/>Link<wbr/>Updated</span></a><a href="#onlinknotecreated"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Method"><use href="../assets/icons.svg#icon-2048"></use></svg><span>on<wbr/>Link<wbr/>Note<wbr/>Created</span></a></div></details><details open class="tsd-accordion tsd-page-navigation-section"><summary class="tsd-accordion-summary" data-key="section-Properties"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>Properties</summary><div><a href="#multipleinstances"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Property"><use href="../assets/icons.svg#icon-1024"></use></svg><span>multiple<wbr/>Instances</span></a><a href="#userid" class="tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Property"><use href="../assets/icons.svg#icon-1024"></use></svg><span>user<wbr/>Id</span></a><a href="#id" class="tsd-is-protected"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Property"><use href="../assets/icons.svg#icon-1024"></use></svg><span>id</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">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>
@@ -184,6 +184,20 @@
184
184
  </code><button type="button">Copy</button></pre>
185
185
 
186
186
  <p>Immediate (non-scheduled) tasks cannot be cancelled.</p>
187
+ <h3 id="recurring-self-renewing-tasks-→" class="tsd-anchor-link">Recurring / self-renewing tasks → <code>scheduleTask</code><a href="#recurring-self-renewing-tasks-→" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p>The <code>runTask</code> + store-token + <code>cancelTask</code> pattern above is fine for a <strong>one-off</strong>
188
+ scheduled task. For anything <strong>recurring or self-renewing</strong> (watch/webhook
189
+ renewals, periodic polling, deferred cleanup), use <code>scheduleTask</code> instead — it
190
+ manages a <strong>singleton</strong> task per key, atomically replacing any pending task when
191
+ you re-schedule:</p>
192
+ <pre><code class="typescript"><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">renewal</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">callback</span><span class="hl-1">(</span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">renewWatch</span><span class="hl-1">, </span><span class="hl-2">resourceId</span><span class="hl-1">);</span><br/><span class="hl-7">// Re-scheduling under the same key cancels-and-replaces the pending task.</span><br/><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">scheduleTask</span><span class="hl-1">(</span><span class="hl-3">`watch-renewal:</span><span class="hl-4">${</span><span class="hl-2">resourceId</span><span class="hl-4">}</span><span class="hl-3">`</span><span class="hl-1">, </span><span class="hl-2">renewal</span><span class="hl-1">, { </span><span class="hl-2">runAt</span><span class="hl-1"> });</span><br/><br/><span class="hl-7">// Teardown:</span><br/><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">cancelScheduledTask</span><span class="hl-1">(</span><span class="hl-3">`watch-renewal:</span><span class="hl-4">${</span><span class="hl-2">resourceId</span><span class="hl-4">}</span><span class="hl-3">`</span><span class="hl-1">);</span>
193
+ </code><button type="button">Copy</button></pre>
194
+
195
+ <p><strong>Why it matters:</strong> a renewal that re-schedules itself is a self-sustaining
196
+ loop. Hand-managing the token (store it, cancel before re-scheduling) is
197
+ error-prone — forget the cancel, or let two setups race, and you leak parallel
198
+ chains that run forever and trip the runtime's execution quota. <code>scheduleTask</code>
199
+ keys the task so only one chain per key is ever live, with the dedup done
200
+ atomically on the server.</p>
187
201
  <h3 id="batch-processing-pattern" class="tsd-anchor-link">Batch Processing Pattern<a href="#batch-processing-pattern" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p>Use tasks to break long operations into chunks that stay under the ~1000 request limit per execution:</p>
188
202
  <pre><code class="typescript"><span class="hl-2">async</span><span class="hl-1"> </span><span class="hl-6">startSync</span><span class="hl-1">() {</span><br/><span class="hl-1"> </span><span class="hl-7">// Initialize state</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">set</span><span class="hl-1">(</span><span class="hl-3">&quot;sync_state&quot;</span><span class="hl-1">, {</span><br/><span class="hl-1"> </span><span class="hl-2">page:</span><span class="hl-1"> </span><span class="hl-14">1</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">hasMore:</span><span class="hl-1"> </span><span class="hl-4">true</span><br/><span class="hl-1"> });</span><br/><br/><span class="hl-1"> </span><span class="hl-7">// Start first batch</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">callback</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">callback</span><span class="hl-1">(</span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">syncBatch</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-7">// runTask creates NEW execution with fresh request limit</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">runTask</span><span class="hl-1">(</span><span class="hl-2">callback</span><span class="hl-1">);</span><br/><span class="hl-1">}</span><br/><br/><span class="hl-2">async</span><span class="hl-1"> </span><span class="hl-6">syncBatch</span><span class="hl-1">() {</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">state</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">get</span><span class="hl-1">&lt;{ </span><span class="hl-2">page</span><span class="hl-1">: </span><span class="hl-5">number</span><span class="hl-1">; </span><span class="hl-2">hasMore</span><span class="hl-1">: </span><span class="hl-5">boolean</span><span class="hl-1"> }&gt;(</span><span class="hl-3">&quot;sync_state&quot;</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-0">if</span><span class="hl-1"> (!</span><span class="hl-2">state</span><span class="hl-1"> || !</span><span class="hl-2">state</span><span class="hl-1">.</span><span class="hl-2">hasMore</span><span class="hl-1">) </span><span class="hl-0">return</span><span class="hl-1">;</span><br/><br/><span class="hl-1"> </span><span class="hl-7">// Process one page (sized to stay under request limit)</span><br/><span class="hl-1"> </span><span class="hl-7">// If each item makes ~10 requests, fetch ~100 items per page</span><br/><span class="hl-1"> </span><span class="hl-7">// 100 items × 10 requests = 1000 requests (at limit)</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">results</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">fetchPage</span><span class="hl-1">(</span><span class="hl-2">state</span><span class="hl-1">.</span><span class="hl-2">page</span><span class="hl-1">, </span><span class="hl-14">100</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">processResults</span><span class="hl-1">(</span><span class="hl-2">results</span><span class="hl-1">);</span><br/><br/><span class="hl-1"> </span><span class="hl-7">// Check if more work remains</span><br/><span class="hl-1"> </span><span class="hl-0">if</span><span class="hl-1"> (</span><span class="hl-2">results</span><span class="hl-1">.</span><span class="hl-2">hasMore</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">set</span><span class="hl-1">(</span><span class="hl-3">&quot;sync_state&quot;</span><span class="hl-1">, {</span><br/><span class="hl-1"> </span><span class="hl-2">page:</span><span class="hl-1"> </span><span class="hl-2">state</span><span class="hl-1">.</span><span class="hl-2">page</span><span class="hl-1"> + </span><span class="hl-14">1</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">hasMore:</span><span class="hl-1"> </span><span class="hl-4">true</span><br/><span class="hl-1"> });</span><br/><br/><span class="hl-1"> </span><span class="hl-7">// Queue next batch - creates NEW execution with fresh request limit</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">callback</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">callback</span><span class="hl-1">(</span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">syncBatch</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">runTask</span><span class="hl-1">(</span><span class="hl-2">callback</span><span class="hl-1">);</span><br/><span class="hl-1"> } </span><span class="hl-0">else</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">set</span><span class="hl-1">(</span><span class="hl-3">&quot;sync_state&quot;</span><span class="hl-1">, { </span><span class="hl-2">page:</span><span class="hl-1"> </span><span class="hl-2">state</span><span class="hl-1">.</span><span class="hl-2">page</span><span class="hl-1">, </span><span class="hl-2">hasMore:</span><span class="hl-1"> </span><span class="hl-4">false</span><span class="hl-1"> });</span><br/><span class="hl-1"> }</span><br/><span class="hl-1">}</span>
189
203
  </code><button type="button">Copy</button></pre>
@@ -342,4 +356,4 @@
342
356
  <li><strong><a href="Runtime_Environment.html">Runtime Environment</a></strong> - Understanding execution constraints</li>
343
357
  <li><strong>API Reference</strong> - Explore detailed API docs in the sidebar</li>
344
358
  </ul>
345
- </div></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div><details open class="tsd-accordion tsd-page-navigation"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>On This Page</h3></summary><div class="tsd-accordion-details"><a href="#built-in-tools"><span>Built-<wbr/>in <wbr/>Tools</span></a><ul><li><a href="#table-of-contents"><span>Table of <wbr/>Contents</span></a></li><li><a href="#plot"><span>Plot</span></a></li><li><ul><li><a href="#workspace-level-twists"><span>Workspace-<wbr/>Level <wbr/>Twists</span></a></li><li><a href="#understanding-threads-and-notes"><span>Understanding <wbr/>Threads and <wbr/>Notes</span></a></li><li><a href="#setup"><span>Setup</span></a></li><li><a href="#creating-threads"><span>Creating <wbr/>Threads</span></a></li><li><a href="#updating-threads"><span>Updating <wbr/>Threads</span></a></li><li><a href="#creating-and-managing-notes"><span>Creating and <wbr/>Managing <wbr/>Notes</span></a></li><li><ul><li><a href="#creating-notes-on-new-threads"><span>Creating <wbr/>Notes on <wbr/>New <wbr/>Threads</span></a></li><li><a href="#adding-notes-to-existing-threads"><span>Adding <wbr/>Notes to <wbr/>Existing <wbr/>Threads</span></a></li><li><a href="#pattern-conversations-and-message-threads"><span>Pattern: <wbr/>Conversations and <wbr/>Message <wbr/>Threads</span></a></li></ul></li><li><a href="#reading-threads-and-notes"><span>Reading <wbr/>Threads and <wbr/>Notes</span></a></li><li><a href="#managing-focuses"><span>Managing <wbr/>Focuses</span></a></li><li><a href="#schedules"><span>Schedules</span></a></li><li><a href="#contacts"><span>Contacts</span></a></li><li><a href="#links-from-connected-channels"><span>Links from <wbr/>Connected <wbr/>Channels</span></a></li><li><a href="#semantic-search"><span>Semantic <wbr/>Search</span></a></li><li><a href="#plans-user-approved-operations"><span>Plans (<wbr/>User-<wbr/>Approved <wbr/>Operations)</span></a></li><li><a href="#responding-to-mentions"><span>Responding to <wbr/>Mentions</span></a></li></ul></li><li><a href="#store"><span>Store</span></a></li><li><ul><li><a href="#setup-1"><span>Setup</span></a></li><li><a href="#storing-data"><span>Storing <wbr/>Data</span></a></li><li><a href="#retrieving-data"><span>Retrieving <wbr/>Data</span></a></li><li><a href="#clearing-data"><span>Clearing <wbr/>Data</span></a></li><li><a href="#listing-keys"><span>Listing <wbr/>Keys</span></a></li><li><a href="#locks"><span>Locks</span></a></li><li><a href="#best-practices"><span>Best <wbr/>Practices</span></a></li><li><ul><li><a href="#type-safety"><span>Type <wbr/>Safety</span></a></li><li><a href="#namespacing"><span>Namespacing</span></a></li><li><a href="#serialization-limits"><span>Serialization <wbr/>Limits</span></a></li></ul></li></ul></li><li><a href="#integrations"><span>Integrations</span></a></li><li><ul><li><a href="#setup-2"><span>Setup</span></a></li><li><a href="#auth-providers"><span>Auth <wbr/>Providers</span></a></li><li><a href="#using-auth-tokens"><span>Using <wbr/>Auth <wbr/>Tokens</span></a></li><li><a href="#saving-synced-data"><span>Saving <wbr/>Synced <wbr/>Data</span></a></li><li><a href="#auth-actions-in-twists"><span>Auth <wbr/>Actions in <wbr/>Twists</span></a></li></ul></li><li><a href="#tasks"><span>Tasks</span></a></li><li><ul><li><a href="#setup-3"><span>Setup</span></a></li><li><a href="#running-tasks-immediately"><span>Running <wbr/>Tasks <wbr/>Immediately</span></a></li><li><a href="#scheduling-tasks"><span>Scheduling <wbr/>Tasks</span></a></li><li><a href="#canceling-tasks"><span>Canceling <wbr/>Tasks</span></a></li><li><a href="#batch-processing-pattern"><span>Batch <wbr/>Processing <wbr/>Pattern</span></a></li></ul></li><li><a href="#network"><span>Network</span></a></li><li><ul><li><a href="#setup-4"><span>Setup</span></a></li><li><a href="#making-http-requests"><span>Making <wbr/>HTTP <wbr/>Requests</span></a></li><li><a href="#creating-webhooks"><span>Creating <wbr/>Webhooks</span></a></li><li><ul><li><a href="#delivery-mode"><span>Delivery <wbr/>Mode</span></a></li><li><a href="#provider-specific-webhooks"><span>Provider-<wbr/>Specific <wbr/>Webhooks</span></a></li></ul></li><li><a href="#deleting-webhooks"><span>Deleting <wbr/>Webhooks</span></a></li></ul></li><li><a href="#callbacks"><span>Callbacks</span></a></li><li><ul><li><a href="#setup-5"><span>Setup</span></a></li><li><a href="#creating-callbacks"><span>Creating <wbr/>Callbacks</span></a></li><li><a href="#executing-callbacks"><span>Executing <wbr/>Callbacks</span></a></li><li><a href="#method-signature"><span>Method <wbr/>Signature</span></a></li><li><a href="#callback-versioning-and-upgrades"><span>Callback <wbr/>Versioning and <wbr/>Upgrades</span></a></li><li><ul><li><a href="#handling-version-transitions"><span>Handling <wbr/>Version <wbr/>Transitions</span></a></li><li><a href="#affected-callback-types"><span>Affected <wbr/>Callback <wbr/>Types</span></a></li><li><a href="#migration-in-upgrade"><span>Migration in upgrade()</span></a></li></ul></li><li><a href="#deleting-callbacks"><span>Deleting <wbr/>Callbacks</span></a></li><li><a href="#use-cases"><span>Use <wbr/>Cases</span></a></li></ul></li><li><a href="#ai"><span>AI</span></a></li><li><ul><li><a href="#setup-6"><span>Setup</span></a></li><li><a href="#simple-text-generation"><span>Simple <wbr/>Text <wbr/>Generation</span></a></li><li><a href="#structured-output"><span>Structured <wbr/>Output</span></a></li><li><a href="#tool-calling"><span>Tool <wbr/>Calling</span></a></li><li><a href="#multi-turn-conversations"><span>Multi-<wbr/>turn <wbr/>Conversations</span></a></li><li><a href="#web-search"><span>Web <wbr/>Search</span></a></li><li><a href="#model-selection"><span>Model <wbr/>Selection</span></a></li><li><a href="#typebox-schemas"><span>Typebox <wbr/>Schemas</span></a></li><li><a href="#real-world-example-email-triage"><span>Real-<wbr/>World <wbr/>Example: <wbr/>Email <wbr/>Triage</span></a></li></ul></li><li><a href="#files"><span>Files</span></a></li><li><ul><li><a href="#setup-7"><span>Setup</span></a></li><li><a href="#reading-files"><span>Reading <wbr/>Files</span></a></li></ul></li><li><a href="#other-built-in-tools"><span>Other <wbr/>Built-<wbr/>in <wbr/>Tools</span></a></li><li><a href="#link-type-safety-pattern"><span>Link <wbr/>Type <wbr/>Safety <wbr/>Pattern</span></a></li><li><a href="#next-steps"><span>Next <wbr/>Steps</span></a></li></ul></div></details></div><div class="site-menu"><nav id="tsd-sidebar-links" class="tsd-navigation"><a href="https://plot.day" class="tsd-nav-link">Plot</a><a href="https://github.com/plotday/plot" class="tsd-nav-link">GitHub</a><a href="https://www.npmjs.com/package/@plotday/twister" class="tsd-nav-link">NPM</a></nav><nav class="tsd-navigation"><a href="../modules.html">Creating Plot Twists</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>
359
+ </div></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div><details open class="tsd-accordion tsd-page-navigation"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>On This Page</h3></summary><div class="tsd-accordion-details"><a href="#built-in-tools"><span>Built-<wbr/>in <wbr/>Tools</span></a><ul><li><a href="#table-of-contents"><span>Table of <wbr/>Contents</span></a></li><li><a href="#plot"><span>Plot</span></a></li><li><ul><li><a href="#workspace-level-twists"><span>Workspace-<wbr/>Level <wbr/>Twists</span></a></li><li><a href="#understanding-threads-and-notes"><span>Understanding <wbr/>Threads and <wbr/>Notes</span></a></li><li><a href="#setup"><span>Setup</span></a></li><li><a href="#creating-threads"><span>Creating <wbr/>Threads</span></a></li><li><a href="#updating-threads"><span>Updating <wbr/>Threads</span></a></li><li><a href="#creating-and-managing-notes"><span>Creating and <wbr/>Managing <wbr/>Notes</span></a></li><li><ul><li><a href="#creating-notes-on-new-threads"><span>Creating <wbr/>Notes on <wbr/>New <wbr/>Threads</span></a></li><li><a href="#adding-notes-to-existing-threads"><span>Adding <wbr/>Notes to <wbr/>Existing <wbr/>Threads</span></a></li><li><a href="#pattern-conversations-and-message-threads"><span>Pattern: <wbr/>Conversations and <wbr/>Message <wbr/>Threads</span></a></li></ul></li><li><a href="#reading-threads-and-notes"><span>Reading <wbr/>Threads and <wbr/>Notes</span></a></li><li><a href="#managing-focuses"><span>Managing <wbr/>Focuses</span></a></li><li><a href="#schedules"><span>Schedules</span></a></li><li><a href="#contacts"><span>Contacts</span></a></li><li><a href="#links-from-connected-channels"><span>Links from <wbr/>Connected <wbr/>Channels</span></a></li><li><a href="#semantic-search"><span>Semantic <wbr/>Search</span></a></li><li><a href="#plans-user-approved-operations"><span>Plans (<wbr/>User-<wbr/>Approved <wbr/>Operations)</span></a></li><li><a href="#responding-to-mentions"><span>Responding to <wbr/>Mentions</span></a></li></ul></li><li><a href="#store"><span>Store</span></a></li><li><ul><li><a href="#setup-1"><span>Setup</span></a></li><li><a href="#storing-data"><span>Storing <wbr/>Data</span></a></li><li><a href="#retrieving-data"><span>Retrieving <wbr/>Data</span></a></li><li><a href="#clearing-data"><span>Clearing <wbr/>Data</span></a></li><li><a href="#listing-keys"><span>Listing <wbr/>Keys</span></a></li><li><a href="#locks"><span>Locks</span></a></li><li><a href="#best-practices"><span>Best <wbr/>Practices</span></a></li><li><ul><li><a href="#type-safety"><span>Type <wbr/>Safety</span></a></li><li><a href="#namespacing"><span>Namespacing</span></a></li><li><a href="#serialization-limits"><span>Serialization <wbr/>Limits</span></a></li></ul></li></ul></li><li><a href="#integrations"><span>Integrations</span></a></li><li><ul><li><a href="#setup-2"><span>Setup</span></a></li><li><a href="#auth-providers"><span>Auth <wbr/>Providers</span></a></li><li><a href="#using-auth-tokens"><span>Using <wbr/>Auth <wbr/>Tokens</span></a></li><li><a href="#saving-synced-data"><span>Saving <wbr/>Synced <wbr/>Data</span></a></li><li><a href="#auth-actions-in-twists"><span>Auth <wbr/>Actions in <wbr/>Twists</span></a></li></ul></li><li><a href="#tasks"><span>Tasks</span></a></li><li><ul><li><a href="#setup-3"><span>Setup</span></a></li><li><a href="#running-tasks-immediately"><span>Running <wbr/>Tasks <wbr/>Immediately</span></a></li><li><a href="#scheduling-tasks"><span>Scheduling <wbr/>Tasks</span></a></li><li><a href="#canceling-tasks"><span>Canceling <wbr/>Tasks</span></a></li><li><a href="#recurring-self-renewing-tasks-→"><span>Recurring / self-<wbr/>renewing tasks → </span></a></li><li><a href="#batch-processing-pattern"><span>Batch <wbr/>Processing <wbr/>Pattern</span></a></li></ul></li><li><a href="#network"><span>Network</span></a></li><li><ul><li><a href="#setup-4"><span>Setup</span></a></li><li><a href="#making-http-requests"><span>Making <wbr/>HTTP <wbr/>Requests</span></a></li><li><a href="#creating-webhooks"><span>Creating <wbr/>Webhooks</span></a></li><li><ul><li><a href="#delivery-mode"><span>Delivery <wbr/>Mode</span></a></li><li><a href="#provider-specific-webhooks"><span>Provider-<wbr/>Specific <wbr/>Webhooks</span></a></li></ul></li><li><a href="#deleting-webhooks"><span>Deleting <wbr/>Webhooks</span></a></li></ul></li><li><a href="#callbacks"><span>Callbacks</span></a></li><li><ul><li><a href="#setup-5"><span>Setup</span></a></li><li><a href="#creating-callbacks"><span>Creating <wbr/>Callbacks</span></a></li><li><a href="#executing-callbacks"><span>Executing <wbr/>Callbacks</span></a></li><li><a href="#method-signature"><span>Method <wbr/>Signature</span></a></li><li><a href="#callback-versioning-and-upgrades"><span>Callback <wbr/>Versioning and <wbr/>Upgrades</span></a></li><li><ul><li><a href="#handling-version-transitions"><span>Handling <wbr/>Version <wbr/>Transitions</span></a></li><li><a href="#affected-callback-types"><span>Affected <wbr/>Callback <wbr/>Types</span></a></li><li><a href="#migration-in-upgrade"><span>Migration in upgrade()</span></a></li></ul></li><li><a href="#deleting-callbacks"><span>Deleting <wbr/>Callbacks</span></a></li><li><a href="#use-cases"><span>Use <wbr/>Cases</span></a></li></ul></li><li><a href="#ai"><span>AI</span></a></li><li><ul><li><a href="#setup-6"><span>Setup</span></a></li><li><a href="#simple-text-generation"><span>Simple <wbr/>Text <wbr/>Generation</span></a></li><li><a href="#structured-output"><span>Structured <wbr/>Output</span></a></li><li><a href="#tool-calling"><span>Tool <wbr/>Calling</span></a></li><li><a href="#multi-turn-conversations"><span>Multi-<wbr/>turn <wbr/>Conversations</span></a></li><li><a href="#web-search"><span>Web <wbr/>Search</span></a></li><li><a href="#model-selection"><span>Model <wbr/>Selection</span></a></li><li><a href="#typebox-schemas"><span>Typebox <wbr/>Schemas</span></a></li><li><a href="#real-world-example-email-triage"><span>Real-<wbr/>World <wbr/>Example: <wbr/>Email <wbr/>Triage</span></a></li></ul></li><li><a href="#files"><span>Files</span></a></li><li><ul><li><a href="#setup-7"><span>Setup</span></a></li><li><a href="#reading-files"><span>Reading <wbr/>Files</span></a></li></ul></li><li><a href="#other-built-in-tools"><span>Other <wbr/>Built-<wbr/>in <wbr/>Tools</span></a></li><li><a href="#link-type-safety-pattern"><span>Link <wbr/>Type <wbr/>Safety <wbr/>Pattern</span></a></li><li><a href="#next-steps"><span>Next <wbr/>Steps</span></a></li></ul></div></details></div><div class="site-menu"><nav id="tsd-sidebar-links" class="tsd-navigation"><a href="https://plot.day" class="tsd-nav-link">Plot</a><a href="https://github.com/plotday/plot" class="tsd-nav-link">GitHub</a><a href="https://www.npmjs.com/package/@plotday/twister" class="tsd-nav-link">NPM</a></nav><nav class="tsd-navigation"><a href="../modules.html">Creating Plot Twists</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>
@@ -44,13 +44,21 @@
44
44
  </ul>
45
45
  <p>Manual/operator suspensions (set directly in the database without a recorded version) are durable across deploys.</p>
46
46
  <h4 id="avoiding-auto-suspension" class="tsd-anchor-link">Avoiding auto-suspension<a href="#avoiding-auto-suspension" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h4><p>The most common cause of auto-suspension is a callback that re-queues itself with no exit condition:</p>
47
- <pre><code class="typescript"><span class="hl-7">// ❌ WRONG — unbounded self-chain. Each call queues another with no</span><br/><span class="hl-7">// completion check. Even with delays, this will exceed the burst</span><br/><span class="hl-7">// limit (200 / 5 min) in under a minute.</span><br/><span class="hl-2">async</span><span class="hl-1"> </span><span class="hl-6">reconcileComments</span><span class="hl-1">() {</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">processOne</span><span class="hl-1">();</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">callback</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">callback</span><span class="hl-1">(</span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">reconcileComments</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">runTask</span><span class="hl-1">(</span><span class="hl-2">callback</span><span class="hl-1">); </span><span class="hl-7">// recurses forever</span><br/><span class="hl-1">}</span><br/><br/><span class="hl-7">// ✅ CORRECT — explicit exit condition based on remaining work</span><br/><span class="hl-2">async</span><span class="hl-1"> </span><span class="hl-6">reconcileComments</span><span class="hl-1">() {</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">state</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">get</span><span class="hl-1">&lt;{ </span><span class="hl-2">cursor</span><span class="hl-1">: </span><span class="hl-5">string</span><span class="hl-1"> | </span><span class="hl-5">null</span><span class="hl-1"> }&gt;(</span><span class="hl-3">&quot;reconcile_state&quot;</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">result</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">processOne</span><span class="hl-1">(</span><span class="hl-2">state</span><span class="hl-1">?.</span><span class="hl-2">cursor</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-0">if</span><span class="hl-1"> (</span><span class="hl-2">result</span><span class="hl-1">.</span><span class="hl-2">hasMore</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">set</span><span class="hl-1">(</span><span class="hl-3">&quot;reconcile_state&quot;</span><span class="hl-1">, { </span><span class="hl-2">cursor:</span><span class="hl-1"> </span><span class="hl-2">result</span><span class="hl-1">.</span><span class="hl-2">nextCursor</span><span class="hl-1"> });</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">callback</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">callback</span><span class="hl-1">(</span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">reconcileComments</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">runTask</span><span class="hl-1">(</span><span class="hl-2">callback</span><span class="hl-1">);</span><br/><span class="hl-1"> } </span><span class="hl-0">else</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">set</span><span class="hl-1">(</span><span class="hl-3">&quot;reconcile_state&quot;</span><span class="hl-1">, { </span><span class="hl-2">cursor:</span><span class="hl-1"> </span><span class="hl-4">null</span><span class="hl-1"> });</span><br/><span class="hl-1"> }</span><br/><span class="hl-1">}</span><br/><br/><span class="hl-7">// ✅ CORRECT — periodic background work uses runAt, not a self-chain</span><br/><span class="hl-2">async</span><span class="hl-1"> </span><span class="hl-6">pollForChanges</span><span class="hl-1">() {</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">processBatch</span><span class="hl-1">();</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">callback</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">callback</span><span class="hl-1">(</span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">pollForChanges</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-7">// Schedule the next run 5 minutes from now. Cloudflare&#39;s queue stays</span><br/><span class="hl-1"> </span><span class="hl-7">// out of the loop entirely between runs.</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">runTask</span><span class="hl-1">(</span><span class="hl-2">callback</span><span class="hl-1">, {</span><br/><span class="hl-1"> </span><span class="hl-2">runAt:</span><span class="hl-1"> </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-6">Date</span><span class="hl-1">(</span><span class="hl-2">Date</span><span class="hl-1">.</span><span class="hl-6">now</span><span class="hl-1">() + </span><span class="hl-14">5</span><span class="hl-1"> * </span><span class="hl-14">60</span><span class="hl-1"> * </span><span class="hl-14">1000</span><span class="hl-1">),</span><br/><span class="hl-1"> });</span><br/><span class="hl-1">}</span>
47
+ <pre><code class="typescript"><span class="hl-7">// ❌ WRONG — unbounded self-chain. Each call queues another with no</span><br/><span class="hl-7">// completion check. Even with delays, this will exceed the burst</span><br/><span class="hl-7">// limit (200 / 5 min) in under a minute.</span><br/><span class="hl-2">async</span><span class="hl-1"> </span><span class="hl-6">reconcileComments</span><span class="hl-1">() {</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">processOne</span><span class="hl-1">();</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">callback</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">callback</span><span class="hl-1">(</span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">reconcileComments</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">runTask</span><span class="hl-1">(</span><span class="hl-2">callback</span><span class="hl-1">); </span><span class="hl-7">// recurses forever</span><br/><span class="hl-1">}</span><br/><br/><span class="hl-7">// ✅ CORRECT — explicit exit condition based on remaining work</span><br/><span class="hl-2">async</span><span class="hl-1"> </span><span class="hl-6">reconcileComments</span><span class="hl-1">() {</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">state</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">get</span><span class="hl-1">&lt;{ </span><span class="hl-2">cursor</span><span class="hl-1">: </span><span class="hl-5">string</span><span class="hl-1"> | </span><span class="hl-5">null</span><span class="hl-1"> }&gt;(</span><span class="hl-3">&quot;reconcile_state&quot;</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">result</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">processOne</span><span class="hl-1">(</span><span class="hl-2">state</span><span class="hl-1">?.</span><span class="hl-2">cursor</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-0">if</span><span class="hl-1"> (</span><span class="hl-2">result</span><span class="hl-1">.</span><span class="hl-2">hasMore</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">set</span><span class="hl-1">(</span><span class="hl-3">&quot;reconcile_state&quot;</span><span class="hl-1">, { </span><span class="hl-2">cursor:</span><span class="hl-1"> </span><span class="hl-2">result</span><span class="hl-1">.</span><span class="hl-2">nextCursor</span><span class="hl-1"> });</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">callback</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">callback</span><span class="hl-1">(</span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">reconcileComments</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">runTask</span><span class="hl-1">(</span><span class="hl-2">callback</span><span class="hl-1">);</span><br/><span class="hl-1"> } </span><span class="hl-0">else</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">set</span><span class="hl-1">(</span><span class="hl-3">&quot;reconcile_state&quot;</span><span class="hl-1">, { </span><span class="hl-2">cursor:</span><span class="hl-1"> </span><span class="hl-4">null</span><span class="hl-1"> });</span><br/><span class="hl-1"> }</span><br/><span class="hl-1">}</span><br/><br/><span class="hl-7">// ✅ CORRECT — periodic background work uses scheduleTask, not a self-chain</span><br/><span class="hl-2">async</span><span class="hl-1"> </span><span class="hl-6">pollForChanges</span><span class="hl-1">() {</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">processBatch</span><span class="hl-1">();</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">callback</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">callback</span><span class="hl-1">(</span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">pollForChanges</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-7">// Singleton: re-scheduling under the same key atomically replaces the</span><br/><span class="hl-1"> </span><span class="hl-7">// pending run, so the poll can never fork into parallel chains even if</span><br/><span class="hl-1"> </span><span class="hl-7">// pollForChanges is entered more than once. Cloudflare&#39;s queue stays out</span><br/><span class="hl-1"> </span><span class="hl-7">// of the loop entirely between runs.</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">scheduleTask</span><span class="hl-1">(</span><span class="hl-3">&quot;poll-for-changes&quot;</span><span class="hl-1">, </span><span class="hl-2">callback</span><span class="hl-1">, {</span><br/><span class="hl-1"> </span><span class="hl-2">runAt:</span><span class="hl-1"> </span><span class="hl-4">new</span><span class="hl-1"> </span><span class="hl-6">Date</span><span class="hl-1">(</span><span class="hl-2">Date</span><span class="hl-1">.</span><span class="hl-6">now</span><span class="hl-1">() + </span><span class="hl-14">5</span><span class="hl-1"> * </span><span class="hl-14">60</span><span class="hl-1"> * </span><span class="hl-14">1000</span><span class="hl-1">),</span><br/><span class="hl-1"> });</span><br/><span class="hl-1">}</span>
48
48
  </code><button type="button">Copy</button></pre>
49
49
 
50
+ <blockquote>
51
+ <p>⚠️ A self-rescheduling <code>runTask({ runAt })</code> (not keyed) is a hidden trap: if
52
+ the method is entered twice — a re-dispatched lifecycle hook, a re-init, two
53
+ racing triggers — you get <strong>two</strong> independent chains, then four, accumulating
54
+ forever and tripping the execution quota. <code>scheduleTask(key, …)</code> keys the task
55
+ so re-scheduling replaces rather than forks. This is the single most common
56
+ source of slow-burn auto-suspensions.</p>
57
+ </blockquote>
50
58
  <p><strong>Guidelines:</strong></p>
51
59
  <ul>
52
60
  <li>Every <code>runTask</code> self-chain must have an explicit exit condition (a cursor that ends, a counter that reaches a limit, a <code>hasMore</code> flag).</li>
53
- <li>For periodic &quot;keep checking&quot; patterns, use <code>runTask({ runAt })</code> instead of an immediate self-chain the queue stays free between runs.</li>
61
+ <li>For periodic/self-renewing work (polling, watch renewals), use <strong><code>scheduleTask(key, callback, { runAt })</code></strong> it guarantees a single live chain per key. Plain <code>runTask({ runAt })</code> forks if its method ever runs twice; <code>cancelScheduledTask(key)</code> tears it down.</li>
54
62
  <li>Cap recursion depth: store a counter in <code>this.set</code> and stop after a sane bound (e.g., 100 batches).</li>
55
63
  <li>For sync flows, paginate with <code>runTask</code> per page rather than fanning out hundreds of tasks at once.</li>
56
64
  </ul>