@mastra/github-signals 0.1.0 → 0.1.1-alpha.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.
package/dist/index.d.ts CHANGED
@@ -8,6 +8,7 @@ export declare const GITHUB_SUBSCRIBE_PR_TAG = "github-subscribe-pr";
8
8
  export declare const GITHUB_UNSUBSCRIBE_PR_TAG = "github-unsubscribe-pr";
9
9
  export declare const GITHUB_SYNC_STATUS_TAG = "github-sync-status";
10
10
  export declare const GITHUB_SIGNALS_METADATA_KEY = "githubSignals";
11
+ export type GithubPermission = 'admin' | 'maintain' | 'write' | 'triage' | 'read' | 'none';
11
12
  export type GithubPRSubscription = {
12
13
  owner: string;
13
14
  repo: string;
@@ -64,6 +65,14 @@ export type GithubPullRequestCheckSnapshot = {
64
65
  detailsUrl?: string;
65
66
  updatedAt?: string;
66
67
  };
68
+ export type GithubPullRequestCommentSnapshot = {
69
+ author?: string;
70
+ authorType?: string;
71
+ isBot?: boolean;
72
+ body?: string;
73
+ url?: string;
74
+ updatedAt?: string;
75
+ };
67
76
  type GithubPullRequestCheckInput = GithubPullRequestCheckSnapshot & {
68
77
  source: 'check' | 'workflow';
69
78
  };
@@ -87,6 +96,11 @@ export type GithubPullRequestSnapshot = {
87
96
  latestCommentAuthor?: string;
88
97
  latestCommentAuthorType?: string;
89
98
  latestCommentIsBot?: boolean;
99
+ latestCommentBody?: string;
100
+ latestCommentUrl?: string;
101
+ latestCommentUpdatedAt?: string;
102
+ /** Recent comments newest-first, used to fall back when the latest comment is unauthorized noise. */
103
+ latestComments?: GithubPullRequestCommentSnapshot[];
90
104
  };
91
105
  export type GithubSignalsSyncClient = {
92
106
  syncPullRequest(input: GithubSignalsSyncInput): Promise<GithubSignalsSyncResult>;
@@ -111,6 +125,9 @@ export type GithubSignalsThreadStore = {
111
125
  thread: StorageThreadType;
112
126
  }): Promise<StorageThreadType>;
113
127
  };
