@mastra/github-signals 0.3.0 → 0.4.0-alpha.1

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.
package/LICENSE.md CHANGED
@@ -1,10 +1,12 @@
1
1
  Portions of this software are licensed as follows:
2
2
 
3
- - All content that resides under any directory named "ee/" within this
3
+ - All content that resides under any directory named `ee/` within this
4
4
  repository, including but not limited to:
5
- - `packages/core/src/auth/ee/`
6
- - `packages/server/src/server/auth/ee/`
7
- is licensed under the license defined in `ee/LICENSE`.
5
+ - `@mastra/core/auth/ee`
6
+ - `@mastra/core/agent-builder/ee`
7
+ - `@mastra/editor/ee`
8
+
9
+ is licensed under the license defined in [`ee/LICENSE`](https://github.com/mastra-ai/mastra/blob/main/ee/LICENSE).
8
10
 
9
11
  - All third-party components incorporated into the Mastra Software are
10
12
  licensed under the original license provided by the owner of the
package/dist/index.cjs CHANGED
@@ -148,7 +148,8 @@ function getGithubMetadata(threadMetadata) {
148
148
  ...readString(rawSubscription.lastNotificationAt) ? { lastNotificationAt: readString(rawSubscription.lastNotificationAt) } : {},
149
149
  ...readString(rawSubscription.lastNotificationKind) ? { lastNotificationKind: readString(rawSubscription.lastNotificationKind) } : {},
150
150
  ...rawSubscription.lastNotificationPriority === "medium" || rawSubscription.lastNotificationPriority === "high" ? { lastNotificationPriority: rawSubscription.lastNotificationPriority } : {},
151
- ...readString(rawSubscription.lastNotificationSummary) ? { lastNotificationSummary: readString(rawSubscription.lastNotificationSummary) } : {}
151
+ ...readString(rawSubscription.lastNotificationSummary) ? { lastNotificationSummary: readString(rawSubscription.lastNotificationSummary) } : {},
152
+ ...readString(rawSubscription.lastNotificationDedupeKey) ? { lastNotificationDedupeKey: readString(rawSubscription.lastNotificationDedupeKey) } : {}
152
153
  });
153
154
  }
