opencode-forgekeeper 2.1.1 → 2.2.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.
Files changed (4) hide show
  1. package/README.md +34 -14
  2. package/dist/index.js +376 -44
  3. package/dist/tui.js +429 -200
  4. package/package.json +1 -1
package/dist/tui.js CHANGED
@@ -73,14 +73,182 @@ class ForgeError extends Error {
73
73
  var query = (text) => text;
74
74
  var typed = (transport) => async (host, query2, variables) => await transport(host, query2, variables);
75
75
 
76
- // packages/forgekeeper/src/gitlab-feedback.ts
76
+ // packages/forgekeeper/src/github-feedback.ts
77
77
  var PAGE_SIZE = 100;
78
78
  var MAX_COMMENT_PAGES = 20;
79
+ var MAX_FETCH_REQUESTS = 200;
80
+ var author = "author { __typename login ... on User { id } ... on Bot { id } ... on Mannequin { id } }";
81
+ var page = "pageInfo { hasPreviousPage startCursor }";
82
+ var INLINE_FIELDS = `id url state createdAt publishedAt lastEditedAt isMinimized ${author}`;
83
+ var listQuery = (field, connection) => query(`query($owner: String!, $repo: String!, $number: Int!, $before: String) {
84
+ viewer { id }
85
+ repository(owner: $owner, name: $repo) {
86
+ pullRequest(number: $number) {
87
+ ${field}(last: ${PAGE_SIZE}, before: $before) { ${page} nodes { ${connection} } }
88
+ }
89
+ }
90
+ }`);
91
+ var ISSUE_COMMENTS_QUERY = listQuery("comments", `id url createdAt publishedAt lastEditedAt isMinimized ${author}`);
92
+ var REVIEWS_QUERY = listQuery("reviews", `id url state body submittedAt lastEditedAt isMinimized ${author}`);
93
+ var THREADS_QUERY = listQuery("reviewThreads", `id isResolved comments(last: ${PAGE_SIZE}) { ${page} nodes { ${INLINE_FIELDS} } }`);
94
+ var THREAD_COMMENTS_QUERY = query(`query($id: ID!, $before: String) {
95
+ node(id: $id) {
96
+ ... on PullRequestReviewThread {
97
+ comments(last: ${PAGE_SIZE}, before: $before) { ${page} nodes { ${INLINE_FIELDS} } }
98
+ }
99
+ }
100
+ }`);
101
+ var REVIEW_STATES = new Set(["COMMENTED", "CHANGES_REQUESTED", "APPROVED"]);
102
+ var time = (...values) => {
103
+ const value = values.find((candidate) => candidate);
104
+ return value ? Date.parse(value) : NaN;
105
+ };
106
+ var activity = (lastEditedAt, postedAt) => {
107
+ const edited = lastEditedAt ? Date.parse(lastEditedAt) : NaN;
108
+ return Number.isFinite(edited) ? Math.max(edited, postedAt) : postedAt;
109
+ };
110
+ function build({ node, postedAt, editedAt, resolved }) {
111
+ if (node.isMinimized || !node.author?.id || !Number.isFinite(postedAt) || !Number.isFinite(editedAt))
112
+ return;
113
+ const { __typename, login } = node.author;
114
+ return {
115
+ id: node.id,
116
+ order: postedAt,
117
+ url: node.url ?? "",
118
+ editedAt,
119
+ resolved,
120
+ bot: __typename === "Bot" || login.endsWith("[bot]"),
121
+ authorID: node.author.id,
122
+ username: login
123
+ };
124
+ }
125
+ function toIssueComment(node) {
126
+ const postedAt = time(node.publishedAt, node.createdAt);
127
+ return build({
128
+ node,
129
+ postedAt,
130
+ editedAt: activity(node.lastEditedAt, postedAt),
131
+ resolved: false
132
+ });
133
+ }
134
+ function toReview(node) {
135
+ if (!REVIEW_STATES.has(node.state) || !node.body.trim())
136
+ return;
137
+ const postedAt = time(node.submittedAt);
138
+ return build({
139
+ node,
140
+ postedAt,
141
+ editedAt: activity(node.lastEditedAt, postedAt),
142
+ resolved: false
143
+ });
144
+ }
145
+ function toInlineComment(node, resolved) {
146
+ if (node.state === "PENDING")
147
+ return;
148
+ const postedAt = time(node.publishedAt, node.createdAt);
149
+ return build({
150
+ node,
151
+ postedAt,
152
+ editedAt: activity(node.lastEditedAt, postedAt),
153
+ resolved
154
+ });
155
+ }
156
+ var commentWindow = { pages: MAX_COMMENT_PAGES, completeAtLimit: true };
157
+ var allThreads = { pages: MAX_FETCH_REQUESTS, completeAtLimit: false };
158
+ async function readList(graphql, host, base, text, field, limit = commentWindow) {
159
+ const pages = [];
160
+ let viewer;
161
+ let before;
162
+ const result = (complete) => ({
163
+ items: pages.toReversed().flat(),
164
+ viewer,
165
+ complete
166
+ });
167
+ for (let count = 0;count < limit.pages; count++) {
168
+ const variables = before ? { ...base, before } : base;
169
+ const data = await graphql(host, text, variables);
170
+ viewer ??= data.viewer?.id ?? undefined;
171
+ const connection = data.repository?.pullRequest?.[field];
172
+ if (!connection)
173
+ return count === 0 ? { viewer, complete: false } : result(false);
174
+ pages.push(connection.nodes);
175
+ if (!connection.pageInfo.hasPreviousPage)
176
+ return result(true);
177
+ before = connection.pageInfo.startCursor ?? undefined;
178
+ if (!before)
179
+ return result(false);
180
+ }
181
+ return result(limit.completeAtLimit);
182
+ }
183
+ async function readOlderComments(graphql, host, thread) {
184
+ if (!thread.comments)
185
+ return { comments: [], complete: false };
186
+ const pages = [];
187
+ let before = thread.comments?.pageInfo.hasPreviousPage ? thread.comments.pageInfo.startCursor ?? undefined : undefined;
188
+ if (thread.comments?.pageInfo.hasPreviousPage && !before)
189
+ return { comments: [], complete: false };
190
+ for (let count = 1;before && count < MAX_COMMENT_PAGES; count++) {
191
+ const data = await graphql(host, THREAD_COMMENTS_QUERY, { id: thread.id, before });
192
+ const connection = data.node?.comments;
193
+ if (!connection)
194
+ return { comments: pages.toReversed().flat(), complete: false };
195
+ pages.push(connection.nodes);
196
+ before = connection.pageInfo.hasPreviousPage ? connection.pageInfo.startCursor ?? undefined : undefined;
197
+ if (connection.pageInfo.hasPreviousPage && !before)
198
+ return { comments: pages.toReversed().flat(), complete: false };
199
+ }
200
+ return { comments: pages.toReversed().flat(), complete: true };
201
+ }
202
+ async function fetchComments(transport, host, project, number) {
203
+ let requests = 0;
204
+ const graphql = typed(async (...args) => {
205
+ if (requests++ >= MAX_FETCH_REQUESTS)
206
+ return {};
207
+ return transport(...args);
208
+ });
209
+ const [owner, repo] = project.split("/");
210
+ const base = { owner, repo, number: Number(number) };
211
+ const [conversation, reviews, threads] = await Promise.all([
212
+ readList(graphql, host, base, ISSUE_COMMENTS_QUERY, "comments"),
213
+ readList(graphql, host, base, REVIEWS_QUERY, "reviews"),
214
+ readList(graphql, host, base, THREADS_QUERY, "reviewThreads", allThreads)
215
+ ]);
216
+ if (!conversation.items || !reviews.items || !threads.items)
217
+ return;
218
+ const viewerID = conversation.viewer ?? reviews.viewer ?? threads.viewer;
219
+ let threadsComplete = threads.complete;
220
+ const inline = [];
221
+ for (const thread of threads.items) {
222
+ const older = await readOlderComments(graphql, host, thread);
223
+ threadsComplete &&= older.complete;
224
+ for (const node of [...older.comments, ...thread.comments?.nodes ?? []]) {
225
+ const comment = toInlineComment(node, thread.isResolved);
226
+ if (comment)
227
+ inline.push(comment);
228
+ }
229
+ inline.sort((a, b) => b.order - a.order);
230
+ inline.splice(PAGE_SIZE * MAX_COMMENT_PAGES);
231
+ }
232
+ const comments = [
233
+ ...conversation.items.map(toIssueComment),
234
+ ...reviews.items.map(toReview),
235
+ ...inline.sort((a, b) => a.order - b.order).slice(-PAGE_SIZE * MAX_COMMENT_PAGES)
236
+ ].flatMap((comment) => comment ?? []);
237
+ return {
238
+ complete: conversation.complete && reviews.complete && threadsComplete && viewerID !== undefined,
239
+ viewerID,
240
+ comments: comments.sort((a, b) => a.order - b.order)
241
+ };
242
+ }
243
+
244
+ // packages/forgekeeper/src/gitlab-feedback.ts
245
+ var PAGE_SIZE2 = 100;
246
+ var MAX_COMMENT_PAGES2 = 20;
79
247
  var COMMENTS_QUERY = query(`query($project: ID!, $iid: String!, $before: String) {
80
248
  currentUser { id }
81
249
  project(fullPath: $project) {
82
250
  mergeRequest(iid: $iid) {
83
- notes(last: ${PAGE_SIZE}, before: $before, filter: ONLY_COMMENTS) {
251
+ notes(last: ${PAGE_SIZE2}, before: $before, filter: ONLY_COMMENTS) {
84
252
  pageInfo { hasPreviousPage startCursor }
85
253
  nodes {
86
254
  id url createdAt updatedAt lastEditedAt system
@@ -109,7 +277,7 @@ function toComment(node) {
109
277
  username: node.author.username
110
278
  };
111
279
  }
112
- async function fetchComments(transport, host, project, iid) {
280
+ async function fetchComments2(transport, host, project, iid) {
113
281
  const graphql = typed(transport);
114
282
  const pages = [];
115
283
  let viewerID;
@@ -119,7 +287,7 @@ async function fetchComments(transport, host, project, iid) {
119
287
  viewerID,
120
288
  comments: pages.toReversed().flat()
121
289
  });
122
- for (let page = 0;page < MAX_COMMENT_PAGES; page++) {
290
+ for (let page2 = 0;page2 < MAX_COMMENT_PAGES2; page2++) {
123
291
  const variables = { project, iid };
124
292
  if (before)
125
293
  variables.before = before;
@@ -127,7 +295,7 @@ async function fetchComments(transport, host, project, iid) {
127
295
  viewerID ??= data.currentUser?.id ?? undefined;
128
296
  const connection = data.project?.mergeRequest?.notes;
129
297
  if (!connection)
130
- return page === 0 ? undefined : snapshot(false);
298
+ return page2 === 0 ? undefined : snapshot(false);
131
299
  pages.push(connection.nodes.flatMap((node) => toComment(node) ?? []));
132
300
  if (!connection.pageInfo.hasPreviousPage)
133
301
  return snapshot(true);
@@ -140,7 +308,7 @@ async function fetchComments(transport, host, project, iid) {
140
308
 
141
309
  // packages/forgekeeper/src/gitlab.ts
142
310
  var DISCUSSIONS = "pageInfo { hasNextPage endCursor } nodes { resolvable resolved }";
143
- var PAGE_SIZE2 = 100;
311
+ var PAGE_SIZE3 = 100;
144
312
  var MAX_DISCUSSION_PAGES = 50;
145
313
  var MERGE_REQUEST_FIELDS = `
146
314
  iid title webUrl state draft conflicts approved detailedMergeStatus diffHeadSha updatedAt targetBranch
@@ -149,7 +317,7 @@ var MERGE_REQUEST_FIELDS = `
149
317
  targetProject { fullPath }
150
318
  headPipeline { status path detailedStatus { label } }
151
319
  reviewers(first: 100) { nodes { type username bot mergeRequestInteraction { reviewState approved } } }
152
- discussions(first: ${PAGE_SIZE2}) { ${DISCUSSIONS} }
320
+ discussions(first: ${PAGE_SIZE3}) { ${DISCUSSIONS} }
153
321
  `;
154
322
  function mergeRequestsQuery(projectCount) {
155
323
  const variables = Array.from({ length: projectCount }, (_, index) => `$p${index}: ID!`).join(", ");
@@ -184,7 +352,7 @@ var SOURCE_BRANCH_QUERY = query(`query($project: ID!, $iid: String!) {
184
352
  }`);
185
353
  var DISCUSSIONS_QUERY = query(`query($project: ID!, $iid: String!, $after: String) {
186
354
  project(fullPath: $project) {
187
- mergeRequest(iid: $iid) { discussions(first: ${PAGE_SIZE2}, after: $after) { ${DISCUSSIONS} } }
355
+ mergeRequest(iid: $iid) { discussions(first: ${PAGE_SIZE3}, after: $after) { ${DISCUSSIONS} } }
188
356
  }
189
357
  }`);
190
358
  function classifyError(message, code) {
@@ -223,7 +391,7 @@ function glabGraphQL(run, cwd) {
223
391
  return body.data;
224
392
  };
225
393
  }
226
- var countUnresolved = (page) => page.nodes.filter((discussion) => discussion.resolvable && !discussion.resolved).length;
394
+ var countUnresolved = (page2) => page2.nodes.filter((discussion) => discussion.resolvable && !discussion.resolved).length;
227
395
  var gitlabTraits = {
228
396
  kind: "gitlab",
229
397
  noun: "MR",
@@ -258,7 +426,7 @@ var gitlabTraits = {
258
426
  feedback: {
259
427
  async fetch(run, directory, request) {
260
428
  const ref = gitlabTraits.parseUrl(request.url);
261
- return ref ? fetchComments(glabGraphQL(run, directory), ref.host, ref.project, ref.iid) : undefined;
429
+ return ref ? fetchComments2(glabGraphQL(run, directory), ref.host, ref.project, ref.iid) : undefined;
262
430
  }
263
431
  }
264
432
  };
@@ -330,22 +498,22 @@ class GitLabForge {
330
498
  }
331
499
  async unresolvedThreads(host, node) {
332
500
  let count = countUnresolved(node.discussions);
333
- let page = node.discussions.pageInfo;
501
+ let page2 = node.discussions.pageInfo;
334
502
  let pages = 1;
335
- while (page.hasNextPage && page.endCursor && pages < MAX_DISCUSSION_PAGES) {
503
+ while (page2.hasNextPage && page2.endCursor && pages < MAX_DISCUSSION_PAGES) {
336
504
  const data = await this.graphql(host, DISCUSSIONS_QUERY, {
337
505
  project: node.targetProject.fullPath,
338
506
  iid: node.iid,
339
- after: page.endCursor
507
+ after: page2.endCursor
340
508
  });
341
509
  const next = data.project?.mergeRequest?.discussions;
342
510
  if (!next)
343
511
  break;
344
512
  count += countUnresolved(next);
345
- page = next.pageInfo;
513
+ page2 = next.pageInfo;
346
514
  pages++;
347
515
  }
348
- return { count, complete: !page.hasNextPage };
516
+ return { count, complete: !page2.hasNextPage };
349
517
  }
350
518
  async normalize(host, node) {
351
519
  const threads = await this.unresolvedThreads(host, node);
@@ -384,10 +552,12 @@ class GitLabForge {
384
552
  }
385
553
 
386
554
  // packages/forgekeeper/src/github.ts
555
+ var COPILOT_AUTHOR = "copilot-pull-request-reviewer[bot]";
387
556
  var fields = `number title url state isDraft mergeable reviewDecision headRefOid headRefName
388
557
  headRepository { nameWithOwner } baseRepository { nameWithOwner } baseRefName updatedAt
389
558
  reviewThreads(first:100) { nodes { isResolved } pageInfo { hasNextPage endCursor } }
390
- reviewRequests(first:100) { nodes { requestedReviewer { ... on User { login } ... on Team { name } } } pageInfo { hasNextPage } }
559
+ reviewRequests(first:100) { nodes { requestedReviewer { __typename ... on User { login } ... on Bot { login } ... on Team { name } } } pageInfo { hasNextPage endCursor } }
560
+ copilotReviews: reviews(last:1, author:"${COPILOT_AUTHOR}", states:[COMMENTED,CHANGES_REQUESTED,APPROVED,DISMISSED]) { nodes { id state comments { totalCount } } }
391
561
  commits(last:1) { nodes { commit { statusCheckRollup { contexts(first:100) {
392
562
  nodes { __typename ... on CheckRun { status conclusion detailsUrl } ... on StatusContext { state targetUrl } }
393
563
  pageInfo { hasNextPage endCursor }
@@ -445,22 +615,31 @@ var CONCLUSIONS = [
445
615
  ];
446
616
  var STATES = ["SUCCESS", "FAILURE", "ERROR", "PENDING", "EXPECTED"];
447
617
  function checks(nodes, complete, url) {
618
+ const count = (value) => `${value} check${value === 1 ? "" : "s"}`;
448
619
  const failed = nodes.filter((node) => FAILED.includes(node.conclusion ?? node.state ?? "")).length;
449
620
  const pending = nodes.filter((node) => node.status ? node.status !== "COMPLETED" : ["PENDING", "EXPECTED"].includes(node.state ?? "")).length;
450
621
  const unknown = nodes.some((node) => node.status === "COMPLETED" ? !CONCLUSIONS.includes(node.conclusion ?? "") : !node.status && !STATES.includes(node.state ?? ""));
451
622
  if (failed)
452
623
  return {
453
624
  status: "FAILED",
454
- label: `${failed} failed${pending ? `, ${pending} pending` : ""}${complete ? "" : " (partial)"}`,
625
+ label: `${count(failed)} failed${pending ? `, ${count(pending)} pending` : ""}${complete ? "" : " (partial)"}`,
455
626
  url
456
627
  };
457
628
  if (pending || !complete || unknown)
458
629
  return {
459
630
  status: "PENDING",
460
- label: `${pending ? `${pending} pending` : "unknown"}${complete ? "" : " (partial)"}`,
631
+ label: `${pending ? `${count(pending)} pending` : "unknown"}${complete ? "" : " (partial)"}`,
461
632
  url
462
633
  };
463
- return { status: "SUCCESS", label: `${nodes.length} passed or skipped`, url };
634
+ const label = [
635
+ ["SUCCESS", "passed"],
636
+ ["SKIPPED", "skipped"],
637
+ ["NEUTRAL", "neutral"]
638
+ ].flatMap(([result, text]) => {
639
+ const total = nodes.filter((node) => (node.conclusion ?? node.state) === result).length;
640
+ return total ? [`${count(total)} ${text}`] : [];
641
+ }).join(", ");
642
+ return { status: "SUCCESS", label: label || "0 checks", url };
464
643
  }
465
644
  function parseGitHubUrl(url, pattern) {
466
645
  const ref = parseWebUrl("github", url, pattern);
@@ -481,8 +660,43 @@ var githubTraits = {
481
660
  indicators: (request) => request.reviewDecision === "CHANGES_REQUESTED" ? [{ text: "changes requested", tone: "warning", essential: true }] : [],
482
661
  details: (request) => [
483
662
  `Review decision: ${request.reviewDecision ? humanize(request.reviewDecision) : "not reported"}`
484
- ]
663
+ ],
664
+ automatedReview: {
665
+ name: "GitHub Copilot",
666
+ status: (request) => copilotStatus(request.copilotReview)
667
+ },
668
+ feedback: {
669
+ async fetch(run, directory, request) {
670
+ const ref = githubTraits.parseUrl(request.url);
671
+ return ref ? fetchComments(ghGraphQL(run, directory), ref.host, ref.project, ref.iid) : undefined;
672
+ }
673
+ }
485
674
  };
675
+ function copilotStatus(review) {
676
+ if (!review)
677
+ return;
678
+ const feedback = review.comments > 0 && !review.dismissed;
679
+ const label = review.dismissed ? "dismissed" : feedback ? "commented" : "no comments";
680
+ const completed = review.reviewID ? { id: review.reviewID, feedback, label } : undefined;
681
+ if (review.requested)
682
+ return { state: "running", label: "reviewing", completed };
683
+ if (!completed)
684
+ return;
685
+ return { state: feedback ? "feedback" : "settled", label, completed };
686
+ }
687
+ var isCopilotReviewer = (login) => /^copilot-pull-request-reviewer(\[bot\])?$/i.test(login ?? "");
688
+ function copilotReview(node) {
689
+ const requested = node.reviewRequests.nodes.some((request) => isCopilotReviewer(request.requestedReviewer?.login));
690
+ const latest = node.copilotReviews?.nodes?.find((review) => review);
691
+ if (!requested && !latest)
692
+ return;
693
+ return {
694
+ requested,
695
+ reviewID: latest?.id,
696
+ comments: latest?.comments.totalCount ?? 0,
697
+ ...latest?.state === "DISMISSED" ? { dismissed: true } : {}
698
+ };
699
+ }
486
700
 
487
701
  class GitHubForge {
488
702
  traits = githubTraits;
@@ -533,7 +747,7 @@ class GitHubForge {
533
747
  const [owner, repo] = target.path.split("/");
534
748
  let after;
535
749
  let complete = false;
536
- for (let page = 0;page < MAX_PAGES; page++) {
750
+ for (let page2 = 0;page2 < MAX_PAGES; page2++) {
537
751
  const data = await this.graphql(target.host, query(`query($owner:String!,$repo:String!,$branch:String!${after ? ",$after:String!" : ""}) {
538
752
  repository(owner:$owner,name:$repo) { pullRequests(first:100,states:OPEN,headRefName:$branch${after ? ",after:$after" : ""}) {
539
753
  nodes { ${fields} } pageInfo { hasNextPage endCursor }
@@ -563,21 +777,21 @@ class GitHubForge {
563
777
  async threads(host, node) {
564
778
  const [owner, repo] = node.baseRepository.nameWithOwner.split("/");
565
779
  const threads = [...node.reviewThreads.nodes];
566
- let page = node.reviewThreads.pageInfo;
567
- for (let count = 1;page?.hasNextPage && page.endCursor && count < MAX_PAGES; count++) {
780
+ let page2 = node.reviewThreads.pageInfo;
781
+ for (let count = 1;page2?.hasNextPage && page2.endCursor && count < MAX_PAGES; count++) {
568
782
  const data = await this.graphql(host, query(`query($owner:String!,$repo:String!,$number:Int!,$after:String!) {
569
783
  repository(owner:$owner,name:$repo) { pullRequest(number:$number) {
570
784
  reviewThreads(first:100,after:$after) { nodes { isResolved } pageInfo { hasNextPage endCursor } }
571
- } } }`), { owner, repo, number: node.number, after: page.endCursor });
785
+ } } }`), { owner, repo, number: node.number, after: page2.endCursor });
572
786
  const next = data.repository?.pullRequest?.reviewThreads;
573
787
  if (!next)
574
788
  break;
575
789
  threads.push(...next.nodes);
576
- page = next.pageInfo;
790
+ page2 = next.pageInfo;
577
791
  }
578
792
  return {
579
793
  unresolved: threads.filter((thread) => !thread.isResolved).length,
580
- complete: !page?.hasNextPage
794
+ complete: !page2?.hasNextPage
581
795
  };
582
796
  }
583
797
  async contexts(host, node) {
@@ -598,7 +812,33 @@ class GitHubForge {
598
812
  }
599
813
  return { nodes: contexts, complete: !cursor?.hasNextPage };
600
814
  }
815
+ async reviewers(host, node) {
816
+ const nodes = [...node.reviewRequests.nodes];
817
+ let reviewerPage = node.reviewRequests.pageInfo;
818
+ for (let count = 1;reviewerPage?.hasNextPage && count < MAX_PAGES; count++) {
819
+ if (!reviewerPage.endCursor)
820
+ throw new ForgeError("request", "GitHub reviewer pagination cursor missing");
821
+ const [owner, repo] = node.baseRepository.nameWithOwner.split("/");
822
+ const data = await this.graphql(host, query(`query($owner:String!,$repo:String!,$number:Int!,$after:String!) {
823
+ repository(owner:$owner,name:$repo) { pullRequest(number:$number) {
824
+ reviewRequests(first:100,after:$after) {
825
+ nodes { requestedReviewer { __typename ... on User { login } ... on Bot { login } ... on Team { name } } }
826
+ pageInfo { hasNextPage endCursor }
827
+ }
828
+ } }
829
+ }`), { owner, repo, number: node.number, after: reviewerPage.endCursor });
830
+ const next = data.repository?.pullRequest?.reviewRequests;
831
+ if (!next)
832
+ throw new ForgeError("request", "GitHub reviewers unavailable");
833
+ nodes.push(...next.nodes);
834
+ reviewerPage = next.pageInfo;
835
+ }
836
+ if (reviewerPage?.hasNextPage)
837
+ throw new ForgeError("request", "GitHub reviewers exceeded the pagination limit");
838
+ return { nodes, pageInfo: reviewerPage };
839
+ }
601
840
  async normalize(host, node) {
841
+ const reviewers = await this.reviewers(host, node);
602
842
  const [threads, contexts] = [await this.threads(host, node), await this.contexts(host, node)];
603
843
  return {
604
844
  forge: "github",
@@ -611,11 +851,14 @@ class GitHubForge {
611
851
  conflictsKnown: node.mergeable !== "UNKNOWN",
612
852
  approved: node.reviewDecision === "APPROVED",
613
853
  reviewDecision: node.reviewDecision ?? undefined,
614
- awaitingReviewers: node.reviewRequests.nodes.flatMap((request) => {
854
+ copilotReview: copilotReview({ ...node, reviewRequests: reviewers }),
855
+ awaitingReviewers: reviewers.nodes.flatMap((request) => {
615
856
  const reviewer = request.requestedReviewer;
857
+ if (reviewer?.__typename === "Bot")
858
+ return [];
616
859
  return reviewer?.login ? [reviewer.login] : reviewer?.name ? [reviewer.name] : [];
617
860
  }),
618
- reviewersComplete: !node.reviewRequests.pageInfo?.hasNextPage,
861
+ reviewersComplete: !reviewers.pageInfo?.hasNextPage,
619
862
  targetProject: node.baseRepository.nameWithOwner,
620
863
  targetBranch: node.baseRefName,
621
864
  headSha: node.headRefOid,
@@ -808,7 +1051,7 @@ function responsiveFooterSegments(snapshot, width) {
808
1051
  }
809
1052
  return fitted;
810
1053
  }
811
- var time = (value) => new Date(value).toLocaleTimeString();
1054
+ var time2 = (value) => new Date(value).toLocaleTimeString();
812
1055
  function describe(request, head) {
813
1056
  const traits = traitsOf(request);
814
1057
  const lines = [
@@ -856,9 +1099,9 @@ function detailsMessage(snapshot) {
856
1099
  lines.push("", ...describe(request, repository?.head ?? ""));
857
1100
  }
858
1101
  if (error)
859
- lines.push("", `Last refresh failed at ${time(error.at)}: ${error.message}`);
1102
+ lines.push("", `Last refresh failed at ${time2(error.at)}: ${error.message}`);
860
1103
  if (fetchedAt !== undefined)
861
- lines.push("", `Last fetched: ${time(fetchedAt)}`);
1104
+ lines.push("", `Last fetched: ${time2(fetchedAt)}`);
862
1105
  return lines.join(`
863
1106
  `);
864
1107
  }
@@ -1235,22 +1478,13 @@ var tui_default = {
1235
1478
  })();
1236
1479
  },
1237
1480
  children: (url) => (() => {
1238
- var _el$5 = _$createElement("text"), _el$6 = _$createElement("a"), _el$7 = _$createElement("u");
1481
+ var _el$5 = _$createElement("text"), _el$6 = _$createElement("u");
1239
1482
  _$insertNode(_el$5, _el$6);
1240
1483
  _$setProp(_el$5, "wrapMode", "none");
1241
1484
  _$setProp(_el$5, "flexShrink", 0);
1242
1485
  _$setProp(_el$5, "onMouseUp", () => openUrl(url()));
1243
- _$insertNode(_el$6, _el$7);
1244
- _$insert(_el$7, () => segment.text);
1245
- _$effect((_p$) => {
1246
- var _v$ = color(segment.tone), _v$2 = url();
1247
- _v$ !== _p$.e && (_p$.e = _$setProp(_el$5, "fg", _v$, _p$.e));
1248
- _v$2 !== _p$.t && (_p$.t = _$setProp(_el$6, "href", _v$2, _p$.t));
1249
- return _p$;
1250
- }, {
1251
- e: undefined,
1252
- t: undefined
1253
- });
1486
+ _$insert(_el$6, () => segment.text);
1487
+ _$effect((_$p) => _$setProp(_el$5, "fg", color(segment.tone), _$p));
1254
1488
  return _el$5;
1255
1489
  })()
1256
1490
  })]
@@ -1286,43 +1520,41 @@ var tui_default = {
1286
1520
  function DetailField(props) {
1287
1521
  const foreground = () => props.tone ? color(props.tone) : context.theme.text.base;
1288
1522
  return (() => {
1289
- var _el$8 = _$createElement("text"), _el$9 = _$createTextNode(`: `), _el$0 = _$createElement("span");
1290
- _$insertNode(_el$8, _el$9);
1291
- _$insertNode(_el$8, _el$0);
1292
- _$setProp(_el$8, "onMouseUp", () => props.url && openUrl(props.url));
1293
- _$insert(_el$8, () => props.label, _el$9);
1294
- _$insert(_el$0, _$createComponent(Show, {
1523
+ var _el$7 = _$createElement("text"), _el$8 = _$createTextNode(`: `), _el$9 = _$createElement("span");
1524
+ _$insertNode(_el$7, _el$8);
1525
+ _$insertNode(_el$7, _el$9);
1526
+ _$setProp(_el$7, "onMouseUp", () => props.url && openUrl(props.url));
1527
+ _$insert(_el$7, () => props.label, _el$8);
1528
+ _$insert(_el$9, _$createComponent(Show, {
1295
1529
  get when() {
1296
1530
  return props.url;
1297
1531
  },
1298
1532
  get fallback() {
1299
1533
  return (() => {
1300
- var _el$1 = _$createElement("b");
1301
- _$insert(_el$1, () => props.value);
1302
- return _el$1;
1534
+ var _el$10 = _$createElement("b");
1535
+ _$insert(_el$10, () => props.value);
1536
+ return _el$10;
1303
1537
  })();
1304
1538
  },
1305
- children: (url) => (() => {
1306
- var _el$10 = _$createElement("a"), _el$11 = _$createElement("u"), _el$12 = _$createElement("b");
1307
- _$insertNode(_el$10, _el$11);
1308
- _$insertNode(_el$11, _el$12);
1309
- _$insert(_el$12, () => props.value);
1310
- _$effect((_$p) => _$setProp(_el$10, "href", url(), _$p));
1311
- return _el$10;
1312
- })()
1539
+ get children() {
1540
+ var _el$0 = _$createElement("u"), _el$1 = _$createElement("b");
1541
+ _$insertNode(_el$0, _el$1);
1542
+ _$insert(_el$1, () => props.value);
1543
+ return _el$0;
1544
+ }
1313
1545
  }));
1314
1546
  _$effect((_p$) => {
1315
- var _v$3 = context.theme.text.muted, _v$4 = {
1547
+ var _v$ = context.theme.text.muted, _v$2 = {
1316
1548
  fg: foreground()
1317
1549
  };
1318
- _v$3 !== _p$.e && (_p$.e = _$setProp(_el$8, "fg", _v$3, _p$.e));
1319
- _v$4 !== _p$.t && (_p$.t = _$setProp(_el$0, "style", _v$4, _p$.t));
1550
+ _v$ !== _p$.e && (_p$.e = _$setProp(_el$7, "fg", _v$, _p$.e));
1551
+ _v$2 !== _p$.t && (_p$.t = _$setProp(_el$9, "style", _v$2, _p$.t));
1320
1552
  return _p$;
1321
1553
  }, {
1322
1554
  e: undefined,
1323
1555
  t: undefined
1324
1556
  });
1325
- return _el$8;
1557
+ return _el$7;
1326
1558
  })();
1327
1559
  }
1328
1560
  function RequestDetails(props) {
@@ -1330,21 +1562,20 @@ var tui_default = {
1330
1562
  const traits = () => traitsOf(request());
1331
1563
  const review = () => automatedReview(request());
1332
1564
  return (() => {
1333
- var _el$13 = _$createElement("box"), _el$14 = _$createElement("text"), _el$15 = _$createElement("a"), _el$16 = _$createElement("u"), _el$17 = _$createElement("b"), _el$18 = _$createTextNode(` `), _el$19 = _$createElement("box"), _el$20 = _$createElement("box"), _el$21 = _$createElement("text"), _el$22 = _$createElement("b");
1565
+ var _el$11 = _$createElement("box"), _el$12 = _$createElement("text"), _el$13 = _$createElement("u"), _el$14 = _$createElement("b"), _el$15 = _$createTextNode(` `), _el$16 = _$createElement("box"), _el$17 = _$createElement("box"), _el$18 = _$createElement("text"), _el$19 = _$createElement("b");
1566
+ _$insertNode(_el$11, _el$12);
1567
+ _$insertNode(_el$11, _el$16);
1568
+ _$insertNode(_el$11, _el$17);
1569
+ _$setProp(_el$11, "gap", 1);
1570
+ _$setProp(_el$11, "flexShrink", 0);
1571
+ _$insertNode(_el$12, _el$13);
1572
+ _$setProp(_el$12, "onMouseUp", () => openUrl(request().url));
1334
1573
  _$insertNode(_el$13, _el$14);
1335
- _$insertNode(_el$13, _el$19);
1336
- _$insertNode(_el$13, _el$20);
1337
- _$setProp(_el$13, "gap", 1);
1338
- _$setProp(_el$13, "flexShrink", 0);
1339
1574
  _$insertNode(_el$14, _el$15);
1340
- _$setProp(_el$14, "onMouseUp", () => openUrl(request().url));
1341
- _$insertNode(_el$15, _el$16);
1342
- _$insertNode(_el$16, _el$17);
1343
- _$insertNode(_el$17, _el$18);
1344
- _$insert(_el$17, () => reference(request()), _el$18);
1345
- _$insert(_el$17, () => request().title, null);
1346
- _$setProp(_el$19, "flexShrink", 0);
1347
- _$insert(_el$19, _$createComponent(DetailField, {
1575
+ _$insert(_el$14, () => reference(request()), _el$15);
1576
+ _$insert(_el$14, () => request().title, null);
1577
+ _$setProp(_el$16, "flexShrink", 0);
1578
+ _$insert(_el$16, _$createComponent(DetailField, {
1348
1579
  label: "State",
1349
1580
  get value() {
1350
1581
  return request().state;
@@ -1353,13 +1584,13 @@ var tui_default = {
1353
1584
  return request().state === "merged" ? "success" : undefined;
1354
1585
  }
1355
1586
  }), null);
1356
- _$insert(_el$19, _$createComponent(DetailField, {
1587
+ _$insert(_el$16, _$createComponent(DetailField, {
1357
1588
  label: "Target",
1358
1589
  get value() {
1359
1590
  return `${request().targetProject} \u2192 ${request().targetBranch}`;
1360
1591
  }
1361
1592
  }), null);
1362
- _$insert(_el$19, _$createComponent(DetailField, {
1593
+ _$insert(_el$16, _$createComponent(DetailField, {
1363
1594
  get label() {
1364
1595
  return traits().ci.charAt(0).toUpperCase() + traits().ci.slice(1);
1365
1596
  },
@@ -1373,7 +1604,7 @@ var tui_default = {
1373
1604
  return request().pipeline?.url;
1374
1605
  }
1375
1606
  }), null);
1376
- _$insert(_el$19, _$createComponent(DetailField, {
1607
+ _$insert(_el$16, _$createComponent(DetailField, {
1377
1608
  label: "Unresolved threads",
1378
1609
  get value() {
1379
1610
  return `${request().unresolvedThreads}${request().threadsComplete ? "" : "+"}`;
@@ -1382,7 +1613,7 @@ var tui_default = {
1382
1613
  return request().unresolvedThreads || !request().threadsComplete ? "warning" : undefined;
1383
1614
  }
1384
1615
  }), null);
1385
- _$insert(_el$19, _$createComponent(DetailField, {
1616
+ _$insert(_el$16, _$createComponent(DetailField, {
1386
1617
  label: "Draft",
1387
1618
  get value() {
1388
1619
  return yesNo(request().draft);
@@ -1391,7 +1622,7 @@ var tui_default = {
1391
1622
  return request().draft ? "warning" : undefined;
1392
1623
  }
1393
1624
  }), null);
1394
- _$insert(_el$19, _$createComponent(DetailField, {
1625
+ _$insert(_el$16, _$createComponent(DetailField, {
1395
1626
  label: "Conflicts",
1396
1627
  get value() {
1397
1628
  return _$memo(() => !!request().conflictsKnown)() ? yesNo(request().conflicts) : "unknown";
@@ -1400,21 +1631,21 @@ var tui_default = {
1400
1631
  return request().conflicts ? "error" : undefined;
1401
1632
  }
1402
1633
  }), null);
1403
- _$insertNode(_el$20, _el$21);
1404
- _$setProp(_el$20, "flexShrink", 0);
1405
- _$insertNode(_el$21, _el$22);
1406
- _$insertNode(_el$22, _$createTextNode(`Review and approval`));
1407
- _$insert(_el$20, _$createComponent(For, {
1634
+ _$insertNode(_el$17, _el$18);
1635
+ _$setProp(_el$17, "flexShrink", 0);
1636
+ _$insertNode(_el$18, _el$19);
1637
+ _$insertNode(_el$19, _$createTextNode(`Review and approval`));
1638
+ _$insert(_el$17, _$createComponent(For, {
1408
1639
  get each() {
1409
1640
  return traits().details(request());
1410
1641
  },
1411
1642
  children: (line) => {
1412
1643
  const separator = line.indexOf(": ");
1413
1644
  return separator < 0 ? (() => {
1414
- var _el$29 = _$createElement("text");
1415
- _$insert(_el$29, line);
1416
- _$effect((_$p) => _$setProp(_el$29, "fg", context.theme.text.base, _$p));
1417
- return _el$29;
1645
+ var _el$26 = _$createElement("text");
1646
+ _$insert(_el$26, line);
1647
+ _$effect((_$p) => _$setProp(_el$26, "fg", context.theme.text.base, _$p));
1648
+ return _el$26;
1418
1649
  })() : _$createComponent(DetailField, {
1419
1650
  get label() {
1420
1651
  return line.slice(0, separator);
@@ -1425,7 +1656,7 @@ var tui_default = {
1425
1656
  });
1426
1657
  }
1427
1658
  }), null);
1428
- _$insert(_el$20, _$createComponent(Show, {
1659
+ _$insert(_el$17, _$createComponent(Show, {
1429
1660
  get when() {
1430
1661
  return review();
1431
1662
  },
@@ -1441,7 +1672,7 @@ var tui_default = {
1441
1672
  }
1442
1673
  })
1443
1674
  }), null);
1444
- _$insert(_el$20, _$createComponent(Show, {
1675
+ _$insert(_el$17, _$createComponent(Show, {
1445
1676
  get when() {
1446
1677
  return request().awaitingReviewers.length;
1447
1678
  },
@@ -1454,42 +1685,40 @@ var tui_default = {
1454
1685
  });
1455
1686
  }
1456
1687
  }), null);
1457
- _$insert(_el$13, _$createComponent(Show, {
1688
+ _$insert(_el$11, _$createComponent(Show, {
1458
1689
  get when() {
1459
1690
  return !request().reviewersComplete;
1460
1691
  },
1461
1692
  get children() {
1462
- var _el$24 = _$createElement("text");
1463
- _$insertNode(_el$24, _$createTextNode(`Reviewer list is partial`));
1464
- _$effect((_$p) => _$setProp(_el$24, "fg", color("warning"), _$p));
1465
- return _el$24;
1693
+ var _el$21 = _$createElement("text");
1694
+ _$insertNode(_el$21, _$createTextNode(`Reviewer list is partial`));
1695
+ _$effect((_$p) => _$setProp(_el$21, "fg", color("warning"), _$p));
1696
+ return _el$21;
1466
1697
  }
1467
1698
  }), null);
1468
- _$insert(_el$13, _$createComponent(Show, {
1699
+ _$insert(_el$11, _$createComponent(Show, {
1469
1700
  get when() {
1470
1701
  return _$memo(() => !!(props.head && request().headSha))() && props.head !== request().headSha;
1471
1702
  },
1472
1703
  get children() {
1473
- var _el$26 = _$createElement("text"), _el$27 = _$createTextNode(`Local HEAD differs from the `), _el$28 = _$createTextNode(` head commit (unpushed or not fetched)`);
1474
- _$insertNode(_el$26, _el$27);
1475
- _$insertNode(_el$26, _el$28);
1476
- _$insert(_el$26, () => traits().noun, _el$28);
1477
- _$effect((_$p) => _$setProp(_el$26, "fg", color("warning"), _$p));
1478
- return _el$26;
1704
+ var _el$23 = _$createElement("text"), _el$24 = _$createTextNode(`Local HEAD differs from the `), _el$25 = _$createTextNode(` head commit (unpushed or not fetched)`);
1705
+ _$insertNode(_el$23, _el$24);
1706
+ _$insertNode(_el$23, _el$25);
1707
+ _$insert(_el$23, () => traits().noun, _el$25);
1708
+ _$effect((_$p) => _$setProp(_el$23, "fg", color("warning"), _$p));
1709
+ return _el$23;
1479
1710
  }
1480
1711
  }), null);
1481
1712
  _$effect((_p$) => {
1482
- var _v$5 = context.theme.text.base, _v$6 = request().url, _v$7 = context.theme.text.base;
1483
- _v$5 !== _p$.e && (_p$.e = _$setProp(_el$14, "fg", _v$5, _p$.e));
1484
- _v$6 !== _p$.t && (_p$.t = _$setProp(_el$15, "href", _v$6, _p$.t));
1485
- _v$7 !== _p$.a && (_p$.a = _$setProp(_el$21, "fg", _v$7, _p$.a));
1713
+ var _v$3 = context.theme.text.base, _v$4 = context.theme.text.base;
1714
+ _v$3 !== _p$.e && (_p$.e = _$setProp(_el$12, "fg", _v$3, _p$.e));
1715
+ _v$4 !== _p$.t && (_p$.t = _$setProp(_el$18, "fg", _v$4, _p$.t));
1486
1716
  return _p$;
1487
1717
  }, {
1488
1718
  e: undefined,
1489
- t: undefined,
1490
- a: undefined
1719
+ t: undefined
1491
1720
  });
1492
- return _el$13;
1721
+ return _el$11;
1493
1722
  })();
1494
1723
  }
1495
1724
  function StatusDetails(props) {
@@ -1498,19 +1727,19 @@ var tui_default = {
1498
1727
  return value?.kind === "found" ? value : undefined;
1499
1728
  };
1500
1729
  return (() => {
1501
- var _el$30 = _$createElement("box");
1502
- _$setProp(_el$30, "gap", 1);
1503
- _$setProp(_el$30, "flexShrink", 0);
1504
- _$insert(_el$30, _$createComponent(Show, {
1730
+ var _el$27 = _$createElement("box");
1731
+ _$setProp(_el$27, "gap", 1);
1732
+ _$setProp(_el$27, "flexShrink", 0);
1733
+ _$insert(_el$27, _$createComponent(Show, {
1505
1734
  get when() {
1506
1735
  return lookup();
1507
1736
  },
1508
1737
  get fallback() {
1509
1738
  return (() => {
1510
- var _el$31 = _$createElement("text");
1511
- _$insert(_el$31, () => detailsMessage(props.snapshot));
1512
- _$effect((_$p) => _$setProp(_el$31, "fg", props.snapshot.error ? color("error") : context.theme.text.muted, _$p));
1513
- return _el$31;
1739
+ var _el$28 = _$createElement("text");
1740
+ _$insert(_el$28, () => detailsMessage(props.snapshot));
1741
+ _$effect((_$p) => _$setProp(_el$28, "fg", props.snapshot.error ? color("error") : context.theme.text.muted, _$p));
1742
+ return _el$28;
1514
1743
  })();
1515
1744
  },
1516
1745
  children: (found) => [_$createComponent(Show, {
@@ -1518,21 +1747,21 @@ var tui_default = {
1518
1747
  return found().repository;
1519
1748
  },
1520
1749
  children: (repository) => (() => {
1521
- var _el$36 = _$createElement("box");
1522
- _$setProp(_el$36, "flexShrink", 0);
1523
- _$insert(_el$36, _$createComponent(DetailField, {
1750
+ var _el$33 = _$createElement("box");
1751
+ _$setProp(_el$33, "flexShrink", 0);
1752
+ _$insert(_el$33, _$createComponent(DetailField, {
1524
1753
  label: "Repository",
1525
1754
  get value() {
1526
1755
  return repository().source.path;
1527
1756
  }
1528
1757
  }), null);
1529
- _$insert(_el$36, _$createComponent(DetailField, {
1758
+ _$insert(_el$33, _$createComponent(DetailField, {
1530
1759
  label: "Branch",
1531
1760
  get value() {
1532
1761
  return _$memo(() => repository().branch === repository().sourceBranch)() ? repository().branch : `${repository().branch} (pushes to ${repository().sourceBranch})`;
1533
1762
  }
1534
1763
  }), null);
1535
- return _el$36;
1764
+ return _el$33;
1536
1765
  })()
1537
1766
  }), _$createComponent(Show, {
1538
1767
  get when() {
@@ -1551,27 +1780,27 @@ var tui_default = {
1551
1780
  return found().failed ?? [];
1552
1781
  },
1553
1782
  children: (failure) => (() => {
1554
- var _el$37 = _$createElement("text"), _el$38 = _$createElement("b"), _el$40 = _$createTextNode(`
1555
- `), _el$41 = _$createTextNode(`
1783
+ var _el$34 = _$createElement("text"), _el$35 = _$createElement("b"), _el$37 = _$createTextNode(`
1784
+ `), _el$38 = _$createTextNode(`
1556
1785
  `);
1557
- _$insertNode(_el$37, _el$38);
1558
- _$insertNode(_el$37, _el$40);
1559
- _$insertNode(_el$37, _el$41);
1560
- _$insertNode(_el$38, _$createTextNode(`Unavailable`));
1561
- _$insert(_el$37, () => failure.url, _el$41);
1562
- _$insert(_el$37, () => failure.reason, null);
1563
- _$effect((_$p) => _$setProp(_el$37, "fg", color("warning"), _$p));
1564
- return _el$37;
1786
+ _$insertNode(_el$34, _el$35);
1787
+ _$insertNode(_el$34, _el$37);
1788
+ _$insertNode(_el$34, _el$38);
1789
+ _$insertNode(_el$35, _$createTextNode(`Unavailable`));
1790
+ _$insert(_el$34, () => failure.url, _el$38);
1791
+ _$insert(_el$34, () => failure.reason, null);
1792
+ _$effect((_$p) => _$setProp(_el$34, "fg", color("warning"), _$p));
1793
+ return _el$34;
1565
1794
  })()
1566
1795
  }), _$createComponent(Show, {
1567
1796
  get when() {
1568
1797
  return found().requests.length === 0;
1569
1798
  },
1570
1799
  get children() {
1571
- var _el$32 = _$createElement("text");
1572
- _$insertNode(_el$32, _$createTextNode(`No PR/MR status available.`));
1573
- _$effect((_$p) => _$setProp(_el$32, "fg", context.theme.text.muted, _$p));
1574
- return _el$32;
1800
+ var _el$29 = _$createElement("text");
1801
+ _$insertNode(_el$29, _$createTextNode(`No PR/MR status available.`));
1802
+ _$effect((_$p) => _$setProp(_el$29, "fg", context.theme.text.muted, _$p));
1803
+ return _el$29;
1575
1804
  }
1576
1805
  }), _$createComponent(For, {
1577
1806
  get each() {
@@ -1588,30 +1817,30 @@ var tui_default = {
1588
1817
  return props.snapshot.error;
1589
1818
  },
1590
1819
  children: (error) => (() => {
1591
- var _el$42 = _$createElement("text"), _el$43 = _$createElement("b"), _el$44 = _$createTextNode(`Last refresh failed at `), _el$45 = _$createTextNode(`
1820
+ var _el$39 = _$createElement("text"), _el$40 = _$createElement("b"), _el$41 = _$createTextNode(`Last refresh failed at `), _el$42 = _$createTextNode(`
1592
1821
  `);
1593
- _$insertNode(_el$42, _el$43);
1594
- _$insertNode(_el$42, _el$45);
1595
- _$insertNode(_el$43, _el$44);
1596
- _$insert(_el$43, () => new Date(error().at).toLocaleTimeString(), null);
1597
- _$insert(_el$42, () => error().message, null);
1598
- _$effect((_$p) => _$setProp(_el$42, "fg", color("error"), _$p));
1599
- return _el$42;
1822
+ _$insertNode(_el$39, _el$40);
1823
+ _$insertNode(_el$39, _el$42);
1824
+ _$insertNode(_el$40, _el$41);
1825
+ _$insert(_el$40, () => new Date(error().at).toLocaleTimeString(), null);
1826
+ _$insert(_el$39, () => error().message, null);
1827
+ _$effect((_$p) => _$setProp(_el$39, "fg", color("error"), _$p));
1828
+ return _el$39;
1600
1829
  })()
1601
1830
  }), _$createComponent(Show, {
1602
1831
  get when() {
1603
1832
  return props.snapshot.fetchedAt !== undefined;
1604
1833
  },
1605
1834
  get children() {
1606
- var _el$34 = _$createElement("text"), _el$35 = _$createTextNode(`Last fetched: `);
1607
- _$insertNode(_el$34, _el$35);
1608
- _$insert(_el$34, () => new Date(props.snapshot.fetchedAt).toLocaleTimeString(), null);
1609
- _$effect((_$p) => _$setProp(_el$34, "fg", context.theme.text.muted, _$p));
1610
- return _el$34;
1835
+ var _el$31 = _$createElement("text"), _el$32 = _$createTextNode(`Last fetched: `);
1836
+ _$insertNode(_el$31, _el$32);
1837
+ _$insert(_el$31, () => new Date(props.snapshot.fetchedAt).toLocaleTimeString(), null);
1838
+ _$effect((_$p) => _$setProp(_el$31, "fg", context.theme.text.muted, _$p));
1839
+ return _el$31;
1611
1840
  }
1612
1841
  })]
1613
1842
  }));
1614
- return _el$30;
1843
+ return _el$27;
1615
1844
  })();
1616
1845
  }
1617
1846
  function StatusDialog(props) {
@@ -1663,55 +1892,55 @@ var tui_default = {
1663
1892
  }]
1664
1893
  }));
1665
1894
  return (() => {
1666
- var _el$46 = _$createElement("box"), _el$47 = _$createElement("box"), _el$48 = _$createElement("text"), _el$49 = _$createElement("b"), _el$51 = _$createElement("text"), _el$53 = _$createElement("scrollbox"), _el$54 = _$createElement("box");
1667
- _$insertNode(_el$46, _el$47);
1668
- _$insertNode(_el$46, _el$53);
1669
- _$insertNode(_el$46, _el$54);
1670
- _$setProp(_el$46, "paddingLeft", 2);
1671
- _$setProp(_el$46, "paddingRight", 2);
1672
- _$setProp(_el$46, "paddingBottom", 1);
1673
- _$setProp(_el$46, "gap", 1);
1674
- _$insertNode(_el$47, _el$48);
1675
- _$insertNode(_el$47, _el$51);
1676
- _$setProp(_el$47, "height", 1);
1677
- _$setProp(_el$47, "flexShrink", 0);
1678
- _$setProp(_el$47, "flexDirection", "row");
1679
- _$setProp(_el$47, "justifyContent", "space-between");
1680
- _$insertNode(_el$48, _el$49);
1681
- _$insertNode(_el$49, _$createTextNode(`PR/MR status`));
1682
- _$insertNode(_el$51, _$createTextNode(`esc`));
1683
- _$setProp(_el$51, "onMouseUp", close);
1684
- _$setProp(_el$53, "minHeight", 1);
1685
- _$setProp(_el$53, "flexShrink", 0);
1686
- _$setProp(_el$53, "scrollX", false);
1687
- _$setProp(_el$53, "contentOptions", {
1895
+ var _el$43 = _$createElement("box"), _el$44 = _$createElement("box"), _el$45 = _$createElement("text"), _el$46 = _$createElement("b"), _el$48 = _$createElement("text"), _el$50 = _$createElement("scrollbox"), _el$51 = _$createElement("box");
1896
+ _$insertNode(_el$43, _el$44);
1897
+ _$insertNode(_el$43, _el$50);
1898
+ _$insertNode(_el$43, _el$51);
1899
+ _$setProp(_el$43, "paddingLeft", 2);
1900
+ _$setProp(_el$43, "paddingRight", 2);
1901
+ _$setProp(_el$43, "paddingBottom", 1);
1902
+ _$setProp(_el$43, "gap", 1);
1903
+ _$insertNode(_el$44, _el$45);
1904
+ _$insertNode(_el$44, _el$48);
1905
+ _$setProp(_el$44, "height", 1);
1906
+ _$setProp(_el$44, "flexShrink", 0);
1907
+ _$setProp(_el$44, "flexDirection", "row");
1908
+ _$setProp(_el$44, "justifyContent", "space-between");
1909
+ _$insertNode(_el$45, _el$46);
1910
+ _$insertNode(_el$46, _$createTextNode(`PR/MR status`));
1911
+ _$insertNode(_el$48, _$createTextNode(`esc`));
1912
+ _$setProp(_el$48, "onMouseUp", close);
1913
+ _$setProp(_el$50, "minHeight", 1);
1914
+ _$setProp(_el$50, "flexShrink", 0);
1915
+ _$setProp(_el$50, "scrollX", false);
1916
+ _$setProp(_el$50, "contentOptions", {
1688
1917
  flexShrink: 0
1689
1918
  });
1690
- _$insert(_el$53, _$createComponent(StatusDetails, {
1919
+ _$insert(_el$50, _$createComponent(StatusDetails, {
1691
1920
  get snapshot() {
1692
1921
  return snapshot2();
1693
1922
  }
1694
1923
  }));
1695
- _$setProp(_el$54, "height", 1);
1696
- _$setProp(_el$54, "flexShrink", 0);
1697
- _$setProp(_el$54, "flexDirection", "row");
1698
- _$setProp(_el$54, "justifyContent", "flex-end");
1699
- _$insert(_el$54, _$createComponent(For, {
1924
+ _$setProp(_el$51, "height", 1);
1925
+ _$setProp(_el$51, "flexShrink", 0);
1926
+ _$setProp(_el$51, "flexDirection", "row");
1927
+ _$setProp(_el$51, "justifyContent", "flex-end");
1928
+ _$insert(_el$51, _$createComponent(For, {
1700
1929
  each: ["close", "refresh"],
1701
1930
  children: (action) => {
1702
1931
  const disabled = () => action === "refresh" && snapshot2().loading;
1703
1932
  const active = () => activeAction() === action && !disabled();
1704
1933
  return (() => {
1705
- var _el$55 = _$createElement("box"), _el$56 = _$createElement("text");
1706
- _$insertNode(_el$55, _el$56);
1707
- _$setProp(_el$55, "paddingLeft", 1);
1708
- _$setProp(_el$55, "paddingRight", 1);
1709
- _$setProp(_el$55, "flexShrink", 0);
1710
- _$setProp(_el$55, "onMouseMove", () => {
1934
+ var _el$52 = _$createElement("box"), _el$53 = _$createElement("text");
1935
+ _$insertNode(_el$52, _el$53);
1936
+ _$setProp(_el$52, "paddingLeft", 1);
1937
+ _$setProp(_el$52, "paddingRight", 1);
1938
+ _$setProp(_el$52, "flexShrink", 0);
1939
+ _$setProp(_el$52, "onMouseMove", () => {
1711
1940
  if (!disabled())
1712
1941
  setActiveAction(action);
1713
1942
  });
1714
- _$setProp(_el$55, "onMouseUp", () => {
1943
+ _$setProp(_el$52, "onMouseUp", () => {
1715
1944
  if (disabled())
1716
1945
  return;
1717
1946
  setActiveAction(action);
@@ -1720,27 +1949,27 @@ var tui_default = {
1720
1949
  else
1721
1950
  close();
1722
1951
  });
1723
- _$setProp(_el$56, "wrapMode", "none");
1724
- _$insert(_el$56, () => action === "close" ? "Close" : snapshot2().loading ? "Refreshing\u2026" : "Refresh");
1952
+ _$setProp(_el$53, "wrapMode", "none");
1953
+ _$insert(_el$53, () => action === "close" ? "Close" : snapshot2().loading ? "Refreshing\u2026" : "Refresh");
1725
1954
  _$effect((_p$) => {
1726
- var _v$10 = active() ? context.theme.background.action.primary.focused : undefined, _v$11 = disabled() ? context.theme.text.action.primary.disabled : active() ? context.theme.text.action.primary.focused : context.theme.text.muted;
1727
- _v$10 !== _p$.e && (_p$.e = _$setProp(_el$55, "backgroundColor", _v$10, _p$.e));
1728
- _v$11 !== _p$.t && (_p$.t = _$setProp(_el$56, "fg", _v$11, _p$.t));
1955
+ var _v$9 = active() ? context.theme.background.action.primary.focused : undefined, _v$0 = disabled() ? context.theme.text.action.primary.disabled : active() ? context.theme.text.action.primary.focused : context.theme.text.muted;
1956
+ _v$9 !== _p$.e && (_p$.e = _$setProp(_el$52, "backgroundColor", _v$9, _p$.e));
1957
+ _v$0 !== _p$.t && (_p$.t = _$setProp(_el$53, "fg", _v$0, _p$.t));
1729
1958
  return _p$;
1730
1959
  }, {
1731
1960
  e: undefined,
1732
1961
  t: undefined
1733
1962
  });
1734
- return _el$55;
1963
+ return _el$52;
1735
1964
  })();
1736
1965
  }
1737
1966
  }));
1738
1967
  _$effect((_p$) => {
1739
- var _v$8 = contentHeight() + 5, _v$9 = context.theme.text.base, _v$0 = context.theme.text.muted, _v$1 = contentHeight();
1740
- _v$8 !== _p$.e && (_p$.e = _$setProp(_el$46, "height", _v$8, _p$.e));
1741
- _v$9 !== _p$.t && (_p$.t = _$setProp(_el$48, "fg", _v$9, _p$.t));
1742
- _v$0 !== _p$.a && (_p$.a = _$setProp(_el$51, "fg", _v$0, _p$.a));
1743
- _v$1 !== _p$.o && (_p$.o = _$setProp(_el$53, "height", _v$1, _p$.o));
1968
+ var _v$5 = contentHeight() + 5, _v$6 = context.theme.text.base, _v$7 = context.theme.text.muted, _v$8 = contentHeight();
1969
+ _v$5 !== _p$.e && (_p$.e = _$setProp(_el$43, "height", _v$5, _p$.e));
1970
+ _v$6 !== _p$.t && (_p$.t = _$setProp(_el$45, "fg", _v$6, _p$.t));
1971
+ _v$7 !== _p$.a && (_p$.a = _$setProp(_el$48, "fg", _v$7, _p$.a));
1972
+ _v$8 !== _p$.o && (_p$.o = _$setProp(_el$50, "height", _v$8, _p$.o));
1744
1973
  return _p$;
1745
1974
  }, {
1746
1975
  e: undefined,
@@ -1748,7 +1977,7 @@ var tui_default = {
1748
1977
  a: undefined,
1749
1978
  o: undefined
1750
1979
  });
1751
- return _el$46;
1980
+ return _el$43;
1752
1981
  })();
1753
1982
  }
1754
1983
  function showStatus(place = currentPlace()) {