128
+ export type GithubPermissionResolver = {
129
+ getPermission(owner: string, repo: string, user: string): Promise<GithubPermission | undefined>;
130
+ };
114
131
  export type GithubSignalsOptions = {
115
132
  owner?: string;
116
133
  repo?: string;
@@ -123,18 +140,32 @@ export type GithubSignalsOptions = {
123
140
  repositoryResolver?: GithubRepositoryResolver;
124
141
  threadStore?: GithubSignalsThreadStore;
125
142
  getNotificationStreamOptions?: GithubSignalAgentOptions['getNotificationStreamOptions'];
143
+ /** Permissions that authorize a human commenter to trigger notifications (default: admin, maintain, write). */
144
+ authorizedPermissions?: GithubPermission[];
145
+ /** Bot logins authorized to trigger notifications (default: coderabbitai[bot], devin-ai-integration[bot]). */
146
+ authorizedBots?: string[];
147
+ /** Bot logins whose comments should be ignored and NOT trigger notifications. */
148
+ ignoredBots?: string[];
149
+ /** Custom resolver for looking up collaborator permissions (default: gh api). */
150
+ permissionResolver?: GithubPermissionResolver;
126
151
  };
127
152
  export type GithubSubscriptionsChangedEvent = {
128
153
  threadId: string;
129
154
  resourceId: string;
130
155
  subscriptions: GithubPRSubscription[];
131
156
  };
157
+ export type GithubPollingChangedEvent = {
158
+ threadId: string;
159
+ resourceId: string;
160
+ running: boolean;
161
+ };
132
162
  type GithubSubscriptionsChangedHandler = (event: GithubSubscriptionsChangedEvent) => void;
163
+ type GithubPollingChangedHandler = (event: GithubPollingChangedEvent) => void;
133
164
  type GithubSignalAgent = {
134
165
  sendSignal(signal: AgentSignalInput, target: unknown): {
135
166
  accepted: unknown;
136
167
  };
137
- sendNotificationSignal?(notification: unknown, target: unknown): {
168
+ sendNotificationSignal?(notification: unknown | unknown[], target: unknown): {
138
169
  accepted?: unknown;
139
170
  } | Promise<unknown>;
140
171
  };
@@ -200,6 +231,7 @@ export declare class GithubSignals extends SignalProvider<'github-signals'> {
200
231
  getInputProcessors(): InputProcessorOrWorkflow[];
201
232
  getOutputProcessors(): OutputProcessorOrWorkflow[];
202
233
  onSubscriptionsChanged(handler: GithubSubscriptionsChangedHandler): void;
234
+ onPollingChanged(handler: GithubPollingChangedHandler): void;
203
235
  __registerMastra(mastra: Mastra<any, any, any, any, any, any, any, any, any, any>): void;
204
236
  syncThreadNow(input: GithubPollingThread): Promise<number>;
205
237
  subscribeThreadToPR(input: GithubPollingThread & {
@@ -213,6 +245,7 @@ export declare class GithubSignals extends SignalProvider<'github-signals'> {
213
245
  }): Promise<boolean>;
214
246
  stopPollingForThread(input: GithubPollingThread): void;
215
247
  isPollingThread(input: GithubPollingThread): boolean;
248
+ isPollingThreadRunning(input: GithubPollingThread): boolean;
216
249
  getPollIntervalMs(): number;
217
250
  stopAllPolling(): void;
218
251
  pollThreadNow(input: GithubPollingThread): Promise<number>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -20,6 +20,10 @@ var GITHUB_SUBSCRIBE_PR_TAG = "github-subscribe-pr";
20
20
  var GITHUB_UNSUBSCRIBE_PR_TAG = "github-unsubscribe-pr";
21
21
  var GITHUB_SYNC_STATUS_TAG = "github-sync-status";
22
22
  var GITHUB_SIGNALS_METADATA_KEY = "githubSignals";
23
+ var DEFAULT_AUTHORIZED_PERMISSIONS = ["admin", "maintain", "write"];
24
+ var DEFAULT_AUTHORIZED_BOTS = ["coderabbitai[bot]", "devin-ai-integration[bot]"];
25
+ var PERMISSION_CACHE_TTL_MS = 5 * 60 * 1e3;
26
+ var AUTHOR_GATED_NOTIFICATION_KINDS = /* @__PURE__ */ new Set(["pull-request-activity", "pull-request-review-activity"]);
23
27
  var createGithubTool = createTool;
24
28
  function isPlainObject(value) {
25
29
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -140,6 +144,36 @@ function getPrLabel(subscription, snapshot) {
140
144
  function getMergedNotificationSummary(label) {
141
145
  return `${label} was merged. This thread has been automatically unsubscribed from this PR. Resubscribe if you still need updates.`;
142
146
  }
147
+ function getCommentExcerpt(body) {
148
+ const excerpt = body.replace(/\s+/g, " ").trim();
149
+ return excerpt.length > 240 ? `${excerpt.slice(0, 237)}...` : excerpt;
150
+ }
151
+ function getCommentNotificationSummary(pr, snapshot) {
152
+ if (!snapshot.latestCommentAuthor || !snapshot.latestCommentBody) return void 0;
153
+ return `${snapshot.latestCommentAuthor} commented on ${pr}: ${getCommentExcerpt(snapshot.latestCommentBody)}`;
154
+ }
155
+ var githubActivityNotificationPriority = {
156
+ high: 0,
157
+ medium: 1
158
+ };
159
+ function getGithubActivityNotificationRank(notification) {
160
+ return notification.kind === "pull-request-activity" ? 0 : 1;
161
+ }
162
+ function compareGithubActivityNotifications(a, b) {
163
+ if (!a && !b) return 0;
164
+ if (!a) return 1;
165
+ if (!b) return -1;
166
+ const priorityComparison = githubActivityNotificationPriority[a.priority] - githubActivityNotificationPriority[b.priority];
167
+ if (priorityComparison !== 0) return priorityComparison;
168
+ return getGithubActivityNotificationRank(a) - getGithubActivityNotificationRank(b);
169
+ }
170
+ function classifyGithubCommentActivityNotification(input) {
171
+ if (isBotOnlyActivity(input.snapshot)) return void 0;
172
+ const pr = `${input.subscription.owner}/${input.subscription.repo}#${input.subscription.number}`;
173
+ const summary = getCommentNotificationSummary(pr, input.snapshot);
174
+ if (!summary) return void 0;
175
+ return { kind: "pull-request-activity", priority: "high", summary };
176
+ }
143
177
  function getCheckUpdatedTime(check) {
144
178
  const value = check.updatedAt ? Date.parse(check.updatedAt) : Number.NaN;
145
179
  return Number.isFinite(value) ? value : 0;
@@ -263,10 +297,11 @@ function classifyGithubActivityNotification(input) {
263
297
  }
264
298
  if (input.snapshot.ciState === "pending" && input.subscription.lastObservedCiState === "pending") return void 0;
265
299
  if (isBotOnlyActivity(input.snapshot)) return void 0;
300
+ const commentSummary = getCommentNotificationSummary(pr, input.snapshot);
266
301
  return {
267
302
  kind: "pull-request-activity",
268
- priority: "medium",
269
- summary: `${pr} has new activity${input.snapshot.title ? `: ${input.snapshot.title}` : ""}`
303
+ priority: commentSummary ? "high" : "medium",
304
+ summary: commentSummary ?? `${pr} has new activity${input.snapshot.title ? `: ${input.snapshot.title}` : ""}`
270
305
  };
271
306
  }
272
307
  function classifyGithubBaselineNotification(input) {
@@ -391,13 +426,15 @@ var GitcrawlSyncClient = class {
391
426
  join threads t on t.id=rt.thread_id
392
427
  join repositories r on r.id=t.repo_id
393
428
  where r.owner=${owner} and r.name=${repo} and t.number=${number} and rt.is_resolved=0`);
394
- const [latestComment] = await queryGitcrawlDb(`select c.author_login, c.author_type, c.is_bot
429
+ const latestComments = await queryGitcrawlDb(`select c.author_login, c.author_type, c.is_bot, c.body, json_extract(c.raw_json, '$.html_url') as html_url,
430
+ coalesce(c.updated_at_gh, c.created_at_gh) as updated_at
395
431
  from comments c
396
432
  join threads t on t.id=c.thread_id
397
433
  join repositories r on r.id=t.repo_id
398
434
  where r.owner=${owner} and r.name=${repo} and t.number=${number}
399
435
  order by coalesce(c.updated_at_gh, c.created_at_gh) desc
400
- limit 1`);
436
+ limit 20`);
437
+ const latestComment = latestComments[0];
401
438
  const checks = normalizeGithubChecksForSnapshot({
402
439
  checkRows: checkRows.map((row) => ({
403
440
  source: "check",
@@ -459,7 +496,18 @@ var GitcrawlSyncClient = class {
459
496
  latestReviewThreadAt: readString(reviewState?.latest_review_thread_at),
460
497
  latestCommentAuthor: readString(latestComment?.author_login),
461
498
  latestCommentAuthorType: readString(latestComment?.author_type),
462
- latestCommentIsBot: latestComment?.is_bot === 1
499
+ latestCommentIsBot: latestComment?.is_bot === 1,
500
+ latestCommentBody: readString(latestComment?.body),
501
+ latestCommentUrl: readString(latestComment?.html_url),
502
+ latestCommentUpdatedAt: readString(latestComment?.updated_at),
503
+ latestComments: latestComments.map((comment) => ({
504
+ author: readString(comment.author_login),
505
+ authorType: readString(comment.author_type),
506
+ isBot: comment.is_bot === 1,
507
+ body: readString(comment.body),
508
+ url: readString(comment.html_url),
509
+ updatedAt: readString(comment.updated_at)
510
+ }))
463
511
  };
464
512
  } catch {
465
513
  return void 0;
@@ -514,9 +562,11 @@ var GithubSignals = class extends SignalProvider {
514
562
  #syncClient;
515
563
  #repositoryResolver;
516
564
  #polling = /* @__PURE__ */ new Map();
565
+ #permissionCache = /* @__PURE__ */ new Map();
517
566
  #agent;
518
567
  #agentOptions = {};
519
568
  #subscriptionsChangedHandler;
569
+ #pollingChangedHandler;
520
570
  constructor(options = {}) {
521
571
  super();
522
572
  this.#options = options;
@@ -551,6 +601,9 @@ var GithubSignals = class extends SignalProvider {
551
601
  onSubscriptionsChanged(handler) {
552
602
  this.#subscriptionsChangedHandler = handler;
553
603
  }
604
+ onPollingChanged(handler) {
605
+ this.#pollingChangedHandler = handler;
606
+ }
554
607
  __registerMastra(mastra) {
555
608
  super.__registerMastra(mastra);
556
609
  this.#ghMastra = mastra;
@@ -589,15 +642,13 @@ var GithubSignals = class extends SignalProvider {
589
642
  this.#polling.delete(pollingKey);
590
643
  }
591
644
  if (this.#polling.has(key)) return true;
592
- let scheduledPollCount = options.pollImmediately ? 1 : 0;
593
645
  const runPoll = (pollOptions = {}) => {
594
646
  void this.#pollThread(input, pollOptions).catch((error) => {
595
647
  console.warn("GitHub PR polling failed:", error);
596
648
  });
597
649
  };
598
650
  const timer = setInterval(() => {
599
- scheduledPollCount += 1;
600
- runPoll({ includeComments: scheduledPollCount % 2 === 1 });
651
+ runPoll({ includeComments: true });
601
652
  }, this.#options.pollIntervalMs ?? 3e5);
602
653
  if (options.pollImmediately) runPoll({ includeComments: true });
603
654
  timer.unref?.();
@@ -614,6 +665,9 @@ var GithubSignals = class extends SignalProvider {
614
665
  isPollingThread(input) {
615
666
  return this.#polling.has(this.#pollingKey(input));
616
667
  }
668
+ isPollingThreadRunning(input) {
669
+ return this.#polling.get(this.#pollingKey(input))?.running ?? false;
670
+ }
617
671
  getPollIntervalMs() {
618
672
  return this.#options.pollIntervalMs ?? 3e5;
619
673
  }
@@ -799,6 +853,9 @@ var GithubSignals = class extends SignalProvider {
799
853
  #notifySubscriptionsChanged(input) {
800
854
  this.#subscriptionsChangedHandler?.(input);
801
855
  }
856
+ #notifyPollingChanged(input) {
857
+ this.#pollingChangedHandler?.(input);
858
+ }
802
859
  async #pollThread(input, options = {}) {
803
860
  const key = this.#pollingKey(input);
804
861
  const state = this.#polling.get(key);
@@ -806,6 +863,7 @@ var GithubSignals = class extends SignalProvider {
806
863
  return 0;
807
864
  }
808
865
  if (state) state.running = true;
866
+ this.#notifyPollingChanged({ threadId: input.threadId, resourceId: input.resourceId, running: true });
809
867
  try {
810
868
  const { threadStore, loadedThread } = await this.#loadThread(input);
811
869
  const githubMetadata = getGithubMetadata(loadedThread.metadata);
@@ -824,7 +882,9 @@ var GithubSignals = class extends SignalProvider {
824
882
  includeComments: options.includeComments
825
883
  };
826
884
  const syncResult = await this.#syncClient.syncPullRequest(syncInput);
827
- const snapshot = syncResult.ok ? await this.#syncClient.getPullRequestSnapshot?.(syncInput) : void 0;
885
+ let snapshot = syncResult.ok ? await this.#syncClient.getPullRequestSnapshot?.(syncInput) : void 0;
886
+ if (snapshot)
887
+ snapshot = await this.#filterUnauthorizedLatestComment(subscription.owner, subscription.repo, snapshot);
828
888
  const nextSubscription = {
829
889
  ...subscription,
830
890
  updatedAt: now,
@@ -837,25 +897,28 @@ var GithubSignals = class extends SignalProvider {
837
897
  const previousContentHash = subscription.lastObservedContentHash;
838
898
  const previousThreadContentHash = subscription.lastObservedThreadContentHash;
839
899
  const previousHeadSha = subscription.lastObservedHeadSha;
900
+ const latestCommentChanged = !!previousGithubUpdatedAt && !!snapshot?.latestCommentUpdatedAt && Date.parse(snapshot.latestCommentUpdatedAt) > Date.parse(previousGithubUpdatedAt);
840
901
  if (snapshot) applySnapshotCursor(nextSubscription, snapshot);
841
902
  const isFirstObservation = syncResult.ok && snapshot && !previousGithubUpdatedAt && !previousContentHash;
842
903
  const legacyAggregateChanged = previousContentHash && snapshot?.contentHash && previousContentHash !== snapshot.contentHash && !previousThreadContentHash && !previousHeadSha;
843
- const changed = isFirstObservation || syncResult.ok && snapshot && (legacyAggregateChanged || previousThreadContentHash && snapshot.threadContentHash && previousThreadContentHash !== snapshot.threadContentHash || previousHeadSha && snapshot.headSha && previousHeadSha !== snapshot.headSha || subscription.lastObservedState && snapshot.state && subscription.lastObservedState !== snapshot.state || subscription.lastObservedMergeableState && snapshot.mergeableState && subscription.lastObservedMergeableState !== snapshot.mergeableState || subscription.lastObservedCiState && snapshot.ciState && subscription.lastObservedCiState !== snapshot.ciState || subscription.lastObservedReviewStateHash && snapshot.reviewStateHash && subscription.lastObservedReviewStateHash !== snapshot.reviewStateHash);
904
+ const changed = isFirstObservation || syncResult.ok && snapshot && (legacyAggregateChanged || latestCommentChanged || previousThreadContentHash && snapshot.threadContentHash && previousThreadContentHash !== snapshot.threadContentHash || previousHeadSha && snapshot.headSha && previousHeadSha !== snapshot.headSha || subscription.lastObservedState && snapshot.state && subscription.lastObservedState !== snapshot.state || subscription.lastObservedMergeableState && snapshot.mergeableState && subscription.lastObservedMergeableState !== snapshot.mergeableState || subscription.lastObservedCiState && snapshot.ciState && subscription.lastObservedCiState !== snapshot.ciState || subscription.lastObservedReviewStateHash && snapshot.reviewStateHash && subscription.lastObservedReviewStateHash !== snapshot.reviewStateHash);
844
905
  let shouldKeepSubscription = true;
845
- if (changed) {
846
- const notification = await this.#sendActivityNotification({
906
+ if (changed && snapshot) {
907
+ const notifications = await this.#sendActivityNotifications({
847
908
  polling: input,
848
909
  subscription,
849
910
  snapshot,
850
911
  previousGithubUpdatedAt,
851
- previousContentHash
912
+ previousContentHash,
913
+ latestCommentChanged
852
914
  });
853
- if (notification) {
915
+ const primaryNotification = notifications[0];
916
+ if (primaryNotification) {
854
917
  nextSubscription.lastNotificationAt = now;
855
- nextSubscription.lastNotificationKind = notification.kind;
856
- nextSubscription.lastNotificationPriority = notification.priority;
857
- nextSubscription.lastNotificationSummary = notification.summary;
858
- shouldKeepSubscription = notification.kind !== "pull-request-merged";
918
+ nextSubscription.lastNotificationKind = primaryNotification.kind;
919
+ nextSubscription.lastNotificationPriority = primaryNotification.priority;
920
+ nextSubscription.lastNotificationSummary = primaryNotification.summary;
921
+ shouldKeepSubscription = notifications.every((notification) => notification.kind !== "pull-request-merged");
859
922
  }
860
923
  }
861
924
  if (shouldKeepSubscription) subscriptions.push(nextSubscription);
@@ -878,17 +941,20 @@ var GithubSignals = class extends SignalProvider {
878
941
  } finally {
879
942
  const latestState = this.#polling.get(key);
880
943
  if (latestState) latestState.running = false;
944
+ this.#notifyPollingChanged({ threadId: input.threadId, resourceId: input.resourceId, running: false });
881
945
  }
882
946
  }
883
- async #sendGithubNotification(input) {
947
+ #createGithubNotificationInput(input) {
884
948
  const failingChecks = getFailingChecks(input.snapshot);
885
949
  const pendingChecks = getPendingChecks(input.snapshot);
950
+ const latestCommentExcerpt = input.snapshot.latestCommentBody ? getCommentExcerpt(input.snapshot.latestCommentBody) : void 0;
951
+ const latestCommentDedupeSuffix = input.notification.kind === "pull-request-activity" && input.snapshot.latestCommentUrl ? `comment:${input.snapshot.latestCommentUrl}:${input.snapshot.latestCommentUpdatedAt ?? ""}` : input.dedupeSuffix;
886
952
  const notificationInput = {
887
953
  source: "github",
888
954
  kind: input.notification.kind,
889
955
  priority: input.notification.priority,
890
956
  summary: input.notification.summary,
891
- dedupeKey: `github:${input.subscription.owner}/${input.subscription.repo}#${input.subscription.number}:${input.dedupeSuffix}`,
957
+ dedupeKey: `github:${input.subscription.owner}/${input.subscription.repo}#${input.subscription.number}:${latestCommentDedupeSuffix}`,
892
958
  coalesceKey: `github:${input.subscription.owner}/${input.subscription.repo}#${input.subscription.number}:${input.notification.kind}`,
893
959
  attributes: {
894
960
  owner: input.subscription.owner,
@@ -902,6 +968,10 @@ var GithubSignals = class extends SignalProvider {
902
968
  ...input.snapshot.mergeableState ? { mergeableState: input.snapshot.mergeableState } : {},
903
969
  ...input.snapshot.ciState ? { ciState: input.snapshot.ciState } : {},
904
970
  ...input.snapshot.unresolvedReviewThreads !== void 0 ? { unresolvedReviewThreads: input.snapshot.unresolvedReviewThreads } : {},
971
+ ...input.snapshot.latestCommentAuthor ? { latestCommentAuthor: input.snapshot.latestCommentAuthor } : {},
972
+ ...latestCommentExcerpt ? { latestCommentExcerpt } : {},
973
+ ...input.snapshot.latestCommentUrl ? { latestCommentUrl: input.snapshot.latestCommentUrl } : {},
974
+ ...input.snapshot.latestCommentUpdatedAt ? { latestCommentUpdatedAt: input.snapshot.latestCommentUpdatedAt } : {},
905
975
  ...failingChecks.length > 0 ? { failingChecks: failingChecks.map((check) => check.name).join(", ") } : {},
906
976
  ...pendingChecks.length > 0 ? { pendingChecks: pendingChecks.map((check) => check.name).join(", ") } : {}
907
977
  },
@@ -930,11 +1000,19 @@ var GithubSignals = class extends SignalProvider {
930
1000
  latestCommentAuthor: input.snapshot.latestCommentAuthor,
931
1001
  latestCommentAuthorType: input.snapshot.latestCommentAuthorType,
932
1002
  latestCommentIsBot: input.snapshot.latestCommentIsBot,
1003
+ latestCommentBody: input.snapshot.latestCommentBody,
1004
+ latestCommentExcerpt,
1005
+ latestCommentUrl: input.snapshot.latestCommentUrl,
1006
+ latestCommentUpdatedAt: input.snapshot.latestCommentUpdatedAt,
933
1007
  failingChecks,
934
1008
  pendingChecks
935
1009
  }
936
1010
  }
937
1011
  };
1012
+ return notificationInput;
1013
+ }
1014
+ async #sendGithubNotification(input) {
1015
+ const notificationInput = this.#createGithubNotificationInput(input);
938
1016
  const streamOptions = await this.#agentOptions.getNotificationStreamOptions?.(input.target);
939
1017
  await input.agent?.sendNotificationSignal?.(
940
1018
  notificationInput,
@@ -953,25 +1031,144 @@ var GithubSignals = class extends SignalProvider {
953
1031
  dedupeSuffix: `baseline:${input.subscription.lastSubscribeSignalId}`
954
1032
  });
955
1033
  }
956
- async #sendActivityNotification(input) {
1034
+ async #isAuthorizedAuthor(owner, repo, user, metadata = {}) {
1035
+ if (!user) return false;
1036
+ const normalizedUser = user.toLowerCase();
1037
+ const isBot = metadata.isBot === true || metadata.authorType?.toLowerCase() === "bot" || normalizedUser.endsWith("[bot]");
1038
+ if (isBot) {
1039
+ const ignoredBots = this.#options.ignoredBots ?? [];
1040
+ if (ignoredBots.some((bot) => bot.toLowerCase() === normalizedUser)) return false;
1041
+ const authorizedBots = this.#options.authorizedBots ?? DEFAULT_AUTHORIZED_BOTS;
1042
+ return authorizedBots.some((bot) => bot.toLowerCase() === normalizedUser);
1043
+ }
1044
+ const permission = await this.#loadAuthorPermission(owner, repo, user);
1045
+ const authorizedPermissions = this.#options.authorizedPermissions ?? DEFAULT_AUTHORIZED_PERMISSIONS;
1046
+ return !!permission && authorizedPermissions.includes(permission);
1047
+ }
1048
+ async #filterUnauthorizedLatestComment(owner, repo, snapshot) {
1049
+ const comments = snapshot.latestComments?.length ? snapshot.latestComments : [
1050
+ {
1051
+ author: snapshot.latestCommentAuthor,
1052
+ authorType: snapshot.latestCommentAuthorType,
1053
+ isBot: snapshot.latestCommentIsBot,
1054
+ body: snapshot.latestCommentBody,
1055
+ url: snapshot.latestCommentUrl,
1056
+ updatedAt: snapshot.latestCommentUpdatedAt
1057
+ }
1058
+ ];
1059
+ if (!comments.some((comment) => comment.author)) return snapshot;
1060
+ if (!comments.some((comment) => comment.body || comment.url || comment.updatedAt)) return snapshot;
1061
+ for (const comment of comments) {
1062
+ if (!await this.#isAuthorizedAuthor(owner, repo, comment.author, {
1063
+ authorType: comment.authorType,
1064
+ isBot: comment.isBot
1065
+ })) {
1066
+ continue;
1067
+ }
1068
+ return {
1069
+ ...snapshot,
1070
+ latestCommentAuthor: comment.author,
1071
+ latestCommentAuthorType: comment.authorType,
1072
+ latestCommentIsBot: comment.isBot,
1073
+ latestCommentBody: comment.body,
1074
+ latestCommentUrl: comment.url,
1075
+ latestCommentUpdatedAt: comment.updatedAt
1076
+ };
1077
+ }
1078
+ return {
1079
+ ...snapshot,
1080
+ latestCommentAuthor: void 0,
1081
+ latestCommentAuthorType: void 0,
1082
+ latestCommentIsBot: void 0,
1083
+ latestCommentBody: void 0,
1084
+ latestCommentUrl: void 0,
1085
+ latestCommentUpdatedAt: void 0
1086
+ };
1087
+ }
1088
+ async #loadAuthorPermission(owner, repo, user) {
1089
+ const cacheKey = `${owner}/${repo}:${user.toLowerCase()}`;
1090
+ const cached = this.#permissionCache.get(cacheKey);
1091
+ if (cached && cached.expiresAt > Date.now()) return cached.permission;
1092
+ if (cached) this.#permissionCache.delete(cacheKey);
1093
+ try {
1094
+ let permission;
1095
+ if (this.#options.permissionResolver) {
1096
+ permission = await this.#options.permissionResolver.getPermission(owner, repo, user);
1097
+ } else {
1098
+ const { stdout } = await execFileAsync("gh", [
1099
+ "api",
1100
+ `repos/${owner}/${repo}/collaborators/${user}/permission`,
1101
+ "--jq",
1102
+ ".permission"
1103
+ ]);
1104
+ const raw = stdout.trim();
1105
+ permission = ["admin", "maintain", "write", "triage", "read", "none"].includes(
1106
+ raw
1107
+ ) ? raw : void 0;
1108
+ }
1109
+ if (permission) {
1110
+ this.#permissionCache.set(cacheKey, { permission, expiresAt: Date.now() + PERMISSION_CACHE_TTL_MS });
1111
+ }
1112
+ return permission;
1113
+ } catch {
1114
+ this.#permissionCache.delete(cacheKey);
1115
+ return void 0;
1116
+ }
1117
+ }
1118
+ async #sendActivityNotifications(input) {
957
1119
  const agent = this.#getNotificationAgent(input.polling);