154
155
  return {
@@ -278,6 +279,22 @@ function getCommentNotificationSummary(pr, snapshot) {
278
279
  if (!snapshot.latestCommentAuthor || !snapshot.latestCommentBody) return void 0;
279
280
  return `${snapshot.latestCommentAuthor} commented on ${pr}: ${getCommentExcerpt(snapshot.latestCommentBody)}`;
280
281
  }
282
+ function isNoisyBotComment(input) {
283
+ const author = input.author?.toLowerCase();
284
+ const body = input.body?.toLowerCase().trim();
285
+ if (!author || !body) return false;
286
+ if (author.includes("coderabbit")) return body.includes("## review skipped") || body.includes("review_stack_entry_start") || body.includes("review change stack") || body.includes("storage.googleapis.com/coderabbit_public_assets/review-stack") || body.includes("no actionable comments were generated") || body.includes("actions performed") && body.includes("review triggered");
287
+ if (author === "vercel[bot]") return body.startsWith("[vc]:");
288
+ if (author === "socket-security[bot]") return body.includes("review the following changes in direct dependencies");
289
+ if (author === "dane-ai-mastra[bot]") return body.includes("mastra-pr-automation") || body.includes("## pr triage") || body.includes("## pr complexity score");
290
+ return false;
291
+ }
292
+ function hasNoisyLatestBotComment(snapshot) {
293
+ return isNoisyBotComment({
294
+ author: snapshot.latestCommentAuthor,
295
+ body: snapshot.latestCommentBody
296
+ });
297
+ }
281
298
  const githubActivityNotificationPriority = {
282
299
  high: 0,
283
300
  medium: 1
@@ -297,7 +314,7 @@ function compareGithubActivityNotifications(a, b) {
297
314
  return getGithubActivityNotificationRank(a) - getGithubActivityNotificationRank(b);
298
315
  }
299
316
  function classifyGithubCommentActivityNotification(input) {
300
- if (isBotOnlyActivity(input.snapshot)) return void 0;
317
+ if (isBotOnlyActivity(input.snapshot) || hasNoisyLatestBotComment(input.snapshot)) return void 0;
301
318
  const summary = getCommentNotificationSummary(`${input.subscription.owner}/${input.subscription.repo}#${input.subscription.number}`, input.snapshot);
302
319
  if (!summary) return void 0;
303
320
  return {
@@ -452,7 +469,7 @@ function classifyGithubActivityNotification(input) {
452
469
  };
453
470
  }
454
471
  if (input.snapshot.ciState === "pending" && input.subscription.lastObservedCiState === "pending") return void 0;
455
- if (isBotOnlyActivity(input.snapshot)) return void 0;
472
+ if (isBotOnlyActivity(input.snapshot) || hasNoisyLatestBotComment(input.snapshot)) return void 0;
456
473
  const commentSummary = getCommentNotificationSummary(pr, input.snapshot);
457
474
  return {
458
475
  kind: "pull-request-activity",
@@ -852,12 +869,6 @@ var GithubSignals = class extends _mastra_core_signals.SignalProvider {
852
869
  return false;
853
870
  }
854
871
  const key = this.#pollingKey(input);
855
- for (const [pollingKey, state] of this.#polling.entries()) {
856
- if (pollingKey === key) continue;
857
- this.#invalidatePollingThread(pollingKey);
858
- clearInterval(state.timer);
859
- this.#polling.delete(pollingKey);
860
- }
861
872
  if (this.#polling.has(key)) return true;
862
873
  const runPoll = (pollOptions = {}) => {
863
874
  this.#pollThread(input, pollOptions).catch((error) => {
@@ -1013,75 +1024,127 @@ var GithubSignals = class extends _mastra_core_signals.SignalProvider {
1013
1024
  threadId: context?.agent?.threadId ?? threadContext.threadId,
1014
1025
  resourceId: context?.agent?.resourceId ?? threadContext.resourceId
1015
1026
  });
1027
+ const prSchema = zod.default.object({
1028
+ number: zod.default.number().int().positive(),
1029
+ owner: zod.default.string().optional(),
1030
+ repo: zod.default.string().optional()
1031
+ });
1032
+ const subscribeSchema = zod.default.object({
1033
+ prs: zod.default.array(prSchema).min(1),
1034
+ mode: zod.default.enum(["working", "review"]).optional()
1035
+ });
1036
+ const unsubscribeSchema = zod.default.object({
1037
+ prs: zod.default.array(prSchema).min(1).optional(),
1038
+ all: zod.default.boolean().optional()
1039
+ }).refine((input) => [!!input.prs, input.all === true].filter(Boolean).length === 1, { message: "Provide exactly one of prs or all." });
1040
+ const dedupePrs = (prs) => {
1041
+ const byKey = /* @__PURE__ */ new Map();
1042
+ for (const pr of prs) byKey.set(`${pr.owner ?? ""}/${pr.repo ?? ""}#${pr.number}`, pr);
1043
+ return [...byKey.values()];
1044
+ };
1045
+ const getSubscribeMessage = (result) => result.terminalState ? `Not subscribed to ${result.owner}/${result.repo}#${result.number} in review mode because it is already ${result.terminalState}.` : result.syncResult?.ok === false ? `Subscribed to ${result.owner}/${result.repo}#${result.number} in ${result.mode} mode, but gitcrawl sync failed: ${result.syncResult.error}` : `Subscribed to ${result.owner}/${result.repo}#${result.number} in ${result.mode} mode.`;
1046
+ const getUnsubscribeMessage = (result) => result.removed ? `Unsubscribed from ${result.owner}/${result.repo}#${result.number}.` : `No GitHub subscription found for ${result.owner}/${result.repo}#${result.number}.`;
1016
1047
  return {
1017
1048
  ...args.tools,
1018
1049
  github_subscribe_pr: createGithubTool({
1019
1050
  id: "github_subscribe_pr",
1020
- description: "Subscribe this thread to a GitHub pull request. Use review mode for new commits, authorized latest PR comments, review-thread-state changes including all threads resolved, and PR close or merge updates. Use working mode for all actionable PR activity. Omitted mode defaults to working. Do not subscribe for a one-off inspection.",
1021
- inputSchema: zod.default.object({
1022
- number: zod.default.number().int().positive(),
1023
- owner: zod.default.string().optional(),
1024
- repo: zod.default.string().optional(),
1025
- mode: zod.default.enum(["working", "review"]).optional()
1026
- }),
1051
+ description: "Subscribe this thread to one or more GitHub pull requests. Use review mode for new commits, authorized latest PR comments, review-thread-state changes including all threads resolved, and PR close or merge updates. Use working mode for all actionable PR activity. Omitted mode defaults to working. Do not subscribe for a one-off inspection.",
1052
+ inputSchema: subscribeSchema,
1027
1053
  execute: async (input, context) => {
1054
+ const subscribeInput = input;
1028
1055
  const executionThreadContext = getExecutionThreadContext(context);
1029
- const result = await this.#subscribe({
1030
- id: `github-tool-subscribe-${(0, crypto.randomUUID)()}`,
1031
- owner: input.owner,
1032
- repo: input.repo,
1033
- number: input.number,
1034
- mode: normalizeGithubSubscriptionMode(input.mode),
1035
- threadId: executionThreadContext.threadId,
1036
- resourceId: executionThreadContext.resourceId
1037
- });
1038
- if (result.terminalState) return {
1039
- subscribed: false,
1040
- mode: result.mode,
1041
- terminalState: result.terminalState,
1042
- reason: "terminal",
1043
- owner: result.owner,
1044
- repo: result.repo,
1045
- number: result.number,
1046
- message: `Not subscribed to ${result.owner}/${result.repo}#${result.number} in review mode because it is already ${result.terminalState}.`
1047
- };
1048
- return {
1049
- subscribed: true,
1050
- mode: result.mode,
1051
- owner: result.owner,
1052
- repo: result.repo,
1053
- number: result.number,
1054
- syncStatus: result.syncResult?.ok === false ? "error" : result.syncResult ? "success" : void 0,
1055
- message: result.syncResult?.ok === false ? `Subscribed to ${result.owner}/${result.repo}#${result.number} in ${result.mode} mode, but gitcrawl sync failed: ${result.syncResult.error}` : `Subscribed to ${result.owner}/${result.repo}#${result.number} in ${result.mode} mode.`
1056
+ const mode = normalizeGithubSubscriptionMode(subscribeInput.mode);
1057
+ const requestedPrs = dedupePrs(subscribeInput.prs);
1058
+ const results = [];
1059
+ for (const pr of requestedPrs) try {
1060
+ const result = await this.#subscribe({
1061
+ id: `github-tool-subscribe-${(0, crypto.randomUUID)()}`,
1062
+ owner: pr.owner,
1063
+ repo: pr.repo,
1064
+ number: pr.number,
1065
+ mode,
1066
+ threadId: executionThreadContext.threadId,
1067
+ resourceId: executionThreadContext.resourceId
1068
+ });
1069
+ results.push({
1070
+ subscribed: !result.terminalState,
1071
+ mode: result.mode ?? mode,
1072
+ owner: result.owner,
1073
+ repo: result.repo,
1074
+ number: result.number,
1075
+ ...result.terminalState ? {
1076
+ terminalState: result.terminalState,
1077
+ reason: "terminal"
1078
+ } : {},
1079
+ syncStatus: result.syncResult?.ok === false ? "error" : result.syncResult ? "success" : void 0,
1080
+ message: getSubscribeMessage(result)
1081
+ });
1082
+ } catch (error) {
1083
+ results.push({
1084
+ subscribed: false,
1085
+ mode,
1086
+ owner: pr.owner ?? "",
1087
+ repo: pr.repo ?? "",
1088
+ number: pr.number,
1089
+ reason: "error",
1090
+ syncStatus: "error",
1091
+ message: `Could not subscribe to PR #${pr.number}: ${error instanceof Error ? error.message : String(error)}`
1092
+ });
1093
+ }
1094
+ const subscriptions = await this.#getSubscriptionSummaries(executionThreadContext).catch(() => []);
1095
+ const response = {
1096
+ subscribed: results.some((result) => result.subscribed),
1097
+ results,
1098
+ subscriptions
1056
1099
  };
1100
+ if (results.length === 1) Object.assign(response, results[0]);
1101
+ return response;
1057
1102
  }
1058
1103
  }),
1059
1104
  github_unsubscribe_pr: createGithubTool({
1060
1105
  id: "github_unsubscribe_pr",
1061
- description: "Unsubscribe this thread from a GitHub pull request.",
1062
- inputSchema: zod.default.object({
1063
- number: zod.default.number().int().positive(),
1064
- owner: zod.default.string().optional(),
1065
- repo: zod.default.string().optional()
1066
- }),
1106
+ description: "Unsubscribe this thread from one or more GitHub pull requests, or unsubscribe all current PRs.",
1107
+ inputSchema: unsubscribeSchema,
1067
1108
  execute: async (input, context) => {
1068
1109
  const executionThreadContext = getExecutionThreadContext(context);
1069
- const result = await this.#unsubscribe({
1070
- id: `github-tool-unsubscribe-${(0, crypto.randomUUID)()}`,
1071
- owner: input.owner,
1072
- repo: input.repo,
1073
- number: input.number,
1074
- threadId: executionThreadContext.threadId,
1075
- resourceId: executionThreadContext.resourceId
1076
- });
1077
- return {
1078
- unsubscribed: result.removed ?? false,
1079
- owner: result.owner,
1080
- repo: result.repo,
1081
- number: result.number,
1082
- remainingSubscriptions: result.remainingSubscriptions,
1083
- message: result.removed ? `Unsubscribed from ${result.owner}/${result.repo}#${result.number}.` : `No GitHub subscription found for ${result.owner}/${result.repo}#${result.number}.`
1110
+ const unsubscribeInput = input;
1111
+ const requestedPrs = unsubscribeInput.all ? await this.#getSubscriptionSummaries(executionThreadContext) : dedupePrs(unsubscribeInput.prs ?? []);
1112
+ const results = [];
1113
+ for (const pr of requestedPrs) try {
1114
+ const result = await this.#unsubscribe({
1115
+ id: `github-tool-unsubscribe-${(0, crypto.randomUUID)()}`,
1116
+ owner: pr.owner,
1117
+ repo: pr.repo,
1118
+ number: pr.number,
1119
+ threadId: executionThreadContext.threadId,
1120
+ resourceId: executionThreadContext.resourceId
1121
+ });
1122
+ results.push({
1123
+ owner: result.owner,
1124
+ repo: result.repo,
1125
+ number: result.number,
1126
+ unsubscribed: result.removed ?? false,
1127
+ message: getUnsubscribeMessage(result)
1128
+ });
1129
+ } catch (error) {
1130
+ results.push({
1131
+ owner: pr.owner ?? "",
1132
+ repo: pr.repo ?? "",
1133
+ number: pr.number,
1134
+ unsubscribed: false,
1135
+ reason: "error",
1136
+ message: `Could not unsubscribe from PR #${pr.number}: ${error instanceof Error ? error.message : String(error)}`
1137
+ });
1138
+ }
1139
+ const subscriptions = await this.#getSubscriptionSummaries(executionThreadContext).catch(() => []);
1140
+ const response = {
1141
+ unsubscribed: results.some((result) => result.unsubscribed),
1142
+ results,
1143
+ subscriptions,
1144
+ remainingSubscriptions: subscriptions.length
1084
1145
  };
1146
+ if (results.length === 1) Object.assign(response, results[0]);
1147
+ return response;
1085
1148
  }
1086
1149
  })
