@plotday/twister 0.61.0 → 0.63.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 (68) hide show
  1. package/dist/connector.d.ts +14 -0
  2. package/dist/connector.d.ts.map +1 -1
  3. package/dist/connector.js +14 -0
  4. package/dist/connector.js.map +1 -1
  5. package/dist/docs/assets/hierarchy.js +1 -1
  6. package/dist/docs/assets/search.js +1 -1
  7. package/dist/docs/classes/index.Connector.html +47 -26
  8. package/dist/docs/classes/index.FileNotFoundError.html +1 -1
  9. package/dist/docs/classes/index.Files.html +1 -1
  10. package/dist/docs/classes/index.Imap.html +1 -1
  11. package/dist/docs/classes/index.Options.html +1 -1
  12. package/dist/docs/classes/index.Smtp.html +1 -1
  13. package/dist/docs/classes/tool.ITool.html +1 -1
  14. package/dist/docs/classes/tool.Tool.html +17 -7
  15. package/dist/docs/classes/tools_ai.AI.html +1 -1
  16. package/dist/docs/classes/tools_callbacks.Callbacks.html +1 -1
  17. package/dist/docs/classes/tools_integrations.Integrations.html +1 -1
  18. package/dist/docs/classes/tools_network.Network.html +1 -1
  19. package/dist/docs/classes/tools_plot.Plot.html +1 -1
  20. package/dist/docs/classes/tools_store.Store.html +1 -1
  21. package/dist/docs/classes/tools_tasks.Tasks.html +40 -14
  22. package/dist/docs/classes/tools_twists.Twists.html +1 -1
  23. package/dist/docs/classes/twist.Twist.html +21 -11
  24. package/dist/docs/documents/Built-in_Tools.html +15 -13
  25. package/dist/docs/documents/Runtime_Environment.html +7 -5
  26. package/dist/docs/hierarchy.html +1 -1
  27. package/dist/docs/media/AGENTS.md +23 -19
  28. package/dist/llm-docs/connector.d.ts +1 -1
  29. package/dist/llm-docs/connector.d.ts.map +1 -1
  30. package/dist/llm-docs/connector.js +1 -1
  31. package/dist/llm-docs/connector.js.map +1 -1
  32. package/dist/llm-docs/tool.d.ts +1 -1
  33. package/dist/llm-docs/tool.d.ts.map +1 -1
  34. package/dist/llm-docs/tool.js +1 -1
  35. package/dist/llm-docs/tool.js.map +1 -1
  36. package/dist/llm-docs/tools/tasks.d.ts +1 -1
  37. package/dist/llm-docs/tools/tasks.d.ts.map +1 -1
  38. package/dist/llm-docs/tools/tasks.js +1 -1
  39. package/dist/llm-docs/tools/tasks.js.map +1 -1
  40. package/dist/llm-docs/twist.d.ts +1 -1
  41. package/dist/llm-docs/twist.d.ts.map +1 -1
  42. package/dist/llm-docs/twist.js +1 -1
  43. package/dist/llm-docs/twist.js.map +1 -1
  44. package/dist/tool.d.ts +16 -0
  45. package/dist/tool.d.ts.map +1 -1
  46. package/dist/tool.js +15 -0
  47. package/dist/tool.js.map +1 -1
  48. package/dist/tools/tasks.d.ts +58 -12
  49. package/dist/tools/tasks.d.ts.map +1 -1
  50. package/dist/tools/tasks.js.map +1 -1
  51. package/dist/twist.d.ts +16 -0
  52. package/dist/twist.d.ts.map +1 -1
  53. package/dist/twist.js +15 -0
  54. package/dist/twist.js.map +1 -1
  55. package/dist/utils/markdown-html.d.ts +15 -0
  56. package/dist/utils/markdown-html.d.ts.map +1 -0
  57. package/dist/utils/markdown-html.js +35 -0
  58. package/dist/utils/markdown-html.js.map +1 -0
  59. package/package.json +7 -1
  60. package/src/connector.ts +15 -0
  61. package/src/llm-docs/connector.ts +1 -1
  62. package/src/llm-docs/tool.ts +1 -1
  63. package/src/llm-docs/tools/tasks.ts +1 -1
  64. package/src/llm-docs/twist.ts +1 -1
  65. package/src/tool.ts +20 -0
  66. package/src/tools/tasks.ts +61 -12
  67. package/src/twist.ts +20 -0
  68. package/src/utils/markdown-html.ts +40 -0
@@ -25,6 +25,7 @@ handle events.</p>
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
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
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>
28
+ <a href="#schedulerecurring" 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/>Recurring</span></a>
28
29
  <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>
