@plotday/twister 0.27.0 → 0.28.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 (94) hide show
  1. package/README.md +10 -4
  2. package/bin/templates/AGENTS.template.md +91 -29
  3. package/cli/templates/AGENTS.template.md +91 -29
  4. package/dist/common/calendar.d.ts +18 -21
  5. package/dist/common/calendar.d.ts.map +1 -1
  6. package/dist/common/messaging.d.ts +14 -5
  7. package/dist/common/messaging.d.ts.map +1 -1
  8. package/dist/common/projects.d.ts +20 -10
  9. package/dist/common/projects.d.ts.map +1 -1
  10. package/dist/docs/assets/hierarchy.js +1 -1
  11. package/dist/docs/assets/search.js +1 -1
  12. package/dist/docs/classes/tool.Tool.html +20 -15
  13. package/dist/docs/classes/tools_ai.AI.html +1 -1
  14. package/dist/docs/classes/tools_callbacks.Callbacks.html +1 -1
  15. package/dist/docs/classes/tools_integrations.Integrations.html +1 -1
  16. package/dist/docs/classes/tools_network.Network.html +1 -1
  17. package/dist/docs/classes/tools_plot.Plot.html +2 -2
  18. package/dist/docs/classes/tools_store.Store.html +13 -4
  19. package/dist/docs/classes/tools_tasks.Tasks.html +1 -1
  20. package/dist/docs/classes/tools_twists.Twists.html +1 -1
  21. package/dist/docs/documents/Building_Custom_Tools.html +8 -2
  22. package/dist/docs/documents/Built-in_Tools.html +19 -8
  23. package/dist/docs/documents/Core_Concepts.html +14 -6
  24. package/dist/docs/documents/Getting_Started.html +11 -4
  25. package/dist/docs/enums/plot.ActorType.html +4 -4
  26. package/dist/docs/enums/tools_plot.ContactAccess.html +1 -1
  27. package/dist/docs/hierarchy.html +1 -1
  28. package/dist/docs/index.html +10 -0
  29. package/dist/docs/interfaces/common_calendar.CalendarTool.html +19 -11
  30. package/dist/docs/media/SYNC_STRATEGIES.md +651 -0
  31. package/dist/docs/types/plot.Activity.html +16 -7
  32. package/dist/docs/types/plot.ActivityCommon.html +4 -4
  33. package/dist/docs/types/plot.ActivityUpdate.html +4 -2
  34. package/dist/docs/types/plot.ActivityWithNotes.html +1 -1
  35. package/dist/docs/types/plot.Actor.html +5 -5
  36. package/dist/docs/types/plot.ContentType.html +1 -1
  37. package/dist/docs/types/plot.NewActivity.html +26 -12
  38. package/dist/docs/types/plot.NewActivityWithNotes.html +1 -1
  39. package/dist/docs/types/plot.NewActor.html +1 -1
  40. package/dist/docs/types/plot.NewContact.html +4 -4
  41. package/dist/docs/types/plot.NewNote.html +9 -4
  42. package/dist/docs/types/plot.Note.html +6 -3
  43. package/dist/docs/types/plot.NoteUpdate.html +4 -3
  44. package/dist/docs/types/plot.PickPriorityConfig.html +2 -2
  45. package/dist/docs/types/plot.SyncUpdate.html +1 -1
  46. package/dist/llm-docs/common/calendar.d.ts +1 -1
  47. package/dist/llm-docs/common/calendar.d.ts.map +1 -1
  48. package/dist/llm-docs/common/calendar.js +1 -1
  49. package/dist/llm-docs/common/calendar.js.map +1 -1
  50. package/dist/llm-docs/common/messaging.d.ts +1 -1
  51. package/dist/llm-docs/common/messaging.d.ts.map +1 -1
  52. package/dist/llm-docs/common/messaging.js +1 -1
  53. package/dist/llm-docs/common/messaging.js.map +1 -1
  54. package/dist/llm-docs/common/projects.d.ts +1 -1
  55. package/dist/llm-docs/common/projects.d.ts.map +1 -1
  56. package/dist/llm-docs/common/projects.js +1 -1
  57. package/dist/llm-docs/common/projects.js.map +1 -1
  58. package/dist/llm-docs/plot.d.ts +1 -1
  59. package/dist/llm-docs/plot.d.ts.map +1 -1
  60. package/dist/llm-docs/plot.js +1 -1
  61. package/dist/llm-docs/plot.js.map +1 -1
  62. package/dist/llm-docs/tool.d.ts +1 -1
  63. package/dist/llm-docs/tool.d.ts.map +1 -1
  64. package/dist/llm-docs/tool.js +1 -1
  65. package/dist/llm-docs/tool.js.map +1 -1
  66. package/dist/llm-docs/tools/plot.d.ts +1 -1
  67. package/dist/llm-docs/tools/plot.d.ts.map +1 -1
  68. package/dist/llm-docs/tools/plot.js +1 -1
  69. package/dist/llm-docs/tools/plot.js.map +1 -1
  70. package/dist/llm-docs/tools/store.d.ts +1 -1
  71. package/dist/llm-docs/tools/store.d.ts.map +1 -1
  72. package/dist/llm-docs/tools/store.js +1 -1
  73. package/dist/llm-docs/tools/store.js.map +1 -1
  74. package/dist/llm-docs/twist-guide-template.d.ts +1 -1
  75. package/dist/llm-docs/twist-guide-template.d.ts.map +1 -1
  76. package/dist/llm-docs/twist-guide-template.js +1 -1
  77. package/dist/llm-docs/twist-guide-template.js.map +1 -1
  78. package/dist/plot.d.ts +109 -44
  79. package/dist/plot.d.ts.map +1 -1
  80. package/dist/plot.js.map +1 -1
  81. package/dist/tool.d.ts +16 -2
  82. package/dist/tool.d.ts.map +1 -1
  83. package/dist/tool.js +16 -2
  84. package/dist/tool.js.map +1 -1
  85. package/dist/tools/plot.d.ts +2 -2
  86. package/dist/tools/plot.d.ts.map +1 -1
  87. package/dist/tools/plot.js +1 -1
  88. package/dist/tools/plot.js.map +1 -1
  89. package/dist/tools/store.d.ts +16 -0
  90. package/dist/tools/store.d.ts.map +1 -1
  91. package/dist/tools/store.js.map +1 -1
  92. package/dist/twist-guide.d.ts +1 -1
  93. package/dist/twist-guide.d.ts.map +1 -1
  94. package/package.json +1 -1
@@ -130,7 +130,7 @@
130
130
 
131
131
  <hr>
132
132
  <h2 id="complete-examples" class="tsd-anchor-link">Complete Examples<a href="#complete-examples" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><h3 id="example-1-github-integration-tool" class="tsd-anchor-link">Example 1: GitHub Integration Tool<a href="#example-1-github-integration-tool" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p>A complete GitHub integration with webhooks and issue management.</p>
