@pepps233/mendr 0.3.0 → 0.4.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.
@@ -834,10 +834,13 @@ async function fetchPullRequestDetails(exec, repo, pr) {
834
834
  { cwd: repo }
835
835
  );
836
836
  const parsed = JSON.parse(result.stdout);
837
+ const comments = normalizeIssueComments(parsed.comments);
838
+ const reviewBodies = await fetchPullRequestReviewBodies(exec, repo, pr);
839
+ const reviewComments = await fetchPullRequestReviewComments(exec, repo, pr);
837
840
  return {
838
841
  title: typeof parsed.title === "string" ? parsed.title : "",
839
842
  body: typeof parsed.body === "string" ? parsed.body : "",
840
- comments: Array.isArray(parsed.comments) ? parsed.comments : []
843
+ comments: sortCommentsByCreatedAt([...comments, ...reviewBodies, ...reviewComments])
841
844
  };
842
845
  }
843
846
  async function fetchPullRequestDiff(exec, repo, pr) {
@@ -903,7 +906,114 @@ function renderReviewMarkdown(pr, details) {
903
906
  function renderComment(comment) {
904
907
  const author = comment.author?.login ?? "unknown";
905
908
  const body = comment.body?.trim() || "(empty comment)";
906
- return `- @${author}: ${body}`;
909
+ const context = renderCommentContext(comment);
910
+ return `- @${author}${context}: ${body}`;
911
+ }
912
+ async function fetchPullRequestReviewBodies(exec, repo, pr) {
913
+ const result = await execOk(
914
+ exec,
915
+ "gh",
916
+ ["api", "--paginate", "--slurp", `repos/{owner}/{repo}/pulls/${pr}/reviews`],
917
+ { cwd: repo }
918
+ );
919
+ return readGhApiArray(result.stdout).map(normalizeReviewBody).filter((comment) => comment !== void 0);
920
+ }
921
+ async function fetchPullRequestReviewComments(exec, repo, pr) {
922
+ const result = await execOk(
923
+ exec,
924
+ "gh",
925
+ ["api", "--paginate", "--slurp", `repos/{owner}/{repo}/pulls/${pr}/comments`],
926
+ { cwd: repo }
927
+ );
928
+ return readGhApiArray(result.stdout).filter(isRecord2).map(normalizeReviewComment);
929
+ }
930
+ function normalizeIssueComments(value) {
931
+ if (!Array.isArray(value)) {
932
+ return [];
933
+ }
934
+ return value.filter(isRecord2).map((comment) => ({
935
+ author: readAuthor(comment.author),
936
+ body: readString(comment, "body"),
937
+ createdAt: readString(comment, "createdAt") ?? readString(comment, "created_at"),
938
+ kind: "comment",
939
+ url: readString(comment, "url") ?? readString(comment, "html_url")
940
+ }));
941
+ }
942
+ function normalizeReviewBody(value) {
943
+ if (!isRecord2(value)) {
944
+ return void 0;
945
+ }
946
+ const body = readString(value, "body");
947
+ const url = readString(value, "html_url") ?? readString(value, "url");
948
+ if (!body && !url) {
949
+ return void 0;
950
+ }
951
+ return {
952
+ author: readAuthor(value.user) ?? readAuthor(value.author),
953
+ body,
954
+ createdAt: readString(value, "submitted_at") ?? readString(value, "submittedAt"),
955
+ kind: "review",
956
+ state: readString(value, "state"),
957
+ url
958
+ };
959
+ }
960
+ function normalizeReviewComment(value) {
961
+ return {
962
+ author: readAuthor(value.user) ?? readAuthor(value.author),
963
+ body: readString(value, "body"),
964
+ createdAt: readString(value, "created_at") ?? readString(value, "createdAt"),
965
+ kind: "review_comment",
966
+ line: readNumber(value, "line") ?? readNumber(value, "original_line"),
967
+ path: readString(value, "path"),
968
+ url: readString(value, "html_url") ?? readString(value, "url")
969
+ };
970
+ }
971
+ function readGhApiArray(stdout) {
972
+ const parsed = JSON.parse(stdout);
973
+ if (!Array.isArray(parsed)) {
974
+ return [];
975
+ }
976
+ if (parsed.every(Array.isArray)) {
977
+ return parsed.flat();
978
+ }
979
+ return parsed;
980
+ }
981
+ function sortCommentsByCreatedAt(comments) {
982
+ return comments.map((comment, index) => ({ comment, index })).sort((left, right) => {
983
+ const leftTime = readCommentTime(left.comment);
984
+ const rightTime = readCommentTime(right.comment);
985
+ if (leftTime === rightTime) {
986
+ return left.index - right.index;
987
+ }
988
+ return leftTime - rightTime;
989
+ }).map(({ comment }) => comment);
990
+ }
991
+ function readCommentTime(comment) {
992
+ const time = comment.createdAt ? Date.parse(comment.createdAt) : Number.NaN;
993
+ return Number.isFinite(time) ? time : Number.MAX_SAFE_INTEGER;
994
+ }
995
+ function renderCommentContext(comment) {
996
+ const parts = [];
997
+ if (comment.kind === "review") {
998
+ parts.push(comment.state ? `review ${comment.state.toLowerCase()}` : "review");
999
+ } else if (comment.kind === "review_comment") {
1000
+ parts.push(renderReviewCommentLocation(comment));
1001
+ } else {
1002
+ parts.push("comment");
1003
+ }
1004
+ if (comment.url) {
1005
+ parts.push(comment.url);
1006
+ }
1007
+ return ` (${parts.join(", ")})`;
1008
+ }
1009
+ function renderReviewCommentLocation(comment) {
1010
+ if (comment.path && comment.line !== void 0) {
1011
+ return `inline comment on ${comment.path}:${comment.line}`;
1012
+ }
1013
+ if (comment.path) {
1014
+ return `inline comment on ${comment.path}`;
1015
+ }
1016
+ return "inline comment";
907
1017
  }
908
1018
  function resolveBranchPushRemote(input) {
909
1019
  const headRepository = readRepositoryInfo(input.headRepository, input.headRepositoryOwner);
@@ -958,6 +1068,13 @@ function readOwnerLogin(value) {
958
1068
  }
959
1069
  return readString(value, "login");
960
1070
  }
1071
+ function readAuthor(value) {
1072
+ if (!isRecord2(value)) {
1073
+ return void 0;
1074
+ }
1075
+ const login = readString(value, "login");
1076
+ return login ? { login } : void 0;
1077
+ }
961
1078
  function normalizedGitUrl(url) {
962
1079
  if (!url) {
963
1080
  return void 0;
@@ -971,6 +1088,10 @@ function readString(value, key) {
971
1088
  const raw = value[key];
972
1089
  return typeof raw === "string" && raw.trim().length > 0 ? raw.trim() : void 0;
973
1090
  }
1091
+ function readNumber(value, key) {
1092
+ const raw = value[key];
1093
+ return typeof raw === "number" && Number.isFinite(raw) ? raw : void 0;
1094
+ }
974
1095
  function isRecord2(value) {
975
1096
  return typeof value === "object" && value !== null && !Array.isArray(value);
976
1097
  }
package/dist/cli.js CHANGED
@@ -26,7 +26,7 @@ import {
26
26
  worktreesDir,
27
27
  writeMeta,
28
28
  writeState
29
- } from "./chunk-3EH6IS7Z.js";
29
+ } from "./chunk-GKT5VC55.js";
30
30
 
31
31
  // src/cli.ts
32
32
  import { spawn as spawn2 } from "child_process";
package/dist/daemon.js CHANGED
@@ -28,7 +28,7 @@ import {
28
28
  stageAll,
29
29
  waitForPullRequestChecks,
30
30
  writeState
31
- } from "./chunk-3EH6IS7Z.js";
31
+ } from "./chunk-GKT5VC55.js";
32
32
 
33
33
  // src/orchestrator.ts
34
34
  import { mkdir, readFile, writeFile } from "fs/promises";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pepps233/mendr",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Autonomous pull request review agent CLI.",
5
5
  "type": "module",
6
6
  "bin": {