29
30
  <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>
30
31
  <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>
@@ -133,33 +134,42 @@ parallel task chains. See Tasks.scheduleTask.</p>
133
134
  No-op if none exists or it already ran. See Tasks.cancelScheduledTask.</p>
134
135
  </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
136
  </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>
137
+ <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 tsd-is-protected"><h3 class="tsd-anchor-link" id="schedulerecurring"><code class="tsd-tag">Protected</code><span>schedule<wbr/>Recurring</span><a href="#schedulerecurring" 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="schedulerecurring-1"><span class="tsd-kind-call-signature">scheduleRecurring</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">intervalMs</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">;</span> <span class="tsd-kind-property">firstRunAt</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">void</span><span class="tsd-signature-symbol">&gt;</span><a href="#schedulerecurring-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 durable recurring task under a stable key. The platform
138
+ re-arms the task every <code>intervalMs</code> automatically — the callback does NOT
139
+ need to reschedule itself. Re-scheduling under the same key atomically
140
+ replaces the pending occurrence (at most one live task per key). Tear down
141
+ with <a href="#cancelscheduledtask" class="tsd-kind-method">cancelScheduledTask</a>. See Tasks.scheduleRecurring.</p>
142
+ </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, e.g. <code>&quot;mailbox-self-heal&quot;</code></p>
143
+ </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>Callback token created with <code>this.callback()</code></p>
144
+ </div></li><li><span><span class="tsd-kind-parameter">options</span>: <span class="tsd-signature-symbol">{</span> <span class="tsd-kind-property">intervalMs</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">;</span> <span class="tsd-kind-property">firstRunAt</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">intervalMs</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span></h5><div class="tsd-comment tsd-typography"><p>Safety-ceiling cadence in milliseconds</p>
145
+ </div></li><li class="tsd-parameter"><h5><code class="tsd-tag">Optional</code><span class="tsd-kind-property">firstRunAt</span><span class="tsd-signature-symbol">?: </span><span class="tsd-signature-type">Date</span></h5><div class="tsd-comment tsd-typography"><p>Optional precise time for the next fire</p>
146
+ </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">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#L342">twist.ts:342</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>
137
147
  <p>This method should contain initialization logic such as seeding
138
148
  initial threads, configuring webhooks, or establishing external
139
149
  connections. When it runs, <code>this.userId</code> is already populated with
140
150
  the installing user's ID.</p>
141
151
  </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>
142
152
  </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>
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>
153
+ <aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twister/twister/src/twist.ts#L362">twist.ts:362</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>
144
154
  <p>This method should contain migration logic for updating old data structures
145
155
  or setting up new resources that weren't needed by the previous version.
146
156
  It is called once per active twist_instance with the new version.</p>
147
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 upgrade is complete</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>
158
+ <aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twister/twister/src/twist.ts#L375">twist.ts:375</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>
149
159
  <p>Override to react to option changes, e.g. archiving items when a sync
150
160
  type is toggled off, or starting sync when a type is toggled on.</p>
151
161
  </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>
152
162
  </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>
153
163
  </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>
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>
164
+ <aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twister/twister/src/twist.ts#L390">twist.ts:390</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>
155
165
  <p>This method should contain cleanup logic such as removing webhooks,
156
166
  cleaning up external resources, or performing final data operations.</p>
157
167
  </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>
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.
168
+ <aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twister/twister/src/twist.ts#L405">twist.ts:405</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.
159
169
  Override to implement two-way sync with an external system.</p>
160
170
  </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>
161
171
  </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>
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.
172
+ </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#L417">twist.ts:417</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.
163
173
  Override to implement two-way sync (e.g. syncing notes as comments).</p>
164
174
  <p>Notes created by the twist itself are filtered out to prevent loops.</p>
165
175
  <p>Returning a string sets the note's <code>key</code> for future upsert matching,
@@ -167,19 +177,19 @@ linking the Plot note to its external counterpart so that subsequent
167
177
  syncs (reactions, edits) update the existing note instead of creating duplicates.</p>
168
178
  </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>
169
179
  </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>
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.
180
+ <aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/plotday/plot/blob/main/twister/twister/src/twist.ts#L441">twist.ts:441</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.
171
181
  Requires <code>link: true</code> in Plot options.</p>
172
182
  </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>
173
183
  </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>
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.
184
+ </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#L453">twist.ts:453</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.
175
185
  Requires <code>link: true</code> in Plot options.</p>
176
186
  </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>
177
187
  </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>
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.
188
+ </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#L465">twist.ts:465</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.
179
189
  Requires <code>link: true</code> in Plot options.</p>
180
190
  </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>
181
191
  </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>
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
192
+ </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#L477">twist.ts:477</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
183
193
  the same scope (personal workspace or team). Each instance must have a
184
194
  distinct name.</p>
185
195
  <p>Defaults to <code>false</code> (single instance per scope).</p>
@@ -188,4 +198,4 @@ distinct name.</p>
188
198
 
189
199
  </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.
190
200
  Populated by the runtime before any lifecycle method runs.</p>
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>
201
+ </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="#schedulerecurring" 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/>Recurring</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,20 +184,22 @@
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>
187
+ <h3 id="recurring-self-renewing-tasks-→" class="tsd-anchor-link">Recurring / self-renewing tasks → <code>scheduleRecurring</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
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>
189
+ renewals, periodic polling, daily syncs, self-heal loops), use <code>scheduleRecurring</code>
190
+ instead — it manages a <strong>durable singleton</strong> per key that the platform re-arms
191
+ automatically every <code>intervalMs</code>:</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">// The platform fires this every intervalMs. firstRunAt sets a precise earlier</span><br/><span class="hl-7">// next fire (e.g. renew 24 h before expiry rather than waiting the full interval).</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">scheduleRecurring</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><br/><span class="hl-1"> </span><span class="hl-2">intervalMs:</span><span class="hl-1"> </span><span class="hl-14">24</span><span class="hl-1"> * </span><span class="hl-14">60</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><span class="hl-7">// safety ceiling: re-arm every 24 h</span><br/><span class="hl-1"> </span><span class="hl-2">firstRunAt:</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">expiresAt</span><span class="hl-1">.</span><span class="hl-6">getTime</span><span class="hl-1">() - </span><span class="hl-14">24</span><span class="hl-1"> * </span><span class="hl-14">60</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/><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> <code>scheduleRecurring</code> survives dropped queue messages, worker
196
+ restarts, and deploys — the platform re-arms the chain even if a callback throws
197
+ before it can reschedule itself. The callback does <strong>not</strong> need to call
198
+ <code>scheduleRecurring</code> again on each run; the platform owns the cadence. To tighten
199
+ timing (e.g. re-arm at expiry-minus-24h rather than waiting the full ceiling),
200
+ re-calling under the same key is fine and atomic — it replaces the pending run
201
+ without forking. Use <code>scheduleTask(key, cb, { runAt })</code> only for <strong>one-shot</strong>
202
+ keyed deferred work (a single future task, atomically replaced if re-keyed).</p>
201
203
  <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>
