glassbox 0.9.10 → 0.9.11-rc.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/README.md +6 -0
- package/dist/cli.js +35 -31
- package/dist/client/app.global.js +13 -12
- package/dist/client/history.global.js +6 -5
- package/dist/client/styles.css +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -341,6 +341,12 @@ npm link # Symlink for global 'glassbox' command
|
|
|
341
341
|
- **[Hot Sheet](https://github.com/brianwestphal/hotsheet)** — Lightweight local project management for AI-assisted development. Pairs well with Glassbox for tracking review feedback as actionable tickets.
|
|
342
342
|
- **[Changelog](CHANGELOG.md)** — Full release history
|
|
343
343
|
|
|
344
|
+
## Sponsor
|
|
345
|
+
|
|
346
|
+
Glassbox is free and open-source. If it saves you time on your AI workflow, consider sponsoring continued development:
|
|
347
|
+
|
|
348
|
+
[](https://github.com/sponsors/brianwestphal)
|
|
349
|
+
|
|
344
350
|
## License
|
|
345
351
|
|
|
346
352
|
MIT
|
package/dist/cli.js
CHANGED
|
@@ -3250,7 +3250,7 @@ async function generateReviewExport(reviewId, repoRoot, isCurrent) {
|
|
|
3250
3250
|
lines.push("# Code Review");
|
|
3251
3251
|
lines.push("");
|
|
3252
3252
|
lines.push(`- **Repository**: ${review.repo_name}`);
|
|
3253
|
-
lines.push(`- **Review mode**: ${review.mode}
|
|
3253
|
+
lines.push(`- **Review mode**: ${review.mode}`);
|
|
3254
3254
|
lines.push(`- **Review ID**: ${review.id}`);
|
|
3255
3255
|
lines.push(`- **Date**: ${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
3256
3256
|
lines.push(`- **Files reviewed**: ${files.filter((f) => f.status === "reviewed").length}/${files.length}`);
|
|
@@ -5704,23 +5704,40 @@ function Layout({ title, reviewId, children }) {
|
|
|
5704
5704
|
] });
|
|
5705
5705
|
}
|
|
5706
5706
|
|
|
5707
|
+
// src/utils/formatReviewMode.ts
|
|
5708
|
+
var FULL_SHA_RE = /^[0-9a-f]{40}$/i;
|
|
5709
|
+
function shortenIfSha(ref) {
|
|
5710
|
+
if (FULL_SHA_RE.test(ref)) return ref.slice(0, 7);
|
|
5711
|
+
return ref;
|
|
5712
|
+
}
|
|
5713
|
+
function argsFor(mode, prefix, modeArgs) {
|
|
5714
|
+
if (modeArgs !== null && modeArgs !== "") return modeArgs;
|
|
5715
|
+
if (mode.startsWith(prefix)) return mode.slice(prefix.length);
|
|
5716
|
+
return "";
|
|
5717
|
+
}
|
|
5718
|
+
function formatReviewMode(mode, modeArgs) {
|
|
5719
|
+
if (mode === "commit" || mode.startsWith("commit:")) {
|
|
5720
|
+
return `commit: ${shortenIfSha(argsFor(mode, "commit:", modeArgs))}`;
|
|
5721
|
+
}
|
|
5722
|
+
if (mode === "range" || mode.startsWith("range:")) {
|
|
5723
|
+
const raw = argsFor(mode, "range:", modeArgs);
|
|
5724
|
+
const [from = "", to = ""] = raw.split("..");
|
|
5725
|
+
return `range: ${shortenIfSha(from)}..${shortenIfSha(to)}`;
|
|
5726
|
+
}
|
|
5727
|
+
if (mode === "branch" || mode.startsWith("branch:")) {
|
|
5728
|
+
return `branch: ${argsFor(mode, "branch:", modeArgs)}`;
|
|
5729
|
+
}
|
|
5730
|
+
if (mode === "files" || mode.startsWith("files:")) {
|
|
5731
|
+
return `files: ${argsFor(mode, "files:", modeArgs)}`;
|
|
5732
|
+
}
|
|
5733
|
+
return mode;
|
|
5734
|
+
}
|
|
5735
|
+
|
|
5707
5736
|
// src/components/reviewHistory.tsx
|
|
5708
5737
|
import { jsx as jsx5, jsxs as jsxs5 } from "kerfjs/jsx-runtime";
|
|
5709
5738
|
function titleCase(s) {
|
|
5710
5739
|
return s.replace(/[_-]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
5711
5740
|
}
|
|
5712
|
-
function shortenArgs(args) {
|
|
5713
|
-
const shaPattern = /\b([0-9a-f]{7,40})\b/gi;
|
|
5714
|
-
const result = { hasLong: false };
|
|
5715
|
-
const short = args.replace(shaPattern, (match) => {
|
|
5716
|
-
if (match.length > 8) {
|
|
5717
|
-
result.hasLong = true;
|
|
5718
|
-
return match.slice(0, 7);
|
|
5719
|
-
}
|
|
5720
|
-
return match;
|
|
5721
|
-
});
|
|
5722
|
-
return { short, full: result.hasLong ? args : "" };
|
|
5723
|
-
}
|
|
5724
5741
|
function ReviewHistory({ reviews, currentReviewId }) {
|
|
5725
5742
|
const hasOtherReviews = reviews.some((r) => r.id !== currentReviewId);
|
|
5726
5743
|
const hasCompletedOthers = reviews.some((r) => r.id !== currentReviewId && r.status === "completed");
|
|
@@ -5729,24 +5746,14 @@ function ReviewHistory({ reviews, currentReviewId }) {
|
|
|
5729
5746
|
reviews.length === 0 ? /* @__PURE__ */ jsx5("p", { style: "color:var(--text-dim)", children: "No previous reviews found." }) : /* @__PURE__ */ jsx5("div", { children: reviews.map((r) => {
|
|
5730
5747
|
const isCurrent = r.id === currentReviewId;
|
|
5731
5748
|
const href = isCurrent ? "/" : `/review/${r.id}`;
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
const { short, full } = shortenArgs(r.mode_args);
|
|
5735
|
-
argsDisplay = full !== "" ? /* @__PURE__ */ jsxs5("span", { title: full, children: [
|
|
5736
|
-
": ",
|
|
5737
|
-
short
|
|
5738
|
-
] }) : /* @__PURE__ */ jsxs5("span", { children: [
|
|
5739
|
-
": ",
|
|
5740
|
-
short
|
|
5741
|
-
] });
|
|
5742
|
-
}
|
|
5749
|
+
const modeLabel = titleCase(formatReviewMode(r.mode, r.mode_args));
|
|
5750
|
+
const fullArgs = r.mode_args !== null && r.mode_args !== "" && /[0-9a-f]{40}/i.test(r.mode_args) ? r.mode_args : "";
|
|
5743
5751
|
return /* @__PURE__ */ jsxs5("div", { children: [
|
|
5744
5752
|
/* @__PURE__ */ jsx5("a", { href, className: "history-item-link", children: /* @__PURE__ */ jsxs5("div", { className: "history-item", "data-review-id": r.id, children: [
|
|
5745
5753
|
/* @__PURE__ */ jsxs5("h3", { children: [
|
|
5746
5754
|
r.repo_name,
|
|
5747
5755
|
" - ",
|
|
5748
|
-
|
|
5749
|
-
argsDisplay,
|
|
5756
|
+
fullArgs !== "" ? /* @__PURE__ */ jsx5("span", { title: fullArgs, children: modeLabel }) : modeLabel,
|
|
5750
5757
|
isCurrent ? /* @__PURE__ */ jsx5("span", { className: "status-badge in_progress", style: "margin-left:8px", children: "Current" }) : null,
|
|
5751
5758
|
/* @__PURE__ */ jsx5("span", { className: `status-badge ${r.status}`, style: "margin-left:8px", children: titleCase(r.status) })
|
|
5752
5759
|
] }),
|
|
@@ -5874,10 +5881,7 @@ function ReviewShell({ reviewId, review, files, annotationCounts, staleCounts, f
|
|
|
5874
5881
|
/* @__PURE__ */ jsxs7("aside", { className: "sidebar", children: [
|
|
5875
5882
|
/* @__PURE__ */ jsxs7("div", { className: "sidebar-header", children: [
|
|
5876
5883
|
/* @__PURE__ */ jsx7("h2", { children: review.repo_name }),
|
|
5877
|
-
/* @__PURE__ */
|
|
5878
|
-
review.mode,
|
|
5879
|
-
review.mode_args !== null && review.mode_args !== "" ? `: ${review.mode_args}` : ""
|
|
5880
|
-
] })
|
|
5884
|
+
/* @__PURE__ */ jsx7("span", { className: "review-mode", children: formatReviewMode(review.mode, review.mode_args) })
|
|
5881
5885
|
] }),
|
|
5882
5886
|
/* @__PURE__ */ jsx7("div", { className: "file-filter", children: /* @__PURE__ */ jsx7("input", { type: "text", className: "file-filter-input", id: "file-filter", placeholder: "Filter files..." }) }),
|
|
5883
5887
|
/* @__PURE__ */ jsx7(FileList, { files, annotationCounts, staleCounts }),
|
|
@@ -6670,7 +6674,7 @@ async function main() {
|
|
|
6670
6674
|
console.log("AI service test mode enabled \u2014 using mock AI responses");
|
|
6671
6675
|
}
|
|
6672
6676
|
if (debug) {
|
|
6673
|
-
console.log(`[debug] Build timestamp: ${"2026-05-
|
|
6677
|
+
console.log(`[debug] Build timestamp: ${"2026-05-22T07:55:40.035Z"}`);
|
|
6674
6678
|
}
|
|
6675
6679
|
if (projectDir !== null) {
|
|
6676
6680
|
process.chdir(projectDir);
|