@plotday/twister 0.48.0 → 0.50.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 (137) hide show
  1. package/bin/templates/AGENTS.template.md +8 -2
  2. package/cli/templates/AGENTS.template.md +8 -2
  3. package/dist/connector.d.ts +97 -10
  4. package/dist/connector.d.ts.map +1 -1
  5. package/dist/connector.js +15 -5
  6. package/dist/connector.js.map +1 -1
  7. package/dist/docs/assets/hierarchy.js +1 -1
  8. package/dist/docs/assets/navigation.js +1 -1
  9. package/dist/docs/assets/search.js +1 -1
  10. package/dist/docs/classes/index.Connector.html +84 -51
  11. package/dist/docs/classes/index.Imap.html +1 -1
  12. package/dist/docs/classes/index.Options.html +1 -1
  13. package/dist/docs/classes/index.Smtp.html +1 -1
  14. package/dist/docs/classes/tools_ai.AI.html +1 -1
  15. package/dist/docs/classes/tools_callbacks.Callbacks.html +1 -1
  16. package/dist/docs/classes/tools_integrations.Integrations.html +55 -9
  17. package/dist/docs/classes/tools_network.Network.html +1 -1
  18. package/dist/docs/classes/tools_plot.Plot.html +11 -19
  19. package/dist/docs/classes/tools_store.Store.html +25 -2
  20. package/dist/docs/classes/tools_tasks.Tasks.html +1 -1
  21. package/dist/docs/classes/tools_twists.Twists.html +1 -1
  22. package/dist/docs/classes/twist.Twist.html +28 -28
  23. package/dist/docs/documents/Building_Connectors.html +8 -1
  24. package/dist/docs/documents/Built-in_Tools.html +1 -1
  25. package/dist/docs/documents/Runtime_Environment.html +25 -1
  26. package/dist/docs/enums/plot.ActorType.html +4 -4
  27. package/dist/docs/enums/tag.Tag.html +11 -1
  28. package/dist/docs/enums/tools_integrations.AuthProvider.html +13 -13
  29. package/dist/docs/hierarchy.html +1 -1
  30. package/dist/docs/media/AGENTS.md +298 -775
  31. package/dist/docs/media/MULTI_USER_AUTH.md +6 -4
  32. package/dist/docs/media/SYNC_STRATEGIES.md +20 -14
  33. package/dist/docs/modules/index.html +1 -1
  34. package/dist/docs/types/index.CreateLinkDraft.html +7 -12
  35. package/dist/docs/types/index.NewScheduleOccurrence.html +15 -2
  36. package/dist/docs/types/index.NoteWriteBackResult.html +38 -0
  37. package/dist/docs/types/index.ScheduleOccurrence.html +2 -4
  38. package/dist/docs/types/index.ScheduleOccurrenceUpdate.html +1 -1
  39. package/dist/docs/types/plot.Actor.html +5 -5
  40. package/dist/docs/types/plot.Contact.html +4 -4
  41. package/dist/docs/types/plot.ContentType.html +1 -1
  42. package/dist/docs/types/plot.Link.html +15 -15
  43. package/dist/docs/types/plot.LinkUpdate.html +1 -1
  44. package/dist/docs/types/plot.NewActor.html +1 -1
  45. package/dist/docs/types/plot.NewContact.html +1 -1
  46. package/dist/docs/types/plot.NewLink.html +1 -1
  47. package/dist/docs/types/plot.NewLinkWithNotes.html +1 -1
  48. package/dist/docs/types/plot.NewNote.html +1 -1
  49. package/dist/docs/types/plot.Note.html +7 -1
  50. package/dist/docs/types/plot.NoteUpdate.html +1 -1
  51. package/dist/docs/types/plot.PlanOperation.html +1 -1
  52. package/dist/docs/types/tools_integrations.ArchiveLinkFilter.html +5 -5
  53. package/dist/docs/types/tools_integrations.AuthToken.html +4 -4
  54. package/dist/docs/types/tools_integrations.Authorization.html +4 -4
  55. package/dist/docs/types/tools_integrations.SyncContext.html +21 -2
  56. package/dist/llm-docs/connector.d.ts +1 -1
  57. package/dist/llm-docs/connector.d.ts.map +1 -1
  58. package/dist/llm-docs/connector.js +1 -1
  59. package/dist/llm-docs/connector.js.map +1 -1
  60. package/dist/llm-docs/plot.d.ts +1 -1
  61. package/dist/llm-docs/plot.d.ts.map +1 -1
  62. package/dist/llm-docs/plot.js +1 -1
  63. package/dist/llm-docs/plot.js.map +1 -1
  64. package/dist/llm-docs/schedule.d.ts +1 -1
  65. package/dist/llm-docs/schedule.d.ts.map +1 -1
  66. package/dist/llm-docs/schedule.js +1 -1
  67. package/dist/llm-docs/schedule.js.map +1 -1
  68. package/dist/llm-docs/tag.d.ts +1 -1
  69. package/dist/llm-docs/tag.d.ts.map +1 -1
  70. package/dist/llm-docs/tag.js +1 -1
  71. package/dist/llm-docs/tag.js.map +1 -1
  72. package/dist/llm-docs/tools/integrations.d.ts +1 -1
  73. package/dist/llm-docs/tools/integrations.d.ts.map +1 -1
  74. package/dist/llm-docs/tools/integrations.js +1 -1
  75. package/dist/llm-docs/tools/integrations.js.map +1 -1
  76. package/dist/llm-docs/tools/plot.d.ts +1 -1
  77. package/dist/llm-docs/tools/plot.d.ts.map +1 -1
  78. package/dist/llm-docs/tools/plot.js +1 -1
  79. package/dist/llm-docs/tools/plot.js.map +1 -1
  80. package/dist/llm-docs/tools/store.d.ts +1 -1
  81. package/dist/llm-docs/tools/store.d.ts.map +1 -1
  82. package/dist/llm-docs/tools/store.js +1 -1
  83. package/dist/llm-docs/tools/store.js.map +1 -1
  84. package/dist/llm-docs/twist-guide-template.d.ts +1 -1
  85. package/dist/llm-docs/twist-guide-template.d.ts.map +1 -1
  86. package/dist/llm-docs/twist-guide-template.js +1 -1
  87. package/dist/llm-docs/twist-guide-template.js.map +1 -1
  88. package/dist/llm-docs/twist.d.ts +1 -1
  89. package/dist/llm-docs/twist.d.ts.map +1 -1
  90. package/dist/llm-docs/twist.js +1 -1
  91. package/dist/llm-docs/twist.js.map +1 -1
  92. package/dist/plot.d.ts +8 -1
  93. package/dist/plot.d.ts.map +1 -1
  94. package/dist/plot.js.map +1 -1
  95. package/dist/schedule.d.ts +18 -2
  96. package/dist/schedule.d.ts.map +1 -1
  97. package/dist/tag.d.ts +11 -1
  98. package/dist/tag.d.ts.map +1 -1
  99. package/dist/tag.js +10 -0
  100. package/dist/tag.js.map +1 -1
  101. package/dist/tools/integrations.d.ts +86 -0
  102. package/dist/tools/integrations.d.ts.map +1 -1
  103. package/dist/tools/integrations.js.map +1 -1
  104. package/dist/tools/plot.d.ts +0 -11
  105. package/dist/tools/plot.d.ts.map +1 -1
  106. package/dist/tools/plot.js.map +1 -1
  107. package/dist/tools/store.d.ts +40 -0
  108. package/dist/tools/store.d.ts.map +1 -1
  109. package/dist/tools/store.js.map +1 -1
  110. package/dist/twist-guide.d.ts +1 -1
  111. package/dist/twist-guide.d.ts.map +1 -1
  112. package/dist/twist.d.ts +2 -1
  113. package/dist/twist.d.ts.map +1 -1
  114. package/dist/twist.js.map +1 -1
  115. package/dist/utils/markdown.d.ts +27 -0
  116. package/dist/utils/markdown.d.ts.map +1 -0
  117. package/dist/utils/markdown.js +82 -0
  118. package/dist/utils/markdown.js.map +1 -0
  119. package/package.json +6 -1
  120. package/src/connector.ts +98 -10
  121. package/src/llm-docs/connector.ts +1 -1
  122. package/src/llm-docs/plot.ts +1 -1
  123. package/src/llm-docs/schedule.ts +1 -1
  124. package/src/llm-docs/tag.ts +1 -1
  125. package/src/llm-docs/tools/integrations.ts +1 -1
  126. package/src/llm-docs/tools/plot.ts +1 -1
  127. package/src/llm-docs/tools/store.ts +1 -1
  128. package/src/llm-docs/twist-guide-template.ts +1 -1
  129. package/src/llm-docs/twist.ts +1 -1
  130. package/src/plot.ts +8 -1
  131. package/src/schedule.ts +19 -3
  132. package/src/tag.ts +10 -0
  133. package/src/tools/integrations.ts +93 -0
  134. package/src/tools/plot.ts +0 -12
  135. package/src/tools/store.ts +44 -0
  136. package/src/twist.ts +2 -1
  137. package/src/utils/markdown.ts +94 -0