202
204
  <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>
203
205
  </code><button type="button">Copy</button></pre>
@@ -44,21 +44,23 @@
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 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>
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 scheduleRecurring, 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">// scheduleRecurring re-arms automatically every intervalMs the platform</span><br/><span class="hl-1"> </span><span class="hl-7">// owns the cadence, so this callback does NOT need to reschedule itself.</span><br/><span class="hl-1"> </span><span class="hl-7">// The chain survives dropped messages, deploys, and thrown exceptions.</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">scheduleRecurring</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">intervalMs:</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
50
  <blockquote>
51
51
  <p>⚠️ A self-rescheduling <code>runTask({ runAt })</code> (not keyed) is a hidden trap: if
52
52
  the method is entered twice — a re-dispatched lifecycle hook, a re-init, two
53
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>
54
+ forever and tripping the execution quota. <code>scheduleRecurring(key, …)</code> keys the
55
+ recurring run so re-registering replaces rather than forks, and the platform
56
+ re-arms it even if a run is dropped. This is the single most common source of
57
+ slow-burn auto-suspensions.</p>
57
58
  </blockquote>
58
59
  <p><strong>Guidelines:</strong></p>
59
60
  <ul>
60
61
  <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>
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>
62
+ <li>For periodic/self-renewing work (polling, watch renewals), use <strong><code>scheduleRecurring(key, callback, { intervalMs, firstRunAt? })</code></strong> — the platform re-arms the chain every <code>intervalMs</code> and it survives drops/deploys. Use <code>firstRunAt</code> to fire earlier than the ceiling (e.g. renew 24 h before expiry). Teardown: <code>cancelScheduledTask(key)</code>.</li>
63
+ <li>Use <code>scheduleTask(key, callback, { runAt })</code> only for <strong>one-shot</strong> keyed deferred work. Plain <code>runTask({ runAt })</code> forks if its method ever runs twice.</li>
62
64
  <li>Cap recursion depth: store a counter in <code>this.set</code> and stop after a sane bound (e.g., 100 batches).</li>
63
65
  <li>For sync flows, paginate with <code>runTask</code> per page rather than fanning out hundreds of tasks at once.</li>
64
66
  </ul>