glassbox 0.3.0 → 0.3.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 CHANGED
@@ -65,13 +65,13 @@ Glassbox gives you a proper diff viewer with annotation categories designed for
65
65
  | **Note** | Context for the AI to consider. |
66
66
  | **Remember** | A rule to persist to the AI's long-term config. |
67
67
 
68
- When you're done, click **Complete Review** and tell your AI tool:
68
+ As you annotate, `.glassbox/latest-review.md` is updated automatically. You can tell your AI tool at any time:
69
69
 
70
70
  ```
71
71
  Read .glassbox/latest-review.md and apply the feedback.
72
72
  ```
73
73
 
74
- The AI gets a structured file with every annotation, organized by file and line number, with clear instructions on how to interpret each category. It fixes the bugs, applies your style preferences, avoids the anti-patterns, and updates its own config with your "remember" items.
74
+ The AI gets a structured file with every annotation, organized by file and line number, with clear instructions on how to interpret each category. It fixes the bugs, applies your style preferences, avoids the anti-patterns, and updates its own config with your "remember" items. You don't need to formally "complete" a review to share feedback — just annotate and switch to your AI tool.
75
75
 
76
76
  Then you run `glassbox` again. Your previous annotations carry forward — matched to the updated diff. Stale comments that no longer apply are flagged so you can keep or discard them. The loop continues until you're satisfied.
77
77
 
package/dist/cli.js CHANGED
@@ -3083,6 +3083,17 @@ async function generateReviewExport(reviewId, repoRoot, isCurrent) {
3083
3083
  return archivePath;
3084
3084
  }
3085
3085
 
3086
+ // src/export/auto-export.ts
3087
+ var debounceTimer = null;
3088
+ var DEBOUNCE_MS = 2e3;
3089
+ function scheduleAutoExport(reviewId, repoRoot) {
3090
+ if (debounceTimer !== null) clearTimeout(debounceTimer);
3091
+ debounceTimer = setTimeout(() => {
3092
+ debounceTimer = null;
3093
+ void generateReviewExport(reviewId, repoRoot, true);
3094
+ }, DEBOUNCE_MS);
3095
+ }
3096
+
3086
3097
  // src/git/image.ts
3087
3098
  import { execSync as execSync4 } from "child_process";
3088
3099
  import { readFileSync as readFileSync5 } from "fs";
@@ -3704,6 +3715,9 @@ apiRoutes.patch("/files/:fileId/status", async (c) => {
3704
3715
  await updateFileStatus(c.req.param("fileId"), status);
3705
3716
  return c.json({ ok: true });
3706
3717
  });
3718
+ function autoExport(c) {
3719
+ scheduleAutoExport(c.get("reviewId"), c.get("repoRoot"));
3720
+ }
3707
3721
  apiRoutes.post("/annotations", async (c) => {
3708
3722
  const body = await c.req.json();
3709
3723
  const annotation = await addAnnotation(
@@ -3713,34 +3727,41 @@ apiRoutes.post("/annotations", async (c) => {
3713
3727
  body.category,
3714
3728
  body.content
3715
3729
  );
3730
+ autoExport(c);
3716
3731
  return c.json(annotation, 201);
3717
3732
  });
3718
3733
  apiRoutes.patch("/annotations/:id", async (c) => {
3719
3734
  const { content, category } = await c.req.json();
3720
3735
  await updateAnnotation(c.req.param("id"), content, category);
3736
+ autoExport(c);
3721
3737
  return c.json({ ok: true });
3722
3738
  });
3723
3739
  apiRoutes.delete("/annotations/:id", async (c) => {
3724
3740
  await deleteAnnotation(c.req.param("id"));
3741
+ autoExport(c);
3725
3742
  return c.json({ ok: true });
3726
3743
  });
3727
3744
  apiRoutes.patch("/annotations/:id/move", async (c) => {
3728
3745
  const { lineNumber, side } = await c.req.json();
3729
3746
  await moveAnnotation(c.req.param("id"), lineNumber, side);
3747
+ autoExport(c);
3730
3748
  return c.json({ ok: true });
3731
3749
  });
3732
3750
  apiRoutes.post("/annotations/:id/keep", async (c) => {
3733
3751
  await markAnnotationCurrent(c.req.param("id"));
3752
+ autoExport(c);
3734
3753
  return c.json({ ok: true });
3735
3754
  });
3736
3755
  apiRoutes.post("/annotations/stale/delete-all", async (c) => {
3737
3756
  const reviewId = resolveReviewId(c);
3738
3757
  await deleteStaleAnnotations(reviewId);
3758
+ autoExport(c);
3739
3759
  return c.json({ ok: true });
3740
3760
  });
3741
3761
  apiRoutes.post("/annotations/stale/keep-all", async (c) => {
3742
3762
  const reviewId = resolveReviewId(c);
3743
3763
  await keepAllStaleAnnotations(reviewId);
3764
+ autoExport(c);
3744
3765
  return c.json({ ok: true });
3745
3766
  });
3746
3767
  apiRoutes.get("/annotations/all", async (c) => {
@@ -3955,16 +3976,14 @@ function ImageDiff({ file, diff }) {
3955
3976
  /* @__PURE__ */ jsx("div", { className: "slice-handle slice-handle-a" }),
3956
3977
  /* @__PURE__ */ jsx("div", { className: "slice-handle slice-handle-b" })
3957
3978
  ] }) }),