1087
1150
  };
@@ -1120,6 +1183,19 @@ var GithubSignals = class extends _mastra_core_signals.SignalProvider {
1120
1183
  #invalidatePollingThread(key) {
1121
1184
  this.#pollingThreadGenerations.set(key, (this.#pollingThreadGenerations.get(key) ?? 0) + 1);
1122
1185
  }
1186
+ #invalidatePollingForThread(input) {
1187
+ const key = this.#pollingKey(input);
1188
+ this.#invalidatePollingThread(key);
1189
+ const state = this.#polling.get(key);
1190
+ if (!state) return;
1191
+ clearInterval(state.timer);
1192
+ this.#polling.delete(key);
1193
+ this.#notifyPollingChanged({
1194
+ threadId: input.threadId,
1195
+ resourceId: input.resourceId,
1196
+ running: false
1197
+ });
1198
+ }
1123
1199
  #getNotificationAgent(_input) {
1124
1200
  if (this.#agent) return this.#agent;
1125
1201
  const agentId = _input?.agentId ?? this.#options.agentId;
@@ -1129,6 +1205,16 @@ var GithubSignals = class extends _mastra_core_signals.SignalProvider {
1129
1205
  const { loadedThread } = await this.#loadThread(input);
1130
1206
  return getGithubMetadata(loadedThread.metadata).subscriptions;
1131
1207
  }
1208
+ async #getSubscriptionSummaries(input) {
1209
+ return (await this.#getThreadSubscriptions(input)).map((subscription) => ({
1210
+ owner: subscription.owner,
1211
+ repo: subscription.repo,
1212
+ number: subscription.number,
1213
+ subscribedAt: subscription.subscribedAt,
1214
+ updatedAt: subscription.updatedAt,
1215
+ ...subscription.lastSyncStatus ? { lastSyncStatus: subscription.lastSyncStatus } : {}
1216
+ }));
1217
+ }
1132
1218
  #notifySubscriptionsChanged(input) {