133
- <pre><code class="typescript"><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-0">type</span><span class="hl-1"> </span><span class="hl-2">Priority</span><span class="hl-1">, </span><span class="hl-2">Tool</span><span class="hl-1">, </span><span class="hl-0">type</span><span class="hl-1"> </span><span class="hl-2">ToolBuilder</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&quot;@plotday/twister&quot;</span><span class="hl-1">;</span><br/><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">ActivityLinkType</span><span class="hl-1">, </span><span class="hl-2">ActivityType</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&quot;@plotday/twister&quot;</span><span class="hl-1">;</span><br/><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">Network</span><span class="hl-1">, </span><span class="hl-0">type</span><span class="hl-1"> </span><span class="hl-2">WebhookRequest</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&quot;@plotday/twister/tools/network&quot;</span><span class="hl-1">;</span><br/><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">Plot</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&quot;@plotday/twister/tools/plot&quot;</span><span class="hl-1">;</span><br/><br/><span class="hl-0">export</span><span class="hl-1"> </span><span class="hl-4">class</span><span class="hl-1"> </span><span class="hl-5">GitHubTool</span><span class="hl-1"> </span><span class="hl-4">extends</span><span class="hl-1"> </span><span class="hl-5">Tool</span><span class="hl-1">&lt;</span><span class="hl-5">GitHubTool</span><span class="hl-1">&gt; {</span><br/><span class="hl-1"> </span><span class="hl-4">static</span><span class="hl-1"> </span><span class="hl-2">Options</span><span class="hl-1"> = {</span><br/><span class="hl-1"> </span><span class="hl-2">owner:</span><span class="hl-1"> </span><span class="hl-3">&quot;&quot;</span><span class="hl-1"> </span><span class="hl-0">as</span><span class="hl-1"> </span><span class="hl-5">string</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">repo:</span><span class="hl-1"> </span><span class="hl-3">&quot;&quot;</span><span class="hl-1"> </span><span class="hl-0">as</span><span class="hl-1"> </span><span class="hl-5">string</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">token:</span><span class="hl-1"> </span><span class="hl-3">&quot;&quot;</span><span class="hl-1"> </span><span class="hl-0">as</span><span class="hl-1"> </span><span class="hl-5">string</span><span class="hl-1">,</span><br/><span class="hl-1"> };</span><br/><br/><span class="hl-1"> </span><span class="hl-6">build</span><span class="hl-1">(</span><span class="hl-2">build</span><span class="hl-1">: </span><span class="hl-5">ToolBuilder</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-0">return</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">network:</span><span class="hl-1"> </span><span class="hl-6">build</span><span class="hl-1">(</span><span class="hl-2">Network</span><span class="hl-1">, {</span><br/><span class="hl-1"> </span><span class="hl-2">urls:</span><span class="hl-1"> [</span><span class="hl-3">&quot;https://api.github.com/*&quot;</span><span class="hl-1">],</span><br/><span class="hl-1"> }),</span><br/><span class="hl-1"> </span><span class="hl-2">plot:</span><span class="hl-1"> </span><span class="hl-6">build</span><span class="hl-1">(</span><span class="hl-2">Plot</span><span class="hl-1">),</span><br/><span class="hl-1"> };</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">postActivate</span><span class="hl-1">(</span><span class="hl-2">priority</span><span class="hl-1">: </span><span class="hl-5">Priority</span><span class="hl-1">): </span><span class="hl-5">Promise</span><span class="hl-1">&lt;</span><span class="hl-5">void</span><span class="hl-1">&gt; {</span><br/><span class="hl-1"> </span><span class="hl-7">// Set up webhook for issue updates</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">webhookUrl</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">tools</span><span class="hl-1">.</span><span class="hl-2">network</span><span class="hl-1">.</span><span class="hl-6">createWebhook</span><span class="hl-1">(</span><span class="hl-3">&quot;onIssueUpdate&quot;</span><span class="hl-1">, {</span><br/><span class="hl-1"> </span><span class="hl-2">priorityId:</span><span class="hl-1"> </span><span class="hl-2">priority</span><span class="hl-1">.</span><span class="hl-2">id</span><span class="hl-1">,</span><br/><span class="hl-1"> });</span><br/><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;webhook_url&quot;</span><span class="hl-1">, </span><span class="hl-2">webhookUrl</span><span class="hl-1">);</span><br/><br/><span class="hl-1"> </span><span class="hl-7">// Register webhook with GitHub</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">registerWebhook</span><span class="hl-1">(</span><span class="hl-2">webhookUrl</span><span class="hl-1">);</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">preDeactivate</span><span class="hl-1">(): </span><span class="hl-5">Promise</span><span class="hl-1">&lt;</span><span class="hl-5">void</span><span class="hl-1">&gt; {</span><br/><span class="hl-1"> </span><span class="hl-7">// Cleanup webhook</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">webhookUrl</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-5">string</span><span class="hl-1">&gt;(</span><span class="hl-3">&quot;webhook_url&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">webhookUrl</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">unregisterWebhook</span><span class="hl-1">(</span><span class="hl-2">webhookUrl</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">tools</span><span class="hl-1">.</span><span class="hl-2">network</span><span class="hl-1">.</span><span class="hl-6">deleteWebhook</span><span class="hl-1">(</span><span class="hl-2">webhookUrl</span><span class="hl-1">);</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">getIssues</span><span class="hl-1">(): </span><span class="hl-5">Promise</span><span class="hl-1">&lt;</span><span class="hl-5">any</span><span class="hl-1">[]&gt; {</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">response</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-6">fetch</span><span class="hl-1">(</span><br/><span class="hl-1"> </span><span class="hl-3">`https://api.github.com/repos/</span><span class="hl-4">${</span><span class="hl-4">this</span><span class="hl-13">.</span><span class="hl-2">options</span><span class="hl-13">.</span><span class="hl-2">owner</span><span class="hl-4">}</span><span class="hl-3">/</span><span class="hl-4">${</span><span class="hl-4">this</span><span class="hl-13">.</span><span class="hl-2">options</span><span class="hl-13">.</span><span class="hl-2">repo</span><span class="hl-4">}</span><span class="hl-3">/issues`</span><span class="hl-1">,</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">headers:</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">Authorization:</span><span class="hl-1"> </span><span class="hl-3">`Bearer </span><span class="hl-4">${</span><span class="hl-4">this</span><span class="hl-13">.</span><span class="hl-2">options</span><span class="hl-13">.</span><span class="hl-2">token</span><span class="hl-4">}</span><span class="hl-3">`</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">Accept:</span><span class="hl-1"> </span><span class="hl-3">&quot;application/vnd.github.v3+json&quot;</span><span class="hl-1">,</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> );</span><br/><br/><span class="hl-1"> </span><span class="hl-0">return</span><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-2">response</span><span class="hl-1">.</span><span class="hl-6">json</span><span class="hl-1">();</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">syncIssues</span><span class="hl-1">(): </span><span class="hl-5">Promise</span><span class="hl-1">&lt;</span><span class="hl-5">void</span><span class="hl-1">&gt; {</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">issues</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">getIssues</span><span class="hl-1">();</span><br/><br/><span class="hl-1"> </span><span class="hl-0">for</span><span class="hl-1"> (</span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">issue</span><span class="hl-1"> </span><span class="hl-4">of</span><span class="hl-1"> </span><span class="hl-2">issues</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">tools</span><span class="hl-1">.</span><span class="hl-2">plot</span><span class="hl-1">.</span><span class="hl-6">createActivity</span><span class="hl-1">({</span><br/><span class="hl-1"> </span><span class="hl-2">type:</span><span class="hl-1"> </span><span class="hl-2">ActivityType</span><span class="hl-1">.</span><span class="hl-2">Action</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">title:</span><span class="hl-1"> </span><span class="hl-2">issue</span><span class="hl-1">.</span><span class="hl-2">title</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">meta:</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">github_issue_id:</span><span class="hl-1"> </span><span class="hl-2">issue</span><span class="hl-1">.</span><span class="hl-2">id</span><span class="hl-1">.</span><span class="hl-6">toString</span><span class="hl-1">(),</span><br/><span class="hl-1"> </span><span class="hl-2">github_number:</span><span class="hl-1"> </span><span class="hl-2">issue</span><span class="hl-1">.</span><span class="hl-2">number</span><span class="hl-1">.</span><span class="hl-6">toString</span><span class="hl-1">(),</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> </span><span class="hl-2">notes:</span><span class="hl-1"> [</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">note:</span><span class="hl-1"> </span><span class="hl-2">issue</span><span class="hl-1">.</span><span class="hl-2">body</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">links:</span><span class="hl-1"> [</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">type:</span><span class="hl-1"> </span><span class="hl-2">ActivityLinkType</span><span class="hl-1">.</span><span class="hl-2">external</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">title:</span><span class="hl-1"> </span><span class="hl-3">&quot;View on GitHub&quot;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">url:</span><span class="hl-1"> </span><span class="hl-2">issue</span><span class="hl-1">.</span><span class="hl-2">html_url</span><span class="hl-1">,</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> ],</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> ],</span><br/><span class="hl-1"> });</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">onIssueUpdate</span><span class="hl-1">(</span><br/><span class="hl-1"> </span><span class="hl-2">request</span><span class="hl-1">: </span><span class="hl-5">WebhookRequest</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">context</span><span class="hl-1">: { </span><span class="hl-2">priorityId</span><span class="hl-1">: </span><span class="hl-5">string</span><span class="hl-1"> }</span><br/><span class="hl-1"> ): </span><span class="hl-5">Promise</span><span class="hl-1">&lt;</span><span class="hl-5">void</span><span class="hl-1">&gt; {</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> { </span><span class="hl-8">action</span><span class="hl-1">, </span><span class="hl-8">issue</span><span class="hl-1">, </span><span class="hl-8">comment</span><span class="hl-1"> } = </span><span class="hl-2">request</span><span class="hl-1">.</span><span class="hl-2">body</span><span class="hl-1">;</span><br/><br/><span class="hl-1"> </span><span class="hl-0">if</span><span class="hl-1"> (</span><span class="hl-2">action</span><span class="hl-1"> === </span><span class="hl-3">&quot;opened&quot;</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-7">// Create new activity for new issue with initial Note</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">tools</span><span class="hl-1">.</span><span class="hl-2">plot</span><span class="hl-1">.</span><span class="hl-6">createActivity</span><span class="hl-1">({</span><br/><span class="hl-1"> </span><span class="hl-2">type:</span><span class="hl-1"> </span><span class="hl-2">ActivityType</span><span class="hl-1">.</span><span class="hl-2">Action</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">title:</span><span class="hl-1"> </span><span class="hl-2">issue</span><span class="hl-1">.</span><span class="hl-2">title</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">meta:</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">github_issue_id:</span><span class="hl-1"> </span><span class="hl-2">issue</span><span class="hl-1">.</span><span class="hl-2">id</span><span class="hl-1">.</span><span class="hl-6">toString</span><span class="hl-1">(),</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> </span><span class="hl-2">notes:</span><span class="hl-1"> [</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">note:</span><span class="hl-1"> </span><span class="hl-2">issue</span><span class="hl-1">.</span><span class="hl-2">body</span><span class="hl-1"> || </span><span class="hl-3">&quot;No description provided&quot;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">links:</span><span class="hl-1"> [</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">type:</span><span class="hl-1"> </span><span class="hl-2">ActivityLinkType</span><span class="hl-1">.</span><span class="hl-2">external</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">title:</span><span class="hl-1"> </span><span class="hl-3">&quot;View on GitHub&quot;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">url:</span><span class="hl-1"> </span><span class="hl-2">issue</span><span class="hl-1">.</span><span class="hl-2">html_url</span><span class="hl-1">,</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> ],</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> ],</span><br/><span class="hl-1"> });</span><br/><span class="hl-1"> } </span><span class="hl-0">else</span><span class="hl-1"> </span><span class="hl-0">if</span><span class="hl-1"> (</span><span class="hl-2">action</span><span class="hl-1"> === </span><span class="hl-3">&quot;created&quot;</span><span class="hl-1"> &amp;&amp; </span><span class="hl-2">comment</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-7">// Add comment as Note to existing Activity</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">activity</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">tools</span><span class="hl-1">.</span><span class="hl-2">plot</span><span class="hl-1">.</span><span class="hl-6">getActivityBySource</span><span class="hl-1">({</span><br/><span class="hl-1"> </span><span class="hl-2">github_issue_id:</span><span class="hl-1"> </span><span class="hl-2">issue</span><span class="hl-1">.</span><span class="hl-2">id</span><span class="hl-1">.</span><span class="hl-6">toString</span><span class="hl-1">(),</span><br/><span class="hl-1"> });</span><br/><br/><span class="hl-1"> </span><span class="hl-0">if</span><span class="hl-1"> (</span><span class="hl-2">activity</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">tools</span><span class="hl-1">.</span><span class="hl-2">plot</span><span class="hl-1">.</span><span class="hl-6">createNote</span><span class="hl-1">({</span><br/><span class="hl-1"> </span><span class="hl-2">activity:</span><span class="hl-1"> { </span><span class="hl-2">id:</span><span class="hl-1"> </span><span class="hl-2">activity</span><span class="hl-1">.</span><span class="hl-2">id</span><span class="hl-1"> },</span><br/><span class="hl-1"> </span><span class="hl-2">note:</span><span class="hl-1"> </span><span class="hl-2">comment</span><span class="hl-1">.</span><span class="hl-2">body</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-7">// author could be set if you have user mapping</span><br/><span class="hl-1"> });</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> } </span><span class="hl-0">else</span><span class="hl-1"> </span><span class="hl-0">if</span><span class="hl-1"> (</span><span class="hl-2">action</span><span class="hl-1"> === </span><span class="hl-3">&quot;closed&quot;</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-7">// Mark activity as done</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">activity</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">tools</span><span class="hl-1">.</span><span class="hl-2">plot</span><span class="hl-1">.</span><span class="hl-6">getActivityBySource</span><span class="hl-1">({</span><br/><span class="hl-1"> </span><span class="hl-2">github_issue_id:</span><span class="hl-1"> </span><span class="hl-2">issue</span><span class="hl-1">.</span><span class="hl-2">id</span><span class="hl-1">.</span><span class="hl-6">toString</span><span class="hl-1">(),</span><br/><span class="hl-1"> });</span><br/><br/><span class="hl-1"> </span><span class="hl-0">if</span><span class="hl-1"> (</span><span class="hl-2">activity</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">tools</span><span class="hl-1">.</span><span class="hl-2">plot</span><span class="hl-1">.</span><span class="hl-6">updateActivity</span><span class="hl-1">(</span><span class="hl-2">activity</span><span class="hl-1">.</span><span class="hl-2">id</span><span class="hl-1">, {</span><br/><span class="hl-1"> </span><span class="hl-2">doneAt:</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><br/><span class="hl-1"> });</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-4">private</span><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">registerWebhook</span><span class="hl-1">(</span><span class="hl-2">url</span><span class="hl-1">: </span><span class="hl-5">string</span><span class="hl-1">): </span><span class="hl-5">Promise</span><span class="hl-1">&lt;</span><span class="hl-5">void</span><span class="hl-1">&gt; {</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-6">fetch</span><span class="hl-1">(</span><br/><span class="hl-1"> </span><span class="hl-3">`https://api.github.com/repos/</span><span class="hl-4">${</span><span class="hl-4">this</span><span class="hl-13">.</span><span class="hl-2">options</span><span class="hl-13">.</span><span class="hl-2">owner</span><span class="hl-4">}</span><span class="hl-3">/</span><span class="hl-4">${</span><span class="hl-4">this</span><span class="hl-13">.</span><span class="hl-2">options</span><span class="hl-13">.</span><span class="hl-2">repo</span><span class="hl-4">}</span><span class="hl-3">/hooks`</span><span class="hl-1">,</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">method:</span><span class="hl-1"> </span><span class="hl-3">&quot;POST&quot;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">headers:</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">Authorization:</span><span class="hl-1"> </span><span class="hl-3">`Bearer </span><span class="hl-4">${</span><span class="hl-4">this</span><span class="hl-13">.</span><span class="hl-2">options</span><span class="hl-13">.</span><span class="hl-2">token</span><span class="hl-4">}</span><span class="hl-3">`</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">Accept:</span><span class="hl-1"> </span><span class="hl-3">&quot;application/vnd.github.v3+json&quot;</span><span class="hl-1">,</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> </span><span class="hl-2">body:</span><span class="hl-1"> </span><span class="hl-8">JSON</span><span class="hl-1">.</span><span class="hl-6">stringify</span><span class="hl-1">({</span><br/><span class="hl-1"> </span><span class="hl-2">config:</span><span class="hl-1"> { </span><span class="hl-2">url</span><span class="hl-1">, </span><span class="hl-2">content_type:</span><span class="hl-1"> </span><span class="hl-3">&quot;json&quot;</span><span class="hl-1"> },</span><br/><span class="hl-1"> </span><span class="hl-2">events:</span><span class="hl-1"> [</span><span class="hl-3">&quot;issues&quot;</span><span class="hl-1">],</span><br/><span class="hl-1"> }),</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> );</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-4">private</span><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">unregisterWebhook</span><span class="hl-1">(</span><span class="hl-2">url</span><span class="hl-1">: </span><span class="hl-5">string</span><span class="hl-1">): </span><span class="hl-5">Promise</span><span class="hl-1">&lt;</span><span class="hl-5">void</span><span class="hl-1">&gt; {</span><br/><span class="hl-1"> </span><span class="hl-7">// Implementation to remove webhook from GitHub</span><br/><span class="hl-1"> }</span><br/><span class="hl-1">}</span>
133
+ <pre><code class="typescript"><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-0">type</span><span class="hl-1"> </span><span class="hl-2">Priority</span><span class="hl-1">, </span><span class="hl-2">Tool</span><span class="hl-1">, </span><span class="hl-0">type</span><span class="hl-1"> </span><span class="hl-2">ToolBuilder</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&quot;@plotday/twister&quot;</span><span class="hl-1">;</span><br/><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">ActivityLinkType</span><span class="hl-1">, </span><span class="hl-2">ActivityType</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&quot;@plotday/twister&quot;</span><span class="hl-1">;</span><br/><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">Network</span><span class="hl-1">, </span><span class="hl-0">type</span><span class="hl-1"> </span><span class="hl-2">WebhookRequest</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&quot;@plotday/twister/tools/network&quot;</span><span class="hl-1">;</span><br/><span class="hl-0">import</span><span class="hl-1"> { </span><span class="hl-2">Plot</span><span class="hl-1"> } </span><span class="hl-0">from</span><span class="hl-1"> </span><span class="hl-3">&quot;@plotday/twister/tools/plot&quot;</span><span class="hl-1">;</span><br/><br/><span class="hl-0">export</span><span class="hl-1"> </span><span class="hl-4">class</span><span class="hl-1"> </span><span class="hl-5">GitHubTool</span><span class="hl-1"> </span><span class="hl-4">extends</span><span class="hl-1"> </span><span class="hl-5">Tool</span><span class="hl-1">&lt;</span><span class="hl-5">GitHubTool</span><span class="hl-1">&gt; {</span><br/><span class="hl-1"> </span><span class="hl-4">static</span><span class="hl-1"> </span><span class="hl-2">Options</span><span class="hl-1"> = {</span><br/><span class="hl-1"> </span><span class="hl-2">owner:</span><span class="hl-1"> </span><span class="hl-3">&quot;&quot;</span><span class="hl-1"> </span><span class="hl-0">as</span><span class="hl-1"> </span><span class="hl-5">string</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">repo:</span><span class="hl-1"> </span><span class="hl-3">&quot;&quot;</span><span class="hl-1"> </span><span class="hl-0">as</span><span class="hl-1"> </span><span class="hl-5">string</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">token:</span><span class="hl-1"> </span><span class="hl-3">&quot;&quot;</span><span class="hl-1"> </span><span class="hl-0">as</span><span class="hl-1"> </span><span class="hl-5">string</span><span class="hl-1">,</span><br/><span class="hl-1"> };</span><br/><br/><span class="hl-1"> </span><span class="hl-6">build</span><span class="hl-1">(</span><span class="hl-2">build</span><span class="hl-1">: </span><span class="hl-5">ToolBuilder</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-0">return</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">network:</span><span class="hl-1"> </span><span class="hl-6">build</span><span class="hl-1">(</span><span class="hl-2">Network</span><span class="hl-1">, {</span><br/><span class="hl-1"> </span><span class="hl-2">urls:</span><span class="hl-1"> [</span><span class="hl-3">&quot;https://api.github.com/*&quot;</span><span class="hl-1">],</span><br/><span class="hl-1"> }),</span><br/><span class="hl-1"> </span><span class="hl-2">plot:</span><span class="hl-1"> </span><span class="hl-6">build</span><span class="hl-1">(</span><span class="hl-2">Plot</span><span class="hl-1">),</span><br/><span class="hl-1"> };</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">postActivate</span><span class="hl-1">(</span><span class="hl-2">priority</span><span class="hl-1">: </span><span class="hl-5">Priority</span><span class="hl-1">): </span><span class="hl-5">Promise</span><span class="hl-1">&lt;</span><span class="hl-5">void</span><span class="hl-1">&gt; {</span><br/><span class="hl-1"> </span><span class="hl-7">// Set up webhook for issue updates</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">webhookUrl</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">tools</span><span class="hl-1">.</span><span class="hl-2">network</span><span class="hl-1">.</span><span class="hl-6">createWebhook</span><span class="hl-1">(</span><span class="hl-3">&quot;onIssueUpdate&quot;</span><span class="hl-1">, {</span><br/><span class="hl-1"> </span><span class="hl-2">priorityId:</span><span class="hl-1"> </span><span class="hl-2">priority</span><span class="hl-1">.</span><span class="hl-2">id</span><span class="hl-1">,</span><br/><span class="hl-1"> });</span><br/><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;webhook_url&quot;</span><span class="hl-1">, </span><span class="hl-2">webhookUrl</span><span class="hl-1">);</span><br/><br/><span class="hl-1"> </span><span class="hl-7">// Register webhook with GitHub</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">registerWebhook</span><span class="hl-1">(</span><span class="hl-2">webhookUrl</span><span class="hl-1">);</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">preDeactivate</span><span class="hl-1">(): </span><span class="hl-5">Promise</span><span class="hl-1">&lt;</span><span class="hl-5">void</span><span class="hl-1">&gt; {</span><br/><span class="hl-1"> </span><span class="hl-7">// Cleanup webhook</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">webhookUrl</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-5">string</span><span class="hl-1">&gt;(</span><span class="hl-3">&quot;webhook_url&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">webhookUrl</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">unregisterWebhook</span><span class="hl-1">(</span><span class="hl-2">webhookUrl</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">tools</span><span class="hl-1">.</span><span class="hl-2">network</span><span class="hl-1">.</span><span class="hl-6">deleteWebhook</span><span class="hl-1">(</span><span class="hl-2">webhookUrl</span><span class="hl-1">);</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">getIssues</span><span class="hl-1">(): </span><span class="hl-5">Promise</span><span class="hl-1">&lt;</span><span class="hl-5">any</span><span class="hl-1">[]&gt; {</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">response</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-6">fetch</span><span class="hl-1">(</span><br/><span class="hl-1"> </span><span class="hl-3">`https://api.github.com/repos/</span><span class="hl-4">${</span><span class="hl-4">this</span><span class="hl-13">.</span><span class="hl-2">options</span><span class="hl-13">.</span><span class="hl-2">owner</span><span class="hl-4">}</span><span class="hl-3">/</span><span class="hl-4">${</span><span class="hl-4">this</span><span class="hl-13">.</span><span class="hl-2">options</span><span class="hl-13">.</span><span class="hl-2">repo</span><span class="hl-4">}</span><span class="hl-3">/issues`</span><span class="hl-1">,</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">headers:</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">Authorization:</span><span class="hl-1"> </span><span class="hl-3">`Bearer </span><span class="hl-4">${</span><span class="hl-4">this</span><span class="hl-13">.</span><span class="hl-2">options</span><span class="hl-13">.</span><span class="hl-2">token</span><span class="hl-4">}</span><span class="hl-3">`</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">Accept:</span><span class="hl-1"> </span><span class="hl-3">&quot;application/vnd.github.v3+json&quot;</span><span class="hl-1">,</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> );</span><br/><br/><span class="hl-1"> </span><span class="hl-0">return</span><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-2">response</span><span class="hl-1">.</span><span class="hl-6">json</span><span class="hl-1">();</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">syncIssues</span><span class="hl-1">(): </span><span class="hl-5">Promise</span><span class="hl-1">&lt;</span><span class="hl-5">void</span><span class="hl-1">&gt; {</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">issues</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">getIssues</span><span class="hl-1">();</span><br/><br/><span class="hl-1"> </span><span class="hl-0">for</span><span class="hl-1"> (</span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">issue</span><span class="hl-1"> </span><span class="hl-4">of</span><span class="hl-1"> </span><span class="hl-2">issues</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-7">// Use source for automatic deduplication - no manual ID tracking needed</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">tools</span><span class="hl-1">.</span><span class="hl-2">plot</span><span class="hl-1">.</span><span class="hl-6">createActivity</span><span class="hl-1">({</span><br/><span class="hl-1"> </span><span class="hl-2">source:</span><span class="hl-1"> </span><span class="hl-2">issue</span><span class="hl-1">.</span><span class="hl-2">html_url</span><span class="hl-1">, </span><span class="hl-7">// Enables automatic upserts</span><br/><span class="hl-1"> </span><span class="hl-2">type:</span><span class="hl-1"> </span><span class="hl-2">ActivityType</span><span class="hl-1">.</span><span class="hl-2">Action</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">title:</span><span class="hl-1"> </span><span class="hl-2">issue</span><span class="hl-1">.</span><span class="hl-2">title</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">meta:</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">github_issue_id:</span><span class="hl-1"> </span><span class="hl-2">issue</span><span class="hl-1">.</span><span class="hl-2">id</span><span class="hl-1">.</span><span class="hl-6">toString</span><span class="hl-1">(),</span><br/><span class="hl-1"> </span><span class="hl-2">github_number:</span><span class="hl-1"> </span><span class="hl-2">issue</span><span class="hl-1">.</span><span class="hl-2">number</span><span class="hl-1">.</span><span class="hl-6">toString</span><span class="hl-1">(),</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> </span><span class="hl-2">notes:</span><span class="hl-1"> [</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">activity:</span><span class="hl-1"> { </span><span class="hl-2">source:</span><span class="hl-1"> </span><span class="hl-2">issue</span><span class="hl-1">.</span><span class="hl-2">html_url</span><span class="hl-1"> },</span><br/><span class="hl-1"> </span><span class="hl-2">key:</span><span class="hl-1"> </span><span class="hl-3">&quot;description&quot;</span><span class="hl-1">, </span><span class="hl-7">// Using key enables upserts</span><br/><span class="hl-1"> </span><span class="hl-2">content:</span><span class="hl-1"> </span><span class="hl-2">issue</span><span class="hl-1">.</span><span class="hl-2">body</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">links:</span><span class="hl-1"> [</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">type:</span><span class="hl-1"> </span><span class="hl-2">ActivityLinkType</span><span class="hl-1">.</span><span class="hl-2">external</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">title:</span><span class="hl-1"> </span><span class="hl-3">&quot;View on GitHub&quot;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">url:</span><span class="hl-1"> </span><span class="hl-2">issue</span><span class="hl-1">.</span><span class="hl-2">html_url</span><span class="hl-1">,</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> ],</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> ],</span><br/><span class="hl-1"> });</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-7">// Note: For advanced sync patterns (batching, pagination, etc.),</span><br/><span class="hl-1"> </span><span class="hl-7">// see the Sync Strategies guide: https://twist.plot.day/documents/Sync_Strategies.html</span><br/><br/><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">onIssueUpdate</span><span class="hl-1">(</span><br/><span class="hl-1"> </span><span class="hl-2">request</span><span class="hl-1">: </span><span class="hl-5">WebhookRequest</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">context</span><span class="hl-1">: { </span><span class="hl-2">priorityId</span><span class="hl-1">: </span><span class="hl-5">string</span><span class="hl-1"> }</span><br/><span class="hl-1"> ): </span><span class="hl-5">Promise</span><span class="hl-1">&lt;</span><span class="hl-5">void</span><span class="hl-1">&gt; {</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> { </span><span class="hl-8">action</span><span class="hl-1">, </span><span class="hl-8">issue</span><span class="hl-1">, </span><span class="hl-8">comment</span><span class="hl-1"> } = </span><span class="hl-2">request</span><span class="hl-1">.</span><span class="hl-2">body</span><span class="hl-1">;</span><br/><br/><span class="hl-1"> </span><span class="hl-0">if</span><span class="hl-1"> (</span><span class="hl-2">action</span><span class="hl-1"> === </span><span class="hl-3">&quot;opened&quot;</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-7">// Create new activity for new issue with initial Note</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">tools</span><span class="hl-1">.</span><span class="hl-2">plot</span><span class="hl-1">.</span><span class="hl-6">createActivity</span><span class="hl-1">({</span><br/><span class="hl-1"> </span><span class="hl-2">type:</span><span class="hl-1"> </span><span class="hl-2">ActivityType</span><span class="hl-1">.</span><span class="hl-2">Action</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">title:</span><span class="hl-1"> </span><span class="hl-2">issue</span><span class="hl-1">.</span><span class="hl-2">title</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">meta:</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">github_issue_id:</span><span class="hl-1"> </span><span class="hl-2">issue</span><span class="hl-1">.</span><span class="hl-2">id</span><span class="hl-1">.</span><span class="hl-6">toString</span><span class="hl-1">(),</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> </span><span class="hl-2">notes:</span><span class="hl-1"> [</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">note:</span><span class="hl-1"> </span><span class="hl-2">issue</span><span class="hl-1">.</span><span class="hl-2">body</span><span class="hl-1"> || </span><span class="hl-3">&quot;No description provided&quot;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">links:</span><span class="hl-1"> [</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">type:</span><span class="hl-1"> </span><span class="hl-2">ActivityLinkType</span><span class="hl-1">.</span><span class="hl-2">external</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">title:</span><span class="hl-1"> </span><span class="hl-3">&quot;View on GitHub&quot;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">url:</span><span class="hl-1"> </span><span class="hl-2">issue</span><span class="hl-1">.</span><span class="hl-2">html_url</span><span class="hl-1">,</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> ],</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> ],</span><br/><span class="hl-1"> });</span><br/><span class="hl-1"> } </span><span class="hl-0">else</span><span class="hl-1"> </span><span class="hl-0">if</span><span class="hl-1"> (</span><span class="hl-2">action</span><span class="hl-1"> === </span><span class="hl-3">&quot;created&quot;</span><span class="hl-1"> &amp;&amp; </span><span class="hl-2">comment</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-7">// Add comment as Note to existing Activity</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">activity</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">tools</span><span class="hl-1">.</span><span class="hl-2">plot</span><span class="hl-1">.</span><span class="hl-6">getActivityBySource</span><span class="hl-1">({</span><br/><span class="hl-1"> </span><span class="hl-2">github_issue_id:</span><span class="hl-1"> </span><span class="hl-2">issue</span><span class="hl-1">.</span><span class="hl-2">id</span><span class="hl-1">.</span><span class="hl-6">toString</span><span class="hl-1">(),</span><br/><span class="hl-1"> });</span><br/><br/><span class="hl-1"> </span><span class="hl-0">if</span><span class="hl-1"> (</span><span class="hl-2">activity</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">tools</span><span class="hl-1">.</span><span class="hl-2">plot</span><span class="hl-1">.</span><span class="hl-6">createNote</span><span class="hl-1">({</span><br/><span class="hl-1"> </span><span class="hl-2">activity:</span><span class="hl-1"> { </span><span class="hl-2">id:</span><span class="hl-1"> </span><span class="hl-2">activity</span><span class="hl-1">.</span><span class="hl-2">id</span><span class="hl-1"> },</span><br/><span class="hl-1"> </span><span class="hl-2">note:</span><span class="hl-1"> </span><span class="hl-2">comment</span><span class="hl-1">.</span><span class="hl-2">body</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-7">// author could be set if you have user mapping</span><br/><span class="hl-1"> });</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> } </span><span class="hl-0">else</span><span class="hl-1"> </span><span class="hl-0">if</span><span class="hl-1"> (</span><span class="hl-2">action</span><span class="hl-1"> === </span><span class="hl-3">&quot;closed&quot;</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-7">// Mark activity as done</span><br/><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-8">activity</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">tools</span><span class="hl-1">.</span><span class="hl-2">plot</span><span class="hl-1">.</span><span class="hl-6">getActivityBySource</span><span class="hl-1">({</span><br/><span class="hl-1"> </span><span class="hl-2">github_issue_id:</span><span class="hl-1"> </span><span class="hl-2">issue</span><span class="hl-1">.</span><span class="hl-2">id</span><span class="hl-1">.</span><span class="hl-6">toString</span><span class="hl-1">(),</span><br/><span class="hl-1"> });</span><br/><br/><span class="hl-1"> </span><span class="hl-0">if</span><span class="hl-1"> (</span><span class="hl-2">activity</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">tools</span><span class="hl-1">.</span><span class="hl-2">plot</span><span class="hl-1">.</span><span class="hl-6">updateActivity</span><span class="hl-1">(</span><span class="hl-2">activity</span><span class="hl-1">.</span><span class="hl-2">id</span><span class="hl-1">, {</span><br/><span class="hl-1"> </span><span class="hl-2">done:</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><br/><span class="hl-1"> });</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-4">private</span><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">registerWebhook</span><span class="hl-1">(</span><span class="hl-2">url</span><span class="hl-1">: </span><span class="hl-5">string</span><span class="hl-1">): </span><span class="hl-5">Promise</span><span class="hl-1">&lt;</span><span class="hl-5">void</span><span class="hl-1">&gt; {</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-6">fetch</span><span class="hl-1">(</span><br/><span class="hl-1"> </span><span class="hl-3">`https://api.github.com/repos/</span><span class="hl-4">${</span><span class="hl-4">this</span><span class="hl-13">.</span><span class="hl-2">options</span><span class="hl-13">.</span><span class="hl-2">owner</span><span class="hl-4">}</span><span class="hl-3">/</span><span class="hl-4">${</span><span class="hl-4">this</span><span class="hl-13">.</span><span class="hl-2">options</span><span class="hl-13">.</span><span class="hl-2">repo</span><span class="hl-4">}</span><span class="hl-3">/hooks`</span><span class="hl-1">,</span><br/><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">method:</span><span class="hl-1"> </span><span class="hl-3">&quot;POST&quot;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">headers:</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-2">Authorization:</span><span class="hl-1"> </span><span class="hl-3">`Bearer </span><span class="hl-4">${</span><span class="hl-4">this</span><span class="hl-13">.</span><span class="hl-2">options</span><span class="hl-13">.</span><span class="hl-2">token</span><span class="hl-4">}</span><span class="hl-3">`</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">Accept:</span><span class="hl-1"> </span><span class="hl-3">&quot;application/vnd.github.v3+json&quot;</span><span class="hl-1">,</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> </span><span class="hl-2">body:</span><span class="hl-1"> </span><span class="hl-8">JSON</span><span class="hl-1">.</span><span class="hl-6">stringify</span><span class="hl-1">({</span><br/><span class="hl-1"> </span><span class="hl-2">config:</span><span class="hl-1"> { </span><span class="hl-2">url</span><span class="hl-1">, </span><span class="hl-2">content_type:</span><span class="hl-1"> </span><span class="hl-3">&quot;json&quot;</span><span class="hl-1"> },</span><br/><span class="hl-1"> </span><span class="hl-2">events:</span><span class="hl-1"> [</span><span class="hl-3">&quot;issues&quot;</span><span class="hl-1">],</span><br/><span class="hl-1"> }),</span><br/><span class="hl-1"> }</span><br/><span class="hl-1"> );</span><br/><span class="hl-1"> }</span><br/><br/><span class="hl-1"> </span><span class="hl-4">private</span><span class="hl-1"> </span><span class="hl-4">async</span><span class="hl-1"> </span><span class="hl-6">unregisterWebhook</span><span class="hl-1">(</span><span class="hl-2">url</span><span class="hl-1">: </span><span class="hl-5">string</span><span class="hl-1">): </span><span class="hl-5">Promise</span><span class="hl-1">&lt;</span><span class="hl-5">void</span><span class="hl-1">&gt; {</span><br/><span class="hl-1"> </span><span class="hl-7">// Implementation to remove webhook from GitHub</span><br/><span class="hl-1"> }</span><br/><span class="hl-1">}</span>
134
134
  </code><button type="button">Copy</button></pre>
135
135
 
136
136
  <h3 id="example-2-slack-notification-tool" class="tsd-anchor-link">Example 2: Slack Notification Tool<a href="#example-2-slack-notification-tool" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h3><p>A tool for sending Slack notifications.</p>
@@ -191,9 +191,15 @@
191
191
  <pre><code class="typescript"><span class="hl-7">/**</span><br/><span class="hl-7"> * Fetches all open issues from the GitHub repository.</span><br/><span class="hl-7"> *</span><br/><span class="hl-7"> * </span><span class="hl-4">@returns</span><span class="hl-7"> Promise resolving to array of GitHub issues</span><br/><span class="hl-7"> * </span><span class="hl-4">@throws</span><span class="hl-7"> Error if GitHub API is unavailable</span><br/><span class="hl-7"> *</span><br/><span class="hl-7"> * </span><span class="hl-4">@example</span><br/><span class="hl-7"> * ```typescript</span><br/><span class="hl-7"> * const issues = await this.tools.github.getIssues();</span><br/><span class="hl-7"> * ```</span><br/><span class="hl-7"> */</span><br/><span class="hl-2">async</span><span class="hl-1"> </span><span class="hl-6">getIssues</span><span class="hl-1">(): </span><span class="hl-5">Promise</span><span class="hl-1">&lt;</span><span class="hl-2">GitHubIssue</span><span class="hl-1">[]&gt; {</span><br/><span class="hl-1"> </span><span class="hl-7">// Implementation</span><br/><span class="hl-1">}</span>
192
192
  </code><button type="button">Copy</button></pre>
193
193
 
194
+ <h3 id="8-data-synchronization" class="tsd-anchor-link">8. Data Synchronization<a href="#8-data-synchronization" 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>When building tools that sync from external systems, use the recommended patterns for deduplication and updates:</p>
195
+ <p><strong>Recommended:</strong> Use <code>Activity.source</code> and <code>Note.key</code> for automatic upserts:</p>
196
+ <pre><code class="typescript"><span class="hl-7">// ✅ GOOD - Automatic deduplication via source</span><br/><span class="hl-2">async</span><span class="hl-1"> </span><span class="hl-6">syncItems</span><span class="hl-1">(</span><span class="hl-2">items</span><span class="hl-1">: </span><span class="hl-2">ExternalItem</span><span class="hl-1">[]): </span><span class="hl-5">Promise</span><span class="hl-1">&lt;</span><span class="hl-4">void</span><span class="hl-1">&gt; {</span><br/><span class="hl-1"> </span><span class="hl-6">for</span><span class="hl-1"> (</span><span class="hl-2">const</span><span class="hl-1"> </span><span class="hl-2">item</span><span class="hl-1"> </span><span class="hl-2">of</span><span class="hl-1"> </span><span class="hl-2">items</span><span class="hl-1">) {</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">tools</span><span class="hl-1">.</span><span class="hl-2">plot</span><span class="hl-1">.</span><span class="hl-6">createActivity</span><span class="hl-1">({</span><br/><span class="hl-1"> </span><span class="hl-2">source:</span><span class="hl-1"> </span><span class="hl-2">item</span><span class="hl-1">.</span><span class="hl-2">url</span><span class="hl-1">, </span><span class="hl-7">// Canonical URL for deduplication</span><br/><span class="hl-1"> </span><span class="hl-2">type:</span><span class="hl-1"> </span><span class="hl-2">ActivityType</span><span class="hl-1">.</span><span class="hl-2">Action</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">title:</span><span class="hl-1"> </span><span class="hl-2">item</span><span class="hl-1">.</span><span class="hl-2">title</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">notes:</span><span class="hl-1"> [{</span><br/><span class="hl-1"> </span><span class="hl-2">activity:</span><span class="hl-1"> { </span><span class="hl-2">source:</span><span class="hl-1"> </span><span class="hl-2">item</span><span class="hl-1">.</span><span class="hl-2">url</span><span class="hl-1"> },</span><br/><span class="hl-1"> </span><span class="hl-2">key:</span><span class="hl-1"> </span><span class="hl-3">&quot;description&quot;</span><span class="hl-1">, </span><span class="hl-7">// Enables note upserts</span><br/><span class="hl-1"> </span><span class="hl-2">content:</span><span class="hl-1"> </span><span class="hl-2">item</span><span class="hl-1">.</span><span class="hl-2">description</span><span class="hl-1">,</span><br/><span class="hl-1"> }],</span><br/><span class="hl-1"> });</span><br/><span class="hl-1"> }</span><br/><span class="hl-1">}</span><br/><br/><span class="hl-7">// ❌ BAD - Manual ID tracking (only use for advanced cases)</span><br/><span class="hl-2">async</span><span class="hl-1"> </span><span class="hl-6">syncItemsManual</span><span class="hl-1">(</span><span class="hl-2">items</span><span class="hl-1">: </span><span class="hl-2">ExternalItem</span><span class="hl-1">[]): </span><span class="hl-5">Promise</span><span class="hl-1">&lt;</span><span class="hl-4">void</span><span class="hl-1">&gt; {</span><br/><span class="hl-1"> </span><span class="hl-6">for</span><span class="hl-1"> (</span><span class="hl-2">const</span><span class="hl-1"> </span><span class="hl-2">item</span><span class="hl-1"> </span><span class="hl-2">of</span><span class="hl-1"> </span><span class="hl-2">items</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">activityId</span><span class="hl-1"> = </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-6">get</span><span class="hl-1">(</span><span class="hl-3">`item:</span><span class="hl-4">${</span><span class="hl-2">item</span><span class="hl-13">.</span><span class="hl-2">id</span><span class="hl-4">}</span><span class="hl-3">`</span><span class="hl-1">) || </span><span class="hl-2">Uuid</span><span class="hl-1">.</span><span class="hl-6">Generate</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">`item:</span><span class="hl-4">${</span><span class="hl-2">item</span><span class="hl-13">.</span><span class="hl-2">id</span><span class="hl-4">}</span><span class="hl-3">`</span><span class="hl-1">, </span><span class="hl-2">activityId</span><span class="hl-1">);</span><br/><span class="hl-1"> </span><span class="hl-0">await</span><span class="hl-1"> </span><span class="hl-4">this</span><span class="hl-1">.</span><span class="hl-2">tools</span><span class="hl-1">.</span><span class="hl-2">plot</span><span class="hl-1">.</span><span class="hl-6">createActivity</span><span class="hl-1">({</span><br/><span class="hl-1"> </span><span class="hl-2">id:</span><span class="hl-1"> </span><span class="hl-2">activityId</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-7">// ... missing automatic deduplication</span><br/><span class="hl-1"> });</span><br/><span class="hl-1"> }</span><br/><span class="hl-1">}</span>
197
+ </code><button type="button">Copy</button></pre>
198
+
199
+ <p>For comprehensive guidance on choosing the right sync strategy (upserts, batching, pagination, tag management, etc.), see the <strong><a href="../media/SYNC_STRATEGIES.md">Sync Strategies Guide</a></strong>.</p>
194
200
  <hr>
195
201
  <h2 id="next-steps" class="tsd-anchor-link">Next Steps<a href="#next-steps" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></h2><ul>
196
202
  <li><strong><a href="Built-in_Tools.html">Built-in Tools Guide</a></strong> - Learn from built-in tool patterns</li>
197
203
  <li><strong>API Reference</strong> - Explore the Tool class API</li>
198
204
  </ul>
199
- </div></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div><details open class="tsd-accordion tsd-page-navigation"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>On This Page</h3></summary><div class="tsd-accordion-details"><a href="#building-custom-tools"><span>Building <wbr/>Custom <wbr/>Tools</span></a><ul><li><a href="#table-of-contents"><span>Table of <wbr/>Contents</span></a></li><li><a href="#why-build-tools"><span>Why <wbr/>Build <wbr/>Tools?</span></a></li><li><ul><li><a href="#built-in-vs-custom-tools"><span>Built-<wbr/>in vs. <wbr/>Custom <wbr/>Tools</span></a></li></ul></li><li><a href="#tool-basics"><span>Tool <wbr/>Basics</span></a></li><li><ul><li><a href="#minimal-tool-example"><span>Minimal <wbr/>Tool <wbr/>Example</span></a></li><li><a href="#using-your-tool"><span>Using <wbr/>Your <wbr/>Tool</span></a></li></ul></li><li><a href="#tool-structure"><span>Tool <wbr/>Structure</span></a></li><li><ul><li><a href="#class-definition"><span>Class <wbr/>Definition</span></a></li><li><a href="#type-parameter"><span>Type <wbr/>Parameter</span></a></li></ul></li><li><a href="#lifecycle-methods"><span>Lifecycle <wbr/>Methods</span></a></li><li><ul><li><a href="#preactivatepriority"><span>pre<wbr/>Activate(priority)</span></a></li><li><a href="#postactivatepriority"><span>post<wbr/>Activate(priority)</span></a></li><li><a href="#preupgrade"><span>pre<wbr/>Upgrade()</span></a></li><li><a href="#postupgrade"><span>post<wbr/>Upgrade()</span></a></li><li><a href="#predeactivate"><span>pre<wbr/>Deactivate()</span></a></li><li><a href="#postdeactivate"><span>post<wbr/>Deactivate()</span></a></li><li><a href="#execution-order"><span>Execution <wbr/>Order</span></a></li></ul></li><li><a href="#dependencies"><span>Dependencies</span></a></li><li><ul><li><a href="#declaring-dependencies"><span>Declaring <wbr/>Dependencies</span></a></li><li><a href="#accessing-dependencies"><span>Accessing <wbr/>Dependencies</span></a></li><li><a href="#built-in-tool-access"><span>Built-<wbr/>in <wbr/>Tool <wbr/>Access</span></a></li></ul></li><li><a href="#options-and-configuration"><span>Options and <wbr/>Configuration</span></a></li><li><ul><li><a href="#defining-options"><span>Defining <wbr/>Options</span></a></li><li><a href="#using-options"><span>Using <wbr/>Options</span></a></li><li><a href="#required-vs-optional-options"><span>Required vs. <wbr/>Optional <wbr/>Options</span></a></li></ul></li><li><a href="#complete-examples"><span>Complete <wbr/>Examples</span></a></li><li><ul><li><a href="#example-1-github-integration-tool"><span>Example 1: <wbr/>Git<wbr/>Hub <wbr/>Integration <wbr/>Tool</span></a></li><li><a href="#example-2-slack-notification-tool"><span>Example 2: <wbr/>Slack <wbr/>Notification <wbr/>Tool</span></a></li></ul></li><li><a href="#testing-tools"><span>Testing <wbr/>Tools</span></a></li><li><ul><li><a href="#unit-testing"><span>Unit <wbr/>Testing</span></a></li><li><a href="#integration-testing"><span>Integration <wbr/>Testing</span></a></li></ul></li><li><a href="#publishing-tools"><span>Publishing <wbr/>Tools</span></a></li><li><ul><li><a href="#package-structure"><span>Package <wbr/>Structure</span></a></li><li><a href="#packagejson"><span>package.json</span></a></li><li><a href="#publishing"><span>Publishing</span></a></li><li><a href="#documentation"><span>Documentation</span></a></li></ul></li><li><a href="#best-practices"><span>Best <wbr/>Practices</span></a></li><li><ul><li><a href="#1-single-responsibility"><span>1. <wbr/>Single <wbr/>Responsibility</span></a></li><li><a href="#2-type-safety"><span>2. <wbr/>Type <wbr/>Safety</span></a></li><li><a href="#3-error-handling"><span>3. <wbr/>Error <wbr/>Handling</span></a></li><li><a href="#4-configuration-validation"><span>4. <wbr/>Configuration <wbr/>Validation</span></a></li><li><a href="#5-resource-cleanup"><span>5. <wbr/>Resource <wbr/>Cleanup</span></a></li><li><a href="#6-avoid-instance-state"><span>6. <wbr/>Avoid <wbr/>Instance <wbr/>State</span></a></li><li><a href="#7-document-your-api"><span>7. <wbr/>Document <wbr/>Your <wbr/>API</span></a></li></ul></li><li><a href="#next-steps"><span>Next <wbr/>Steps</span></a></li></ul></div></details></div><div class="site-menu"><nav id="tsd-sidebar-links" class="tsd-navigation"><a href="https://plot.day" class="tsd-nav-link">Plot</a><a href="https://github.com/plotday/plot" class="tsd-nav-link">GitHub</a><a href="https://www.npmjs.com/package/@plotday/twister" class="tsd-nav-link">NPM</a></nav><nav class="tsd-navigation"><a href="../modules.html">Creating Plot Twists</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>
205
+ </div></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div><details open class="tsd-accordion tsd-page-navigation"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>On This Page</h3></summary><div class="tsd-accordion-details"><a href="#building-custom-tools"><span>Building <wbr/>Custom <wbr/>Tools</span></a><ul><li><a href="#table-of-contents"><span>Table of <wbr/>Contents</span></a></li><li><a href="#why-build-tools"><span>Why <wbr/>Build <wbr/>Tools?</span></a></li><li><ul><li><a href="#built-in-vs-custom-tools"><span>Built-<wbr/>in vs. <wbr/>Custom <wbr/>Tools</span></a></li></ul></li><li><a href="#tool-basics"><span>Tool <wbr/>Basics</span></a></li><li><ul><li><a href="#minimal-tool-example"><span>Minimal <wbr/>Tool <wbr/>Example</span></a></li><li><a href="#using-your-tool"><span>Using <wbr/>Your <wbr/>Tool</span></a></li></ul></li><li><a href="#tool-structure"><span>Tool <wbr/>Structure</span></a></li><li><ul><li><a href="#class-definition"><span>Class <wbr/>Definition</span></a></li><li><a href="#type-parameter"><span>Type <wbr/>Parameter</span></a></li></ul></li><li><a href="#lifecycle-methods"><span>Lifecycle <wbr/>Methods</span></a></li><li><ul><li><a href="#preactivatepriority"><span>pre<wbr/>Activate(priority)</span></a></li><li><a href="#postactivatepriority"><span>post<wbr/>Activate(priority)</span></a></li><li><a href="#preupgrade"><span>pre<wbr/>Upgrade()</span></a></li><li><a href="#postupgrade"><span>post<wbr/>Upgrade()</span></a></li><li><a href="#predeactivate"><span>pre<wbr/>Deactivate()</span></a></li><li><a href="#postdeactivate"><span>post<wbr/>Deactivate()</span></a></li><li><a href="#execution-order"><span>Execution <wbr/>Order</span></a></li></ul></li><li><a href="#dependencies"><span>Dependencies</span></a></li><li><ul><li><a href="#declaring-dependencies"><span>Declaring <wbr/>Dependencies</span></a></li><li><a href="#accessing-dependencies"><span>Accessing <wbr/>Dependencies</span></a></li><li><a href="#built-in-tool-access"><span>Built-<wbr/>in <wbr/>Tool <wbr/>Access</span></a></li></ul></li><li><a href="#options-and-configuration"><span>Options and <wbr/>Configuration</span></a></li><li><ul><li><a href="#defining-options"><span>Defining <wbr/>Options</span></a></li><li><a href="#using-options"><span>Using <wbr/>Options</span></a></li><li><a href="#required-vs-optional-options"><span>Required vs. <wbr/>Optional <wbr/>Options</span></a></li></ul></li><li><a href="#complete-examples"><span>Complete <wbr/>Examples</span></a></li><li><ul><li><a href="#example-1-github-integration-tool"><span>Example 1: <wbr/>Git<wbr/>Hub <wbr/>Integration <wbr/>Tool</span></a></li><li><a href="#example-2-slack-notification-tool"><span>Example 2: <wbr/>Slack <wbr/>Notification <wbr/>Tool</span></a></li></ul></li><li><a href="#testing-tools"><span>Testing <wbr/>Tools</span></a></li><li><ul><li><a href="#unit-testing"><span>Unit <wbr/>Testing</span></a></li><li><a href="#integration-testing"><span>Integration <wbr/>Testing</span></a></li></ul></li><li><a href="#publishing-tools"><span>Publishing <wbr/>Tools</span></a></li><li><ul><li><a href="#package-structure"><span>Package <wbr/>Structure</span></a></li><li><a href="#packagejson"><span>package.json</span></a></li><li><a href="#publishing"><span>Publishing</span></a></li><li><a href="#documentation"><span>Documentation</span></a></li></ul></li><li><a href="#best-practices"><span>Best <wbr/>Practices</span></a></li><li><ul><li><a href="#1-single-responsibility"><span>1. <wbr/>Single <wbr/>Responsibility</span></a></li><li><a href="#2-type-safety"><span>2. <wbr/>Type <wbr/>Safety</span></a></li><li><a href="#3-error-handling"><span>3. <wbr/>Error <wbr/>Handling</span></a></li><li><a href="#4-configuration-validation"><span>4. <wbr/>Configuration <wbr/>Validation</span></a></li><li><a href="#5-resource-cleanup"><span>5. <wbr/>Resource <wbr/>Cleanup</span></a></li><li><a href="#6-avoid-instance-state"><span>6. <wbr/>Avoid <wbr/>Instance <wbr/>State</span></a></li><li><a href="#7-document-your-api"><span>7. <wbr/>Document <wbr/>Your <wbr/>API</span></a></li><li><a href="#8-data-synchronization"><span>8. <wbr/>Data <wbr/>Synchronization</span></a></li></ul></li><li><a href="#next-steps"><span>Next <wbr/>Steps</span></a></li></ul></div></details></div><div class="site-menu"><nav id="tsd-sidebar-links" class="tsd-navigation"><a href="https://plot.day" class="tsd-nav-link">Plot</a><a href="https://github.com/plotday/plot" class="tsd-nav-link">GitHub</a><a href="https://www.npmjs.com/package/@plotday/twister" class="tsd-nav-link">NPM</a></nav><nav class="tsd-navigation"><a href="../modules.html">Creating Plot Twists</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>