getgloss 0.12.3 → 0.13.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.
@@ -10,7 +10,7 @@ import path from "path";
10
10
  // package.json
11
11
  var package_default = {
12
12
  name: "getgloss",
13
- version: "0.12.3",
13
+ version: "0.13.0",
14
14
  description: "Local browser-based diff review for coding-agent loops.",
15
15
  type: "module",
16
16
  packageManager: "pnpm@10.33.2",
@@ -67,8 +67,8 @@ var package_default = {
67
67
  tsup: "8.5.1",
68
68
  tsx: "4.22.3",
69
69
  typescript: "5.9.3",
70
- vite: "6.4.2",
71
- vitest: "3.2.4"
70
+ vite: "6.4.3",
71
+ vitest: "3.2.6"
72
72
  },
73
73
  keywords: [
74
74
  "diff",
@@ -365,7 +365,13 @@ function isDiffLine(value) {
365
365
  return isRecord(value) && isOneOf(value.type, DIFF_LINE_TYPES) && isNullableNumber(value.oldLine) && isNullableNumber(value.newLine) && isString(value.content);
366
366
  }
367
367
  function isComment(value) {
368
- return isRecord(value) && isString(value.id) && isString(value.filePath) && isNumber(value.startLine) && isNumber(value.endLine) && isOneOf(value.side, SIDES) && isString(value.body) && isString(value.originalSnippet) && isString(value.createdAt);
368
+ if (!isRecord(value)) {
369
+ return false;
370
+ }
371
+ if (value.kind === "general") {
372
+ return isString(value.id) && isString(value.body) && isString(value.createdAt);
373
+ }
374
+ return isString(value.id) && (value.kind === void 0 || value.kind === "line") && isString(value.filePath) && isNumber(value.startLine) && isNumber(value.endLine) && isOneOf(value.side, SIDES) && isString(value.body) && isString(value.originalSnippet) && isString(value.createdAt);
369
375
  }
370
376
  function isResolvedComment(value) {
371
377
  return isRecord(value) && isString(value.commentId) && value.status === "resolved" && isOptionalString(value.summary) && isString(value.resolvedAt);
@@ -580,11 +586,28 @@ import { Hono } from "hono";
580
586
  import { streamSSE } from "hono/streaming";
581
587
 
582
588
  // src/shared/comments.ts
589
+ function isLineComment(comment) {
590
+ return comment.kind === void 0 || comment.kind === "line";
591
+ }
583
592
  function compareCommentsByLocation(a, b) {
593
+ const aIsLine = isLineComment(a);
594
+ const bIsLine = isLineComment(b);
595
+ if (!aIsLine || !bIsLine) {
596
+ if (aIsLine !== bIsLine) {
597
+ return aIsLine ? 1 : -1;
598
+ }
599
+ return a.createdAt.localeCompare(b.createdAt) || a.id.localeCompare(b.id);
600
+ }
584
601
  return a.filePath.localeCompare(b.filePath) || a.startLine - b.startLine || a.endLine - b.endLine || a.side.localeCompare(b.side);
585
602
  }
586
603
  function countCommentFiles(comments) {
587
- return new Set(comments.map((comment) => comment.filePath)).size;
604
+ const filePaths = /* @__PURE__ */ new Set();
605
+ for (const comment of comments) {
606
+ if (isLineComment(comment)) {
607
+ filePaths.add(comment.filePath);
608
+ }
609
+ }
610
+ return filePaths.size;
588
611
  }
589
612
  function formatLineRange(range, options = {}) {
590
613
  const startLine = Math.min(range.startLine, range.endLine);
@@ -781,6 +804,17 @@ function summarizeDiffFiles(files) {
781
804
  );
782
805
  }
783
806
 
807
+ // src/shared/file-order.ts
808
+ function compareFilePaths(leftPath, rightPath, leftTieBreaker = "", rightTieBreaker = "") {
809
+ return leftPath.localeCompare(rightPath, void 0, { sensitivity: "base" }) || leftPath.localeCompare(rightPath) || leftTieBreaker.localeCompare(rightTieBreaker, void 0, { sensitivity: "base" }) || leftTieBreaker.localeCompare(rightTieBreaker);
810
+ }
811
+ function compareDiffFiles(left, right) {
812
+ return compareFilePaths(left.path, right.path, left.oldPath ?? "", right.oldPath ?? "");
813
+ }
814
+ function sortDiffFiles(files) {
815
+ return files.toSorted(compareDiffFiles);
816
+ }
817
+
784
818
  // src/shared/git-diff.ts
785
819
  var DIFF_ARGS = ["diff", "--no-color", "--find-renames", "--find-copies"];
786
820
  async function git(args, cwd) {
@@ -789,7 +823,7 @@ async function git(args, cwd) {
789
823
  }
790
824
  async function captureCommitRangeDiff(fromSha, toSha, repoRoot) {
791
825
  const rawDiff = await git([...DIFF_ARGS, `${fromSha}^`, toSha, "--"], repoRoot);
792
- const files = parseUnifiedDiff(rawDiff);
826
+ const files = sortDiffFiles(parseUnifiedDiff(rawDiff));
793
827
  return {
794
828
  stats: summarizeDiffFiles(files),
795
829
  rawDiff,
@@ -1905,9 +1939,11 @@ function languageForSnippet(filePath, snippet) {
1905
1939
  }
1906
1940
  function serializeFeedbackMarkdown(bundle) {
1907
1941
  const comments = bundle.comments.toSorted(compareCommentsByLocation);
1942
+ const generalComments = comments.filter((comment) => !isLineComment(comment));
1943
+ const lineComments = comments.filter(isLineComment);
1908
1944
  const commentsByFile = /* @__PURE__ */ new Map();
1909
1945
  const files = [];
1910
- for (const comment of comments) {
1946
+ for (const comment of lineComments) {
1911
1947
  const fileComments = commentsByFile.get(comment.filePath);
1912
1948
  if (fileComments) {
1913
1949
  fileComments.push(comment);
@@ -1925,6 +1961,12 @@ function serializeFeedbackMarkdown(bundle) {
1925
1961
  `Files: ${files.length} Comments: ${comments.length}`,
1926
1962
  ""
1927
1963
  ];
1964
+ if (generalComments.length > 0) {
1965
+ lines.push("## General comments", "");
1966
+ for (const comment of generalComments) {
1967
+ lines.push(`### ${comment.id}`, comment.body.trim(), "");
1968
+ }
1969
+ }
1928
1970
  for (const filePath of files) {
1929
1971
  lines.push(`## ${filePath}`, "");
1930
1972
  for (const comment of commentsByFile.get(filePath) ?? []) {