958
- if (!agent?.sendNotificationSignal) return void 0;
959
- const notification = classifyGithubActivityNotification({
960
- subscription: input.subscription,
961
- snapshot: input.snapshot
962
- });
963
- if (!notification) return void 0;
964
- await this.#sendGithubNotification({
965
- agent,
966
- subscription: input.subscription,
967
- snapshot: input.snapshot,
968
- notification,
969
- target: { resourceId: input.polling.resourceId, threadId: input.polling.threadId },
970
- dedupeSuffix: input.snapshot.contentHash ?? input.snapshot.githubUpdatedAt ?? String(Date.now()),
971
- previousGithubUpdatedAt: input.previousGithubUpdatedAt,
972
- previousContentHash: input.previousContentHash
973
- });
974
- return notification;
1120
+ if (!agent?.sendNotificationSignal) return [];
1121
+ const notifications = [
1122
+ classifyGithubActivityNotification({
1123
+ subscription: input.subscription,
1124
+ snapshot: input.snapshot
1125
+ })
1126
+ ];
1127
+ if (input.latestCommentChanged && notifications[0]?.kind !== "pull-request-activity") {
1128
+ notifications.push(
1129
+ classifyGithubCommentActivityNotification({
1130
+ subscription: input.subscription,
1131
+ snapshot: input.snapshot
1132
+ })
1133
+ );
1134
+ }
1135
+ const sent = [];
1136
+ const notificationInputs = [];
1137
+ for (const notification of notifications.sort(compareGithubActivityNotifications)) {
1138
+ if (!notification) continue;
1139
+ if (AUTHOR_GATED_NOTIFICATION_KINDS.has(notification.kind)) {
1140
+ const authorized = await this.#isAuthorizedAuthor(
1141
+ input.subscription.owner,
1142
+ input.subscription.repo,
1143
+ input.snapshot.latestCommentAuthor,
1144
+ {
1145
+ authorType: input.snapshot.latestCommentAuthorType,
1146
+ isBot: input.snapshot.latestCommentIsBot
1147
+ }
1148
+ );
1149
+ if (!authorized) continue;
1150
+ }
1151
+ notificationInputs.push(
1152
+ this.#createGithubNotificationInput({
1153
+ subscription: input.subscription,
1154
+ snapshot: input.snapshot,
1155
+ notification,
1156
+ dedupeSuffix: input.snapshot.contentHash ?? input.snapshot.githubUpdatedAt ?? String(Date.now()),
1157
+ previousGithubUpdatedAt: input.previousGithubUpdatedAt,
1158
+ previousContentHash: input.previousContentHash
1159
+ })
1160
+ );
1161
+ sent.push(notification);
1162
+ }
1163
+ if (notificationInputs.length > 0) {
1164
+ const target = { resourceId: input.polling.resourceId, threadId: input.polling.threadId };
1165
+ const streamOptions = await this.#agentOptions.getNotificationStreamOptions?.(target);
1166
+ await agent.sendNotificationSignal(
1167
+ notificationInputs,
1168
+ streamOptions ? { ...target, ifIdle: { streamOptions } } : target
1169
+ );
1170
+ }
1171
+ return sent;
975
1172
  }
976
1173
  async #subscribe(input) {
977
1174
  const { owner, repo } = await this.#resolveRepository(input);