3958
- !hasComparison && /* @__PURE__ */ jsx("div", { className: "image-diff-single", children: [
3959
- /* @__PURE__ */ jsx(
3960
- "img",
3961
- {
3962
- src: `/api/image/${fileId}/${isAdded ? "new" : "old"}`,
3963
- alt: isAdded ? "New image" : "Deleted image"
3964
- }
3965
- ),
3966
- /* @__PURE__ */ jsx("p", { className: "image-diff-status", children: isAdded ? "New file" : "Deleted file" })
3967
- ] })
3979
+ !hasComparison && /* @__PURE__ */ jsx("div", { className: "image-diff-panel image-diff-visual", "data-panel": "image", children: /* @__PURE__ */ jsx("div", { className: "image-visual-canvas", "data-zoomable": "true", children: /* @__PURE__ */ jsx("div", { className: "image-zoom-wrap", children: /* @__PURE__ */ jsx(
3980
+ "img",
3981
+ {
3982
+ className: "image-layer image-layer-old",
3983
+ src: `/api/image/${fileId}/${isAdded ? "new" : "old"}`,
3984
+ alt: isAdded ? "New image" : "Deleted image"
3985
+ }
3986
+ ) }) }) })
3968
3987
  ]
3969
3988
  }
3970
3989
  );
@@ -4526,55 +4545,58 @@ pageRoutes.get("/", async (c) => {
4526
4545
  /* @__PURE__ */ jsx("button", { id: "update-banner-dismiss", className: "btn btn-sm", children: "Later" })
4527
4546
  ] })
4528
4547
  ] }),