@@ -183,9 +183,15 @@ async onThreadUpdated(thread: Thread, changes: { tagsAdded, tagsRemoved }): Prom
183
183
  if (tool?.updateIssue) await tool.updateIssue(thread);
184
184
  }
185
185
 
186
- async onNoteCreated(note: Note): Promise<void> {
186
+ async onNoteCreated(note: Note, thread: Thread): Promise<NoteWriteBackResult | void> {
187
187
  if (note.author.type === ActorType.Twist) return; // Prevent loops
188
- // Sync note to external service as a comment
188
+ // Sync note to external service as a comment. Return the external
189
+ // system's id + stored content so the runtime can set note.key AND
190
+ // record a sync baseline that preserves Plot's content on round-trip.
191
+ // See connectors/AGENTS.md → "Sync baseline preservation".
192
+ const comment = await externalApi.createComment(thread.meta.externalId, { body: note.content ?? "" });
193
+ if (!comment?.id) return;
194
+ return { key: `comment-${comment.id}`, externalContent: comment.body };
189
195
  }
190
196
  ```
191
197
 
@@ -183,9 +183,15 @@ async onThreadUpdated(thread: Thread, changes: { tagsAdded, tagsRemoved }): Prom
183
183
  if (tool?.updateIssue) await tool.updateIssue(thread);
184
184
  }
185
185
 
186
- async onNoteCreated(note: Note): Promise<void> {
186
+ async onNoteCreated(note: Note, thread: Thread): Promise<NoteWriteBackResult | void> {
187
187
  if (note.author.type === ActorType.Twist) return; // Prevent loops
188
- // Sync note to external service as a comment
188
+ // Sync note to external service as a comment. Return the external
189
+ // system's id + stored content so the runtime can set note.key AND
190
+ // record a sync baseline that preserves Plot's content on round-trip.
191
+ // See connectors/AGENTS.md → "Sync baseline preservation".
192
+ const comment = await externalApi.createComment(thread.meta.externalId, { body: note.content ?? "" });
193
+ if (!comment?.id) return;
194
+ return { key: `comment-${comment.id}`, externalContent: comment.body };
189
195
  }
190
196
  ```
191
197
 
@@ -10,6 +10,56 @@ import { Twist } from "./twist";
10
10
  * The platform attaches the returned `NewLinkWithNotes` to the originating
11
11
  * thread once `onCreateLink` resolves.
12
12
  */
13
+ /**
14
+ * Result returned from {@link Connector.onNoteCreated} and
15
+ * {@link Connector.onNoteUpdated} to report what the external system now
16
+ * has stored for the note.
17
+ *
18
+ * The runtime hashes `externalContent` and stores it as the note's sync
19
+ * baseline. On the next sync-in, if the incoming content hashes to the
20
+ * same value, the runtime knows the external side hasn't changed and
21
+ * preserves Plot's (possibly formatted) content. When the external side
22
+ * is edited, the hash diverges and the runtime overwrites Plot's content
23
+ * with the new external version.
24
+ *
25
+ * Omitting `externalContent` skips baseline tracking — the next sync-in
26
+ * will overwrite Plot's content (previous behavior). Always provide it
27
+ * when the write-back's return value reflects what the external system
28
+ * actually stored (often lossy plain-text), so the round-trip does not
29
+ * clobber the original Plot markdown.
30
+ *
31
+ * The hash covers only the content string — the runtime intentionally
32
+ * does not include a content-type in the hash, so write-back and sync-in
33
+ * do not have to agree on a content-type label for the same underlying
34
+ * bytes. Return exactly the string your connector's sync-in path will
35
+ * emit as `NewNote.content` for this note on the next re-ingest.
36
+ *
37
+ * For back-compat, `onNoteCreated` may also return a plain string, which
38
+ * is treated as `{ key }` with no baseline.
39
+ */
40
+ export type NoteWriteBackResult = {
41
+ /**
42
+ * External system identifier assigned to this note. Set as the note's
43
+ * `key` for future upsert matching. Required when the runtime does not
44
+ * already know the key (i.e., from `onNoteCreated`); ignored from
45
+ * `onNoteUpdated` when the key was already established on create.
46
+ */
47
+ key?: string;
48
+ /**
49
+ * The content string as the external system now stores it, post-write.
50
+ * For systems whose write-back returns a representation of what was
51
+ * actually stored (e.g. Google Drive comment `content` after a create),
52
+ * pass that verbatim. For systems that only accept plain text, this
53
+ * will often be a lossy plain-text version of the Plot markdown — that
54
+ * is exactly the point: storing the lossy form as baseline lets the
55
+ * next sync-in recognize it and skip overwriting the richer Plot
56
+ * version.
57
+ *
58
+ * Must exactly match the string your connector's sync-in path emits as
59
+ * `NewNote.content` for this note on re-ingest.
60
+ */
61
+ externalContent?: string;
62
+ };
13
63
  export type CreateLinkDraft = {
14
64
  /** The channel (account + resource) the new item belongs to. */
15
65
  channelId: string;
@@ -151,6 +201,29 @@ export declare abstract class Connector<TSelf> extends Twist<TSelf> {
151
201
  /**
152
202
  * Called when a channel resource is enabled for syncing.
153
203
  *
204
+ * The framework dispatches this in three cases:
205
+ * 1. **Initial enable** — user toggled the channel on for the first time.
206
+ * 2. **Auto-enable** — `setChannels` discovered a new channel on a
207
+ * connection with `auto_enable_new_channels` set.
208
+ * 3. **Recovery after re-auth** — the user re-authorized a previously-
209
+ * broken connection. The framework calls `onChannelEnabled` for every
210
+ * channel that was already enabled at the time of re-auth, with
211
+ * `context.recovering = true`. See {@link SyncContext.recovering}.
212
+ *
213
+ * Implementations should be **idempotent and overwrite stored state**:
214
+ * the same channel may receive multiple `onChannelEnabled` calls across
215
+ * its lifetime. Use unconditional `this.set()` writes rather than
216
+ * coalesce/skip-if-present logic so a recovery dispatch wipes stale
217
+ * cursors and state from the prior session.
218
+ *
219
+ * **Sync state tracking is automatic.** The framework stamps the
220
+ * connection as "syncing" when it dispatches this method and clears
221
+ * that state when:
222
+ * - the connector calls `tools.integrations.channelSyncCompleted(id)`
223
+ * once the initial backfill is done, OR
224
+ * - this method throws an unhandled exception (auto-cleared so the UI
225
+ * doesn't get stuck in "syncing" forever).
226
+ *
154
227
  * **IMPORTANT: This method runs inline in the HTTP request handler.**
155
228
  * Any long-running work (webhook setup, API calls, sync) MUST be queued
156
229
  * as a separate task via `this.runTask()`, not executed inline. Blocking
@@ -161,8 +234,12 @@ export declare abstract class Connector<TSelf> extends Twist<TSelf> {
161
234
  *
162
235
  * @example
163
236
  * ```typescript
164
- * async onChannelEnabled(channel: Channel): Promise<void> {
165
- * await this.set(`sync_enabled_${channel.id}`, true);
237
+ * async onChannelEnabled(channel: Channel, context?: SyncContext): Promise<void> {
238
+ * // Recovery: drop stale cursors so the next sync re-walks history.
239
+ * if (context?.recovering) {
240
+ * await this.clear(`last_sync_token_${channel.id}`);
241
+ * }
242
+ *
166
243
  * await this.set(`sync_state_${channel.id}`, { channelId: channel.id });
167
244
  *
168
245
  * // Queue sync as a task — do NOT use this.run() or call sync methods inline
@@ -176,7 +253,7 @@ export declare abstract class Connector<TSelf> extends Twist<TSelf> {
176
253
  * ```
177
254
  *
178
255
  * @param channel - The channel that was enabled
179
- * @param context - Optional sync context with plan-based hints (e.g. syncHistoryMin)
256
+ * @param context - Optional sync context (plan-based hints, recovery flag)
180
257
  */
181
258
  abstract onChannelEnabled(channel: Channel, context?: SyncContext): Promise<void>;
182
259
  /**
@@ -220,24 +297,34 @@ export declare abstract class Connector<TSelf> extends Twist<TSelf> {
220
297
  * Override to write back comments to the external service
221
298
  * (e.g., adding a comment to a Linear issue).
222
299
  *
223
- * Returning a string sets the note's `key` for future upsert matching,
224
- * linking the Plot note to its external counterpart so that subsequent
225
- * syncs (reactions, edits) update the existing note instead of creating duplicates.
300
+ * Returning a string or {@link NoteWriteBackResult} links the Plot note
301
+ * to its external counterpart. A plain string sets the note's `key`.
302
+ * A `NoteWriteBackResult` additionally sets a sync baseline (via
303
+ * `externalContent`) so the next sync-in can recognize the round-tripped
304
+ * content and preserve Plot's formatted version. See
305
+ * {@link NoteWriteBackResult} for details.
226
306
  *
227
307
  * @param note - The created note
228
308
  * @param thread - The thread the note belongs to (includes thread.meta with connector-specific data)
229
- * @returns Optional note key for external deduplication
309
+ * @returns Optional note key or NoteWriteBackResult for external dedup + baseline tracking
230
310
  */
231
- onNoteCreated(note: Note, thread: Thread): Promise<string | void>;
311
+ onNoteCreated(note: Note, thread: Thread): Promise<string | NoteWriteBackResult | void>;
232
312
  /**
233
313
  * Called when a note on a thread owned by this connector is updated.
234
314
  * Override to write back changes to the external service
235
- * (e.g., syncing reaction tags as emoji reactions).
315
+ * (e.g., syncing reaction tags as emoji reactions, or editing a comment
316
+ * whose content changed in Plot).
317
+ *
318
+ * Return a {@link NoteWriteBackResult} with `externalContent` to update
319
+ * the sync baseline after a successful write-back, so the next sync-in
320
+ * recognizes the external version as already-seen and preserves Plot's
321
+ * content.
236
322
  *
237
323
  * @param note - The updated note (includes current tags)
238
324
  * @param thread - The thread the note belongs to (includes thread.meta with connector-specific data)
325
+ * @returns Optional NoteWriteBackResult for baseline tracking
239
326
  */
240
- onNoteUpdated(note: Note, thread: Thread): Promise<void>;
327
+ onNoteUpdated(note: Note, thread: Thread): Promise<NoteWriteBackResult | void>;
241
328
  /**
242
329
  * Called when a user reads or unreads a thread owned by this connector.
243
330
  * Override to write back read status to the external service
@@ -1 +1 @@
1
- {"version":3,"file":"connector.d.ts","sourceRoot":"","sources":["../src/connector.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"connector.d.ts","sourceRoot":"","sources":["../src/connector.ts"],"names":[],"mappings":"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"}
package/dist/connector.js CHANGED
@@ -157,13 +157,16 @@ export class Connector extends Twist {
157
157
  * Override to write back comments to the external service
158
158
  * (e.g., adding a comment to a Linear issue).
159
159
  *
160
- * Returning a string sets the note's `key` for future upsert matching,
161
- * linking the Plot note to its external counterpart so that subsequent
162
- * syncs (reactions, edits) update the existing note instead of creating duplicates.
160
+ * Returning a string or {@link NoteWriteBackResult} links the Plot note
161
+ * to its external counterpart. A plain string sets the note's `key`.
162
+ * A `NoteWriteBackResult` additionally sets a sync baseline (via
163
+ * `externalContent`) so the next sync-in can recognize the round-tripped
164
+ * content and preserve Plot's formatted version. See
165
+ * {@link NoteWriteBackResult} for details.
163
166
  *
164
167
  * @param note - The created note
165
168
  * @param thread - The thread the note belongs to (includes thread.meta with connector-specific data)
166
- * @returns Optional note key for external deduplication
169
+ * @returns Optional note key or NoteWriteBackResult for external dedup + baseline tracking
167
170
  */
168
171
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
169
172
  onNoteCreated(note, thread) {
@@ -172,10 +175,17 @@ export class Connector extends Twist {
172
175
  /**
173
176
  * Called when a note on a thread owned by this connector is updated.
174
177
  * Override to write back changes to the external service
175
- * (e.g., syncing reaction tags as emoji reactions).
178
+ * (e.g., syncing reaction tags as emoji reactions, or editing a comment
179
+ * whose content changed in Plot).
180
+ *
181
+ * Return a {@link NoteWriteBackResult} with `externalContent` to update
182
+ * the sync baseline after a successful write-back, so the next sync-in
183
+ * recognizes the external version as already-seen and preserves Plot's
184
+ * content.
176
185
  *
177
186
  * @param note - The updated note (includes current tags)
178
187
  * @param thread - The thread the note belongs to (includes thread.meta with connector-specific data)
188
+ * @returns Optional NoteWriteBackResult for baseline tracking
179
189
  */
180
190
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
181
191
  onNoteUpdated(note, thread) {
@@ -1 +1 @@
1
- {"version":3,"file":"connector.js","sourceRoot":"","sources":["../src/connector.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AA8BhC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,MAAM,OAAgB,SAAiB,SAAQ,KAAY;IACzD;;;OAGG;IACH,MAAM,CAAU,WAAW,GAAG,IAAI,CAAC;IAEnC,+DAA+D;IAE/D,4DAA4D;IACnD,QAAQ,CAAgB;IAEjC,kDAAkD;IACzC,MAAM,CAAY;IAE3B,uBAAuB;IAEvB;;;;;;;;;;OAUG;IACM,MAAM,CAAW;IAE1B;;;;;;;OAOG;IACM,SAAS,CAAU;IAE5B,8BAA8B;IAE9B;;;;OAIG;IACM,aAAa,CAAW;IAEjC;;;OAGG;IACM,SAAS,CAAoB;IAEtC;;;;;;OAMG;IACH,MAAM,CAAU,aAAa,CAAW;IAExC,yEAAyE;IAEzE;;;;;;;;;;;;;OAaG;IACH,6DAA6D;IAC7D,cAAc,CACZ,IAA0B,EAC1B,KAAuB;QAEvB,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAyDD,wDAAwD;IAExD;;;;;;OAMG;IACH,6DAA6D;IAC7D,aAAa,CAAC,IAAU;QACtB,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACH,6DAA6D;IAC7D,YAAY,CAAC,KAAsB;QACjC,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,6DAA6D;IAC7D,aAAa,CAAC,IAAU,EAAE,MAAc;QACtC,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED;;;;;;;OAOG;IACH,6DAA6D;IAC7D,aAAa,CAAC,IAAU,EAAE,MAAc;QACtC,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED;;;;;;;;OAQG;IACH,6DAA6D;IAC7D,YAAY,CAAC,MAAc,EAAE,KAAY,EAAE,MAAe;QACxD,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED;;;;;;;;;;OAUG;IACH,6DAA6D;IAC7D,YAAY,CAAC,MAAc,EAAE,KAAY,EAAE,IAAa,EAAE,OAAwB;QAChF,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED;;;;;;;;;OASG;IACH,6DAA6D;IAC7D,wBAAwB,CAAC,MAAc,EAAE,UAAkB,EAAE,SAAkB,EAAE,MAAoC,EAAE,KAAY;QACjI,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED,uBAAuB;IAEvB;;;;;;;;;;;;OAYG;IACH,2EAA2E;IAC3E,QAAQ,CAAC,OAAgD;QACvD,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;;AAGH,2CAA2C;AAC3C,OAAO,EAAE,SAAS,IAAI,MAAM,EAAE,CAAC"}
1
+ {"version":3,"file":"connector.js","sourceRoot":"","sources":["../src/connector.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAiFhC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,MAAM,OAAgB,SAAiB,SAAQ,KAAY;IACzD;;;OAGG;IACH,MAAM,CAAU,WAAW,GAAG,IAAI,CAAC;IAEnC,+DAA+D;IAE/D,4DAA4D;IACnD,QAAQ,CAAgB;IAEjC,kDAAkD;IACzC,MAAM,CAAY;IAE3B,uBAAuB;IAEvB;;;;;;;;;;OAUG;IACM,MAAM,CAAW;IAE1B;;;;;;;OAOG;IACM,SAAS,CAAU;IAE5B,8BAA8B;IAE9B;;;;OAIG;IACM,aAAa,CAAW;IAEjC;;;OAGG;IACM,SAAS,CAAoB;IAEtC;;;;;;OAMG;IACH,MAAM,CAAU,aAAa,CAAW;IAExC,yEAAyE;IAEzE;;;;;;;;;;;;;OAaG;IACH,6DAA6D;IAC7D,cAAc,CACZ,IAA0B,EAC1B,KAAuB;QAEvB,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAoFD,wDAAwD;IAExD;;;;;;OAMG;IACH,6DAA6D;IAC7D,aAAa,CAAC,IAAU;QACtB,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACH,6DAA6D;IAC7D,YAAY,CAAC,KAAsB;QACjC,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACH,6DAA6D;IAC7D,aAAa,CAAC,IAAU,EAAE,MAAc;QACtC,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACH,6DAA6D;IAC7D,aAAa,CAAC,IAAU,EAAE,MAAc;QACtC,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED;;;;;;;;OAQG;IACH,6DAA6D;IAC7D,YAAY,CAAC,MAAc,EAAE,KAAY,EAAE,MAAe;QACxD,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED;;;;;;;;;;OAUG;IACH,6DAA6D;IAC7D,YAAY,CAAC,MAAc,EAAE,KAAY,EAAE,IAAa,EAAE,OAAwB;QAChF,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED;;;;;;;;;OASG;IACH,6DAA6D;IAC7D,wBAAwB,CAAC,MAAc,EAAE,UAAkB,EAAE,SAAkB,EAAE,MAAoC,EAAE,KAAY;QACjI,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED,uBAAuB;IAEvB;;;;;;;;;;;;OAYG;IACH,2EAA2E;IAC3E,QAAQ,CAAC,OAAgD;QACvD,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;;AAGH,2CAA2C;AAC3C,OAAO,EAAE,SAAS,IAAI,MAAM,EAAE,CAAC"}
@@ -1 +1 @@
1
- window.hierarchyData = "eJyVkz1PwzAQhv/LzVdTu86Hs1VMWQCJbqhCITU0qmNXsVGRqvx35KRUhqE2S4bkufe5nM9nGIxxFqoXynIUW4RBvivZus5oC9UZhH/oppdQwebUWQcIh07voKKsRPgcFFTQqsZaae+cB8iEkb3rFeD8CSpwdrfwdYv5BUK779RukHpSU74dESjLA1u9MUbdtBmjyET9TyYw4xlmRYZFnmPJGQpGUYgVUkoFUsqXSLNyhTTnJdJiyebmfo0ipbeE1kaEjGd/Z2xj0fZ1GrWdZ20TJEUoWddxQdORdR0PLvLwzO4bpd6a9pDwA+0PSq5FcVvJWbgh2smPoZl3NSrsApqEpXGtYDTQPkh3MsMhbtQzSC4FCR6xCjxPyty+bZPkqIwjHo3H+/UO8p+dGWRcYD1GJjhFwZfhNjc2ZRecx8gEJygY5eHKGa1l68xwS9PpnfwiVzRBkpXhUdR9c4zneyohOudleAq9S4j2VEJ0sQzvx+MxejXm9AsYE4zjN+vz/lU="
1
+ window.hierarchyData = "eJyVk7FOwzAQht/l5sNwSR0n2apOXQCJbqhCITU0qmNXsVGRqr47clIql6E2S4bku/+7nM9HGIxxFupXygqs1giD/FCydZ3RFuojVP6hm15CDatDZx0g7Dq9gZqyEuFrUFBDqxprpb13HmAjxrauV4DTJ6jB2c2dr7ubXiC0205tBqlH9SxfnxAoKwLbcmWMumkzRrGR+p+sQs458pKjEAWWPMdqRkgPlCNRLpCo4EgFZUiFEEgip6m7q1mkNJfQ2wmBc/53yDYWbd/GWdtp2DZBUoaS+TIuaDo2X8aDhQgPbdEo9d60u4QfaH9RdimK20qehyuinfwcmmlZo8IuoFlYGtdWMwq0j9IdzLCLG/UEsnNB3OOXMBA9K3P7vo2WvTKOeTQhn3IR5L84M8i4wHqMjXCKorha58amLIPzGBvhBEU2C6e0MFrL1pnhlqbTG/nNLmiCpKAsXLW+2cfzPZUSLa5OoXcJ0Z5KiBZ5uKlP++jdmNLPYExwOv0AxKj+rw=="
@@ -1 +1 @@
1
- window.navigationData = "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"
1
+ window.navigationData = "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"