1133
1219
  this.#subscriptionsChangedHandler?.(input);
1134
1220
  }
@@ -1224,6 +1310,7 @@ var GithubSignals = class extends _mastra_core_signals.SignalProvider {
1224
1310
  nextSubscription.lastNotificationKind = primaryNotification.kind;
1225
1311
  nextSubscription.lastNotificationPriority = primaryNotification.priority;
1226
1312
  nextSubscription.lastNotificationSummary = primaryNotification.summary;
1313
+ nextSubscription.lastNotificationDedupeKey = primaryNotification.dedupeKey;
1227
1314
  if (!terminalState) shouldKeepSubscription = notifications.every((notification) => notification.kind !== "pull-request-merged");
1228
1315
  }
1229
1316
  }
@@ -1374,6 +1461,10 @@ var GithubSignals = class extends _mastra_core_signals.SignalProvider {
1374
1461
  if (!comments.some((comment) => comment.body || comment.url || comment.updatedAt)) return snapshot;
1375
1462
  for (const comment of comments) {
1376
1463
  if (isCurrentGeneration && !isCurrentGeneration()) return snapshot;
1464
+ if (isNoisyBotComment({
1465
+ author: comment.author,
1466
+ body: comment.body
1467
+ })) continue;
1377
1468
  if (!await this.#isAuthorizedAuthor(owner, repo, comment.author, {
1378
1469
  authorType: comment.authorType,
1379
1470
  isBot: comment.isBot
@@ -1479,15 +1570,20 @@ var GithubSignals = class extends _mastra_core_signals.SignalProvider {
1479
1570
  if (!input.isCurrentGeneration()) return [];
1480
1571
  if (!authorized) continue;
1481
1572
  }
1482
- notificationInputs.push(this.#createGithubNotificationInput({
1573
+ const notificationInput = this.#createGithubNotificationInput({
1483
1574
  subscription: input.subscription,
1484
1575
  snapshot: input.snapshot,
1485
1576
  notification,
1486
1577
  dedupeSuffix: input.snapshot.contentHash ?? input.snapshot.githubUpdatedAt ?? String(Date.now()),
1487
1578
  previousGithubUpdatedAt: input.previousGithubUpdatedAt,
1488
1579
  previousContentHash: input.previousContentHash
1489
- }));
1490
- sent.push(notification);
1580
+ });
1581
+ if (input.subscription.lastNotificationDedupeKey ? input.subscription.lastNotificationDedupeKey === notificationInput.dedupeKey : input.subscription.lastNotificationKind === notification.kind && input.subscription.lastNotificationSummary === notification.summary) continue;
1582
+ notificationInputs.push(notificationInput);
1583
+ sent.push({
1584
+ ...notification,
1585
+ dedupeKey: notificationInput.dedupeKey
1586
+ });
1491
1587
  }