4529
- /* @__PURE__ */ jsx("aside", { className: "sidebar", children: [
4530
- /* @__PURE__ */ jsx("div", { className: "sidebar-header", children: [
4531
- /* @__PURE__ */ jsx("h2", { children: review.repo_name }),
4532
- /* @__PURE__ */ jsx("span", { className: "review-mode", children: [
4533
- review.mode,
4534
- review.mode_args !== null && review.mode_args !== "" ? `: ${review.mode_args}` : ""
4548
+ /* @__PURE__ */ jsx("div", { className: "review-body", children: [
4549
+ /* @__PURE__ */ jsx("aside", { className: "sidebar", children: [
4550
+ /* @__PURE__ */ jsx("div", { className: "sidebar-header", children: [
4551
+ /* @__PURE__ */ jsx("h2", { children: review.repo_name }),
4552
+ /* @__PURE__ */ jsx("span", { className: "review-mode", children: [
4553
+ review.mode,
4554
+ review.mode_args !== null && review.mode_args !== "" ? `: ${review.mode_args}` : ""
4555
+ ] })
4556
+ ] }),
4557
+ /* @__PURE__ */ jsx("div", { className: "file-filter", children: /* @__PURE__ */ jsx("input", { type: "text", className: "file-filter-input", id: "file-filter", placeholder: "Filter files..." }) }),
4558
+ /* @__PURE__ */ jsx(FileList, { files, annotationCounts, staleCounts: {} }),
4559
+ /* @__PURE__ */ jsx("div", { className: "sidebar-footer", children: [
4560
+ /* @__PURE__ */ jsx("button", { className: "btn btn-primary btn-complete", id: "complete-review", children: "Complete Review" }),
4561
+ /* @__PURE__ */ jsx("a", { href: "/history", className: "btn btn-sm btn-link", children: "Review History" })
4535
4562
  ] })
4536
4563
  ] }),
4537
- /* @__PURE__ */ jsx("div", { className: "file-filter", children: /* @__PURE__ */ jsx("input", { type: "text", className: "file-filter-input", id: "file-filter", placeholder: "Filter files..." }) }),
4538
- /* @__PURE__ */ jsx(FileList, { files, annotationCounts, staleCounts: {} }),
4539
- /* @__PURE__ */ jsx("div", { className: "sidebar-footer", children: [
4540
- /* @__PURE__ */ jsx("button", { className: "btn btn-primary btn-complete", id: "complete-review", children: "Complete Review" }),
4541
- /* @__PURE__ */ jsx("a", { href: "/history", className: "btn btn-sm btn-link", children: "Review History" })
4542
- ] })
4543
- ] }),
4544
- /* @__PURE__ */ jsx("div", { className: "sidebar-resize", id: "sidebar-resize" }),
4545
- /* @__PURE__ */ jsx("main", { className: "main-content", children: [
4546
- /* @__PURE__ */ jsx("div", { className: "welcome-message", children: [
4547
- /* @__PURE__ */ jsx("h3", { children: "Select a file to begin reviewing" }),
4548
- /* @__PURE__ */ jsx("p", { children: [
4549
- files.length,
4550
- " file(s) to review"
4564
+ /* @__PURE__ */ jsx("div", { className: "sidebar-resize", id: "sidebar-resize" }),
4565
+ /* @__PURE__ */ jsx("main", { className: "main-content", children: [
4566
+ /* @__PURE__ */ jsx("div", { className: "welcome-message", children: [
4567
+ /* @__PURE__ */ jsx("h3", { children: "Select a file to begin reviewing" }),
4568
+ /* @__PURE__ */ jsx("p", { children: [
4569
+ files.length,
4570
+ " file(s) to review"
4571
+ ] }),
4572
+ /* @__PURE__ */ jsx("p", { className: "progress-summary", id: "progress-summary" })
4551
4573
  ] }),
4552
- /* @__PURE__ */ jsx("p", { className: "progress-summary", id: "progress-summary" })
4553
- ] }),
4554
- /* @__PURE__ */ jsx("div", { className: "diff-container", id: "diff-container", style: "display:none" }),
4555
- /* @__PURE__ */ jsx("div", { className: "diff-toolbar", id: "diff-toolbar", style: "display:none", children: [
4556
- /* @__PURE__ */ jsx("div", { className: "diff-toolbar-text", children: [
4557
- /* @__PURE__ */ jsx("div", { className: "diff-toolbar-left", children: [
4558
- /* @__PURE__ */ jsx("div", { className: "segmented-control", children: [
4559
- /* @__PURE__ */ jsx("button", { className: "segment active", "data-diff-mode": "split", children: "Split" }),
4560
- /* @__PURE__ */ jsx("button", { className: "segment", "data-diff-mode": "unified", children: "Unified" })
4574
+ /* @__PURE__ */ jsx("div", { className: "diff-container", id: "diff-container", style: "display:none" }),
4575
+ /* @__PURE__ */ jsx("div", { className: "diff-toolbar", id: "diff-toolbar", style: "display:none", children: [
4576
+ /* @__PURE__ */ jsx("div", { className: "diff-toolbar-text", children: [
4577
+ /* @__PURE__ */ jsx("div", { className: "diff-toolbar-left", children: [
4578
+ /* @__PURE__ */ jsx("div", { className: "segmented-control", children: [
4579
+ /* @__PURE__ */ jsx("button", { className: "segment active", "data-diff-mode": "split", children: "Split" }),
4580
+ /* @__PURE__ */ jsx("button", { className: "segment", "data-diff-mode": "unified", children: "Unified" })
4581
+ ] }),
4582
+ /* @__PURE__ */ jsx("button", { className: "toolbar-btn", id: "wrap-toggle", children: "Wrap" }),
4583
+ /* @__PURE__ */ jsx("button", { className: "toolbar-btn", id: "whitespace-toggle", children: "Ignore Whitespace" })
4561
4584
  ] }),
4562
- /* @__PURE__ */ jsx("button", { className: "toolbar-btn", id: "wrap-toggle", children: "Wrap" }),
4563
- /* @__PURE__ */ jsx("button", { className: "toolbar-btn", id: "whitespace-toggle", children: "Ignore Whitespace" })
4585
+ /* @__PURE__ */ jsx("div", { className: "diff-toolbar-right", children: /* @__PURE__ */ jsx("button", { className: "toolbar-btn", id: "language-btn", children: "Plain Text" }) })
4564
4586
  ] }),
4565
- /* @__PURE__ */ jsx("div", { className: "diff-toolbar-right", children: /* @__PURE__ */ jsx("button", { className: "toolbar-btn", id: "language-btn", children: "Plain Text" }) })
4566
- ] }),
4567
- /* @__PURE__ */ jsx("div", { className: "diff-toolbar-image", style: "display:none", children: [
4568
- /* @__PURE__ */ jsx("div", { className: "diff-toolbar-left", children: /* @__PURE__ */ jsx("div", { className: "segmented-control", children: [
4569
- /* @__PURE__ */ jsx("button", { className: "segment active", "data-image-mode": "metadata", children: "Metadata" }),
4570
- /* @__PURE__ */ jsx("button", { className: "segment", "data-image-mode": "difference", children: "Difference" }),
4571
- /* @__PURE__ */ jsx("button", { className: "segment", "data-image-mode": "slice", children: "Slice" })
4572
- ] }) }),
4573
- /* @__PURE__ */ jsx("div", { className: "diff-toolbar-right", children: [
4574
- /* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "out", title: "Zoom out", children: raw(zoomOutSvg) }),
4575
- /* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "fit", title: "Fit to view", children: raw(fitSvg) }),
4576
- /* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "actual", title: "Actual size (1:1)", children: raw(actualSizeSvg) }),
4577
- /* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "in", title: "Zoom in", children: raw(zoomInSvg) })
4587
+ /* @__PURE__ */ jsx("div", { className: "diff-toolbar-image", style: "display:none", children: [
4588
+ /* @__PURE__ */ jsx("div", { className: "diff-toolbar-left", children: /* @__PURE__ */ jsx("div", { className: "segmented-control", children: [
4589
+ /* @__PURE__ */ jsx("button", { className: "segment active", "data-image-mode": "metadata", children: "Metadata" }),
4590
+ /* @__PURE__ */ jsx("button", { className: "segment", "data-image-mode": "difference", children: "Difference" }),
4591
+ /* @__PURE__ */ jsx("button", { className: "segment", "data-image-mode": "slice", children: "Slice" }),
4592
+ /* @__PURE__ */ jsx("button", { className: "segment", "data-image-mode": "image", style: "display:none", children: "Image" })
4593
+ ] }) }),
4594
+ /* @__PURE__ */ jsx("div", { className: "diff-toolbar-right", children: [
4595
+ /* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "out", title: "Zoom out", children: raw(zoomOutSvg) }),
4596
+ /* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "fit", title: "Fit to view", children: raw(fitSvg) }),
4597
+ /* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "actual", title: "Actual size (1:1)", children: raw(actualSizeSvg) }),
4598
+ /* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "in", title: "Zoom in", children: raw(zoomInSvg) })
4599
+ ] })
4578
4600
  ] })
4579
4601
  ] })
4580
4602
  ] })
@@ -4626,56 +4648,59 @@ pageRoutes.get("/review/:reviewId", async (c) => {
4626
4648
  /* @__PURE__ */ jsx("button", { id: "update-banner-dismiss", className: "btn btn-sm", children: "Later" })
4627
4649
  ] })
4628
4650
  ] }),
4629
- /* @__PURE__ */ jsx("aside", { className: "sidebar", children: [
4630
- /* @__PURE__ */ jsx("div", { className: "sidebar-header", children: [
4631
- /* @__PURE__ */ jsx("h2", { children: review.repo_name }),
4632
- /* @__PURE__ */ jsx("span", { className: "review-mode", children: [
4633
- review.mode,
4634
- review.mode_args !== null && review.mode_args !== "" ? `: ${review.mode_args}` : ""
4651
+ /* @__PURE__ */ jsx("div", { className: "review-body", children: [
4652
+ /* @__PURE__ */ jsx("aside", { className: "sidebar", children: [
4653
+ /* @__PURE__ */ jsx("div", { className: "sidebar-header", children: [
4654
+ /* @__PURE__ */ jsx("h2", { children: review.repo_name }),
4655
+ /* @__PURE__ */ jsx("span", { className: "review-mode", children: [
4656
+ review.mode,
4657
+ review.mode_args !== null && review.mode_args !== "" ? `: ${review.mode_args}` : ""
4658
+ ] })
4659
+ ] }),
4660
+ /* @__PURE__ */ jsx("div", { className: "file-filter", children: /* @__PURE__ */ jsx("input", { type: "text", className: "file-filter-input", id: "file-filter", placeholder: "Filter files..." }) }),
4661
+ /* @__PURE__ */ jsx(FileList, { files, annotationCounts, staleCounts: {} }),
4662
+ /* @__PURE__ */ jsx("div", { className: "sidebar-footer", children: [
4663
+ review.status === "completed" ? /* @__PURE__ */ jsx("button", { className: "btn btn-primary", id: "reopen-review", children: "Reopen Review" }) : /* @__PURE__ */ jsx("button", { className: "btn btn-primary btn-complete", id: "complete-review", children: "Complete Review" }),
4664
+ /* @__PURE__ */ jsx("a", { href: "/history", className: "btn btn-sm btn-link", children: "Review History" }),
4665
+ /* @__PURE__ */ jsx("a", { href: "/", className: "btn btn-sm btn-link", children: "Back to current review" })
4635
4666
  ] })
4636
4667
  ] }),
4637
- /* @__PURE__ */ jsx("div", { className: "file-filter", children: /* @__PURE__ */ jsx("input", { type: "text", className: "file-filter-input", id: "file-filter", placeholder: "Filter files..." }) }),
4638
- /* @__PURE__ */ jsx(FileList, { files, annotationCounts, staleCounts: {} }),
4639
- /* @__PURE__ */ jsx("div", { className: "sidebar-footer", children: [
4640
- review.status === "completed" ? /* @__PURE__ */ jsx("button", { className: "btn btn-primary", id: "reopen-review", children: "Reopen Review" }) : /* @__PURE__ */ jsx("button", { className: "btn btn-primary btn-complete", id: "complete-review", children: "Complete Review" }),
4641
- /* @__PURE__ */ jsx("a", { href: "/history", className: "btn btn-sm btn-link", children: "Review History" }),
4642
- /* @__PURE__ */ jsx("a", { href: "/", className: "btn btn-sm btn-link", children: "Back to current review" })
4643
- ] })
4644
- ] }),
4645
- /* @__PURE__ */ jsx("div", { className: "sidebar-resize", id: "sidebar-resize" }),
4646
- /* @__PURE__ */ jsx("main", { className: "main-content", children: [
4647
- /* @__PURE__ */ jsx("div", { className: "welcome-message", children: [
4648
- /* @__PURE__ */ jsx("h3", { children: "Select a file to begin reviewing" }),
4649
- /* @__PURE__ */ jsx("p", { children: [
4650
- files.length,
4651
- " file(s) to review"
4668
+ /* @__PURE__ */ jsx("div", { className: "sidebar-resize", id: "sidebar-resize" }),
4669
+ /* @__PURE__ */ jsx("main", { className: "main-content", children: [
4670
+ /* @__PURE__ */ jsx("div", { className: "welcome-message", children: [
4671
+ /* @__PURE__ */ jsx("h3", { children: "Select a file to begin reviewing" }),
4672
+ /* @__PURE__ */ jsx("p", { children: [
4673
+ files.length,
4674
+ " file(s) to review"
4675
+ ] }),
4676
+ /* @__PURE__ */ jsx("p", { className: "progress-summary", id: "progress-summary" })
4652
4677
  ] }),
4653
- /* @__PURE__ */ jsx("p", { className: "progress-summary", id: "progress-summary" })
4654
- ] }),
4655
- /* @__PURE__ */ jsx("div", { className: "diff-container", id: "diff-container", style: "display:none" }),
4656
- /* @__PURE__ */ jsx("div", { className: "diff-toolbar", id: "diff-toolbar", style: "display:none", children: [
4657
- /* @__PURE__ */ jsx("div", { className: "diff-toolbar-text", children: [
4658
- /* @__PURE__ */ jsx("div", { className: "diff-toolbar-left", children: [
4659
- /* @__PURE__ */ jsx("div", { className: "segmented-control", children: [
4660
- /* @__PURE__ */ jsx("button", { className: "segment active", "data-diff-mode": "split", children: "Split" }),
4661
- /* @__PURE__ */ jsx("button", { className: "segment", "data-diff-mode": "unified", children: "Unified" })
4678
+ /* @__PURE__ */ jsx("div", { className: "diff-container", id: "diff-container", style: "display:none" }),
4679
+ /* @__PURE__ */ jsx("div", { className: "diff-toolbar", id: "diff-toolbar", style: "display:none", children: [
4680
+ /* @__PURE__ */ jsx("div", { className: "diff-toolbar-text", children: [
4681
+ /* @__PURE__ */ jsx("div", { className: "diff-toolbar-left", children: [
4682
+ /* @__PURE__ */ jsx("div", { className: "segmented-control", children: [
4683
+ /* @__PURE__ */ jsx("button", { className: "segment active", "data-diff-mode": "split", children: "Split" }),
4684
+ /* @__PURE__ */ jsx("button", { className: "segment", "data-diff-mode": "unified", children: "Unified" })
4685
+ ] }),
4686
+ /* @__PURE__ */ jsx("button", { className: "toolbar-btn", id: "wrap-toggle", children: "Wrap" }),
4687
+ /* @__PURE__ */ jsx("button", { className: "toolbar-btn", id: "whitespace-toggle", children: "Ignore Whitespace" })
4662
4688
  ] }),
4663
- /* @__PURE__ */ jsx("button", { className: "toolbar-btn", id: "wrap-toggle", children: "Wrap" }),
4664
- /* @__PURE__ */ jsx("button", { className: "toolbar-btn", id: "whitespace-toggle", children: "Ignore Whitespace" })
4689
+ /* @__PURE__ */ jsx("div", { className: "diff-toolbar-right", children: /* @__PURE__ */ jsx("button", { className: "toolbar-btn", id: "language-btn", children: "Plain Text" }) })
4665
4690
  ] }),
4666
- /* @__PURE__ */ jsx("div", { className: "diff-toolbar-right", children: /* @__PURE__ */ jsx("button", { className: "toolbar-btn", id: "language-btn", children: "Plain Text" }) })
4667
- ] }),
4668
- /* @__PURE__ */ jsx("div", { className: "diff-toolbar-image", style: "display:none", children: [
4669
- /* @__PURE__ */ jsx("div", { className: "diff-toolbar-left", children: /* @__PURE__ */ jsx("div", { className: "segmented-control", children: [
4670
- /* @__PURE__ */ jsx("button", { className: "segment active", "data-image-mode": "metadata", children: "Metadata" }),
4671
- /* @__PURE__ */ jsx("button", { className: "segment", "data-image-mode": "difference", children: "Difference" }),
4672
- /* @__PURE__ */ jsx("button", { className: "segment", "data-image-mode": "slice", children: "Slice" })
4673
- ] }) }),
4674
- /* @__PURE__ */ jsx("div", { className: "diff-toolbar-right", children: [
4675
- /* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "out", title: "Zoom out", children: raw(zoomOutSvg) }),
4676
- /* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "fit", title: "Fit to view", children: raw(fitSvg) }),
4677
- /* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "actual", title: "Actual size (1:1)", children: raw(actualSizeSvg) }),
4678
- /* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "in", title: "Zoom in", children: raw(zoomInSvg) })
4691
+ /* @__PURE__ */ jsx("div", { className: "diff-toolbar-image", style: "display:none", children: [
4692
+ /* @__PURE__ */ jsx("div", { className: "diff-toolbar-left", children: /* @__PURE__ */ jsx("div", { className: "segmented-control", children: [
4693
+ /* @__PURE__ */ jsx("button", { className: "segment active", "data-image-mode": "metadata", children: "Metadata" }),
4694
+ /* @__PURE__ */ jsx("button", { className: "segment", "data-image-mode": "difference", children: "Difference" }),
4695
+ /* @__PURE__ */ jsx("button", { className: "segment", "data-image-mode": "slice", children: "Slice" }),
4696
+ /* @__PURE__ */ jsx("button", { className: "segment", "data-image-mode": "image", style: "display:none", children: "Image" })
4697
+ ] }) }),
4698
+ /* @__PURE__ */ jsx("div", { className: "diff-toolbar-right", children: [
4699
+ /* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "out", title: "Zoom out", children: raw(zoomOutSvg) }),
4700
+ /* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "fit", title: "Fit to view", children: raw(fitSvg) }),
4701
+ /* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "actual", title: "Actual size (1:1)", children: raw(actualSizeSvg) }),
4702
+ /* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "in", title: "Zoom in", children: raw(zoomInSvg) })
4703
+ ] })
4679
4704
  ] })
4680
4705
  ] })
4681
4706
  ] })
@@ -5129,7 +5154,7 @@ async function main() {
5129
5154
  console.log("AI service test mode enabled \u2014 using mock AI responses");
5130
5155
  }
5131
5156
  if (debug) {
5132
- console.log(`[debug] Build timestamp: ${"2026-03-16T07:44:26.425Z"}`);
5157
+ console.log(`[debug] Build timestamp: ${"2026-03-16T09:22:20.931Z"}`);
5133
5158
  }
5134
5159
  if (projectDir) {
5135
5160
  process.chdir(projectDir);