1492
1588
  if (notificationInputs.length > 0) {
1493
1589
  const target = {
@@ -1542,7 +1638,12 @@ var GithubSignals = class extends _mastra_core_signals.SignalProvider {
1542
1638
  ...existing?.lastObservedReviewStateHash ? { lastObservedReviewStateHash: existing.lastObservedReviewStateHash } : {},
1543
1639
  ...existing?.lastObservedCommentUrl ? { lastObservedCommentUrl: existing.lastObservedCommentUrl } : {},
1544
1640
  ...existing?.lastObservedCommentAuthor ? { lastObservedCommentAuthor: existing.lastObservedCommentAuthor } : {},
1545
- ...typeof existing?.lastObservedCommentIsBot === "boolean" ? { lastObservedCommentIsBot: existing.lastObservedCommentIsBot } : {}
1641
+ ...typeof existing?.lastObservedCommentIsBot === "boolean" ? { lastObservedCommentIsBot: existing.lastObservedCommentIsBot } : {},
1642
+ ...existing?.lastNotificationAt ? { lastNotificationAt: existing.lastNotificationAt } : {},
1643
+ ...existing?.lastNotificationKind ? { lastNotificationKind: existing.lastNotificationKind } : {},
1644
+ ...existing?.lastNotificationPriority ? { lastNotificationPriority: existing.lastNotificationPriority } : {},
1645
+ ...existing?.lastNotificationSummary ? { lastNotificationSummary: existing.lastNotificationSummary } : {},
1646
+ ...existing?.lastNotificationDedupeKey ? { lastNotificationDedupeKey: existing.lastNotificationDedupeKey } : {}
1546
1647
  };
1547
1648
  let syncResult;
1548
1649
  let baselineSnapshot;
@@ -1570,8 +1671,12 @@ var GithubSignals = class extends _mastra_core_signals.SignalProvider {
1570
1671
  if (snapshot) applySnapshotCursor(subscription, snapshot);
1571
1672
  } else subscription.lastSyncStatus = "skipped";
1572
1673
  const terminalState = mode === "review" ? getGithubTerminalState(baselineSnapshot) : void 0;
1674
+ const subscriptions = terminalState ? githubMetadata.subscriptions.filter((candidate) => !(candidate.owner === owner && candidate.repo === repo && candidate.number === input.number)) : existingIndex >= 0 ? githubMetadata.subscriptions.map((existingSubscription, index) => index === existingIndex ? subscription : existingSubscription) : [...githubMetadata.subscriptions, subscription];
1573
1675
  if (terminalState) {
1574
- const subscriptions = githubMetadata.subscriptions.filter((candidate) => !(candidate.owner === owner && candidate.repo === repo && candidate.number === input.number));
1676
+ this.#invalidatePollingForThread({
1677
+ threadId: input.threadId,
1678
+ resourceId: input.resourceId
1679
+ });
1575
1680
  await threadStore.saveThread({ thread: {
1576
1681
  ...loadedThread,
1577
1682
  id: input.threadId,
@@ -1589,6 +1694,10 @@ var GithubSignals = class extends _mastra_core_signals.SignalProvider {
1589
1694
  threadId: input.threadId,
1590
1695
  resourceId: input.resourceId
1591
1696
  });
1697
+ else await this.startPollingForThread({
1698
+ threadId: input.threadId,
1699
+ resourceId: input.resourceId
1700
+ });
1592
1701
  return {
1593
1702
  owner,
1594
1703
  repo,
@@ -1598,7 +1707,10 @@ var GithubSignals = class extends _mastra_core_signals.SignalProvider {
1598
1707
  syncResult
1599
1708
  };
1600
1709
  }
1601
- const subscriptions = [subscription];
1710
+ this.#invalidatePollingForThread({
1711
+ threadId: input.threadId,
1712
+ resourceId: input.resourceId
1713
+ });
1602
1714
  await threadStore.saveThread({ thread: {
1603
1715
  ...loadedThread,
1604
1716
  id: input.threadId,
@@ -1638,6 +1750,10 @@ var GithubSignals = class extends _mastra_core_signals.SignalProvider {
1638
1750
  const subscriptions = githubMetadata.subscriptions.filter((subscription) => !(subscription.owner === owner && subscription.repo === repo && subscription.number === input.number));
1639
1751
  const removed = subscriptions.length !== githubMetadata.subscriptions.length;
1640
1752
  if (removed) {
1753
+ this.#invalidatePollingForThread({
1754
+ threadId: input.threadId,
1755
+ resourceId: input.resourceId
1756
+ });
1641
1757
  await threadStore.saveThread({ thread: {
1642
1758
  ...loadedThread,
1643
1759
  id: input.threadId,
@@ -1655,6 +1771,10 @@ var GithubSignals = class extends _mastra_core_signals.SignalProvider {
1655
1771
  threadId: input.threadId,
1656
1772
  resourceId: input.resourceId
1657
1773
  });
1774
+ else await this.startPollingForThread({
1775
+ threadId: input.threadId,
1776
+ resourceId: input.resourceId
1777
+ });
1658
1778
  }
1659
1779
  return {
1660
1780
  owner,