critique 0.1.119 → 0.1.121
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/dist/agentation-widget.js +39 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +29 -3
- package/dist/diff-utils.d.ts.map +1 -1
- package/dist/diff-utils.js +23 -0
- package/dist/diff-utils.test.js +35 -0
- package/dist/hooks/use-copy-selection.d.ts.map +1 -1
- package/dist/hooks/use-copy-selection.js +8 -7
- package/dist/image.d.ts +1 -0
- package/dist/image.d.ts.map +1 -1
- package/dist/image.js +1 -0
- package/dist/routes/annotations-context.d.ts +0 -1
- package/dist/routes/annotations-context.d.ts.map +1 -1
- package/dist/routes/annotations-context.js +46 -41
- package/dist/web-utils.d.ts +29 -1
- package/dist/web-utils.d.ts.map +1 -1
- package/dist/web-utils.js +199 -59
- package/dist/web-utils.test.js +119 -1
- package/dist/worker.d.ts.map +1 -1
- package/dist/worker.js +56 -13
- package/package.json +3 -3
- package/public/agentation-widget.js +49 -3
- package/src/.test-stdin-pager-tmp/binary.diff +3 -0
- package/src/.test-stdin-pager-tmp/colored.diff +8 -0
- package/src/.test-stdin-pager-tmp/context-only.diff +7 -0
- package/src/.test-stdin-pager-tmp/delete.diff +9 -0
- package/src/.test-stdin-pager-tmp/empty.diff +0 -0
- package/src/.test-stdin-pager-tmp/large.diff +19 -0
- package/src/.test-stdin-pager-tmp/multi.diff +20 -0
- package/src/.test-stdin-pager-tmp/newfile.diff +12 -0
- package/src/.test-stdin-pager-tmp/rename.diff +11 -0
- package/src/.test-stdin-pager-tmp/single.diff +8 -0
- package/src/agentation-widget.tsx +42 -0
- package/src/cli.tsx +29 -2
- package/src/diff-utils.test.ts +42 -0
- package/src/diff-utils.ts +24 -0
- package/src/hooks/use-copy-selection.ts +7 -7
- package/src/image.ts +2 -1
- package/src/routes/annotations-context.tsx +71 -121
- package/src/web-utils.test.ts +141 -1
- package/src/web-utils.tsx +230 -70
- package/src/worker.tsx +61 -17
|
@@ -13,6 +13,13 @@
|
|
|
13
13
|
// containing many spans). We inject content-visibility: auto on .line elements
|
|
14
14
|
// so the browser only renders visible lines, skipping layout/paint for the
|
|
15
15
|
// ~6,400 off-screen lines. This brings page load from ~16s to <2s on large diffs.
|
|
16
|
+
//
|
|
17
|
+
// iOS Safari pinch-zoom fix:
|
|
18
|
+
// position:fixed is relative to the layout viewport, not the visual viewport.
|
|
19
|
+
// When users pinch-to-zoom on iOS Safari, the widget drifts with the zoomed
|
|
20
|
+
// content and can end up mispositioned after zooming out. We use the
|
|
21
|
+
// visualViewport API to apply a counter-transform that keeps the widget
|
|
22
|
+
// anchored to the bottom-right of what the user actually sees.
|
|
16
23
|
function injectContentVisibility() {
|
|
17
24
|
if (document.getElementById("critique-cv-styles"))
|
|
18
25
|
return;
|
|
@@ -37,6 +44,9 @@ async function init() {
|
|
|
37
44
|
const isLight = window.matchMedia("(prefers-color-scheme: light)").matches;
|
|
38
45
|
localStorage.setItem("feedback-toolbar-theme", isLight ? "light" : "dark");
|
|
39
46
|
}
|
|
47
|
+
// Always reset the widget to the default bottom-right position on page load.
|
|
48
|
+
// If a user accidentally drags it, it snaps back on refresh.
|
|
49
|
+
localStorage.removeItem("feedback-toolbar-position");
|
|
40
50
|
if (document.getElementById("critique-agentation"))
|
|
41
51
|
return;
|
|
42
52
|
const config = window.__CRITIQUE_CONFIG__;
|
|
@@ -47,6 +57,11 @@ async function init() {
|
|
|
47
57
|
const container = document.createElement("div");
|
|
48
58
|
container.id = "critique-agentation";
|
|
49
59
|
document.body.appendChild(container);
|
|
60
|
+
// Fix position:fixed drift during pinch-to-zoom on iOS Safari.
|
|
61
|
+
// The visualViewport API tells us how the visible area has shifted
|
|
62
|
+
// relative to the layout viewport. We apply a counter-transform so
|
|
63
|
+
// the widget stays anchored to the visual viewport's bottom-right.
|
|
64
|
+
setupVisualViewportFix(container);
|
|
50
65
|
// Use preact's render() directly since the build aliases react → preact/compat.
|
|
51
66
|
// preact/compat does not export createRoot from react-dom/client.
|
|
52
67
|
const [{ Agentation }, { render, h }] = await Promise.all([
|
|
@@ -59,6 +74,30 @@ async function init() {
|
|
|
59
74
|
showFreezeButton: config.showFreezeButton,
|
|
60
75
|
}), container);
|
|
61
76
|
}
|
|
77
|
+
function setupVisualViewportFix(container) {
|
|
78
|
+
const vv = window.visualViewport;
|
|
79
|
+
if (!vv)
|
|
80
|
+
return;
|
|
81
|
+
function update() {
|
|
82
|
+
if (!vv)
|
|
83
|
+
return;
|
|
84
|
+
if (vv.scale <= 1.01) {
|
|
85
|
+
// No zoom — clear any transform so default fixed positioning works
|
|
86
|
+
container.style.transform = "";
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
// Translate the container so it follows the visual viewport's position,
|
|
90
|
+
// then scale it back to its original size (counter the zoom).
|
|
91
|
+
container.style.transform = [
|
|
92
|
+
`translate(${vv.offsetLeft}px, ${vv.offsetTop}px)`,
|
|
93
|
+
`scale(${1 / vv.scale})`,
|
|
94
|
+
].join(" ");
|
|
95
|
+
// Set transform-origin to top-left so the translate values are intuitive
|
|
96
|
+
container.style.transformOrigin = "top left";
|
|
97
|
+
}
|
|
98
|
+
vv.addEventListener("resize", update);
|
|
99
|
+
vv.addEventListener("scroll", update);
|
|
100
|
+
}
|
|
62
101
|
if (document.readyState === "loading") {
|
|
63
102
|
document.addEventListener("DOMContentLoaded", init);
|
|
64
103
|
}
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.tsx"],"names":[],"mappings":";AAOA,OAAO,gCAAgC,CAAC;AAYxC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAwB/B,OAAO,EAgBL,KAAK,UAAU,EAEhB,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.tsx"],"names":[],"mappings":";AAOA,OAAO,gCAAgC,CAAC;AAYxC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAwB/B,OAAO,EAgBL,KAAK,UAAU,EAEhB,MAAM,iBAAiB,CAAC;AA45CzB,MAAM,WAAW,QAAQ;IACvB,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B;AAED,wBAAgB,GAAG,CAAC,EAAE,WAAW,EAAE,EAAE,QAAQ,GAAG,KAAK,CAAC,YAAY,CAkVjE"}
|
package/dist/cli.js
CHANGED
|
@@ -886,7 +886,7 @@ async function runResumeMode(options) {
|
|
|
886
886
|
, isGenerating: false, initialReviewData: review.reviewYaml }) }));
|
|
887
887
|
}
|
|
888
888
|
async function runWebMode(diffContent, options) {
|
|
889
|
-
const { captureResponsiveHtml, uploadHtml, openInBrowser, } = await import("./web-utils.js");
|
|
889
|
+
const { captureResponsiveHtml, uploadHtml, uploadOgImage, openInBrowser, } = await import("./web-utils.js");
|
|
890
890
|
// Use stderr for progress when --json is set, stdout otherwise
|
|
891
891
|
const log = options.json ? console.error.bind(console) : console.log.bind(console);
|
|
892
892
|
const desktopCols = options.cols || 230;
|
|
@@ -904,9 +904,12 @@ async function runWebMode(diffContent, options) {
|
|
|
904
904
|
}, 100); // base padding
|
|
905
905
|
log("Converting to HTML...");
|
|
906
906
|
try {
|
|
907
|
-
|
|
907
|
+
// Render desktop + mobile HTML and OG image in parallel.
|
|
908
|
+
// Skip OG from initial upload — we'll PATCH it in the background
|
|
909
|
+
// after the URL is printed, so the user sees the URL faster.
|
|
910
|
+
const { htmlDesktop, htmlMobile, ogImage } = await captureResponsiveHtml(diffContent, { desktopCols, mobileCols, baseRows, themeName, title: options.title, skipOgImage: true });
|
|
908
911
|
log("Uploading...");
|
|
909
|
-
const result = await uploadHtml(htmlDesktop, htmlMobile
|
|
912
|
+
const result = await uploadHtml(htmlDesktop, htmlMobile);
|
|
910
913
|
log(`\nPreview URL: ${result.url}`);
|
|
911
914
|
log(formatPreviewExpiry(result.expiresInDays));
|
|
912
915
|
if (typeof result.expiresInDays === "number") {
|
|
@@ -926,6 +929,29 @@ async function runWebMode(diffContent, options) {
|
|
|
926
929
|
if (options.open) {
|
|
927
930
|
await openInBrowser(result.url);
|
|
928
931
|
}
|
|
932
|
+
// Generate and upload OG image in the background after URL is printed.
|
|
933
|
+
// The URL is already available — this just adds social media previews.
|
|
934
|
+
// Hard cap at 8s to prevent the process hanging after URL output.
|
|
935
|
+
const ogUpload = (async () => {
|
|
936
|
+
try {
|
|
937
|
+
const { renderDiffToOgImage } = await import("./image.js");
|
|
938
|
+
const ogImg = await renderDiffToOgImage(diffContent, {
|
|
939
|
+
themeName: "github-light",
|
|
940
|
+
stabilizeMs: 100,
|
|
941
|
+
});
|
|
942
|
+
if (ogImg) {
|
|
943
|
+
await uploadOgImage(result.id, ogImg);
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
catch {
|
|
947
|
+
// OG image generation failed — not critical, skip silently
|
|
948
|
+
}
|
|
949
|
+
})();
|
|
950
|
+
// Wait for OG upload with a hard timeout so the process always exits
|
|
951
|
+
await Promise.race([
|
|
952
|
+
ogUpload,
|
|
953
|
+
new Promise(resolve => setTimeout(resolve, 8000)),
|
|
954
|
+
]);
|
|
929
955
|
process.exit(0);
|
|
930
956
|
}
|
|
931
957
|
catch (error) {
|
package/dist/diff-utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diff-utils.d.ts","sourceRoot":"","sources":["../src/diff-utils.ts"],"names":[],"mappings":"AAMA;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAchE;AAED;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAA;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,EAAE,EAAE,MAAM,CAAA;IACV,UAAU,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG;IAC/C,aAAa,EAAE,MAAM,CAAA;IACrB,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;CACpC,CA6FA;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EACjC,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,CAAC,EAAE,GAChC,CAAC,CAAC,GAAG;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,EAAE,CAiBzE;AAED,eAAO,MAAM,aAAa,UASzB,CAAC;AAEF,MAAM,WAAW,UAAU;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uDAAuD;IACvD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,IAAI,CAAC,iBAAiB,EAAE,QAAQ,GAAG,mBAAmB,CAAC,GAC/D,MAAM,EAAE,CAQV;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAsBhF;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,CAAC,SAAS,UAAU,EAC9D,KAAK,EAAE,CAAC,EAAE,EACV,OAAO,EAAE,IAAI,CAAC,iBAAiB,EAAE,QAAQ,GAAG,mBAAmB,CAAC,GAC/D,CAAC,EAAE,CAKL;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"diff-utils.d.ts","sourceRoot":"","sources":["../src/diff-utils.ts"],"names":[],"mappings":"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"}
|
package/dist/diff-utils.js
CHANGED
|
@@ -236,6 +236,13 @@ export function buildGitCommand(options) {
|
|
|
236
236
|
const filterArg = filters.length > 0
|
|
237
237
|
? `-- ${filters.map((f) => `'${f}'`).join(" ")}`
|
|
238
238
|
: "";
|
|
239
|
+
// If --commit contains range syntax (A..B or A...B), treat it as a base ref
|
|
240
|
+
// instead. git show with ranges outputs commit metadata interleaved with diffs
|
|
241
|
+
// that parsePatch cannot parse. Redirecting to base reuses the existing range
|
|
242
|
+
// handling below (two-dot and three-dot parsing).
|
|
243
|
+
if (options.commit?.includes("..")) {
|
|
244
|
+
options = { ...options, base: options.commit, commit: undefined };
|
|
245
|
+
}
|
|
239
246
|
if (options.staged) {
|
|
240
247
|
return `git diff --cached --no-prefix ${renameArg} ${submoduleArg} ${contextArg} ${filterArg}`.trim();
|
|
241
248
|
}
|
|
@@ -436,9 +443,15 @@ export function detectFiletype(filePath) {
|
|
|
436
443
|
case "cts":
|
|
437
444
|
return "typescript";
|
|
438
445
|
case "json":
|
|
446
|
+
case "jsonc":
|
|
447
|
+
case "json5":
|
|
439
448
|
return "json";
|
|
440
449
|
case "md":
|
|
441
450
|
case "mdx":
|
|
451
|
+
case "mkd":
|
|
452
|
+
case "mkdn":
|
|
453
|
+
case "mdown":
|
|
454
|
+
case "markdown":
|
|
442
455
|
return "markdown";
|
|
443
456
|
case "zig":
|
|
444
457
|
return "zig";
|
|
@@ -456,6 +469,10 @@ export function detectFiletype(filePath) {
|
|
|
456
469
|
case "cxx":
|
|
457
470
|
case "hpp":
|
|
458
471
|
case "hxx":
|
|
472
|
+
case "hh":
|
|
473
|
+
case "tpp":
|
|
474
|
+
case "ipp":
|
|
475
|
+
case "inl":
|
|
459
476
|
case "h":
|
|
460
477
|
return "cpp";
|
|
461
478
|
case "cs":
|
|
@@ -463,6 +480,7 @@ export function detectFiletype(filePath) {
|
|
|
463
480
|
case "sh":
|
|
464
481
|
case "bash":
|
|
465
482
|
case "zsh":
|
|
483
|
+
case "ksh":
|
|
466
484
|
return "bash";
|
|
467
485
|
case "c":
|
|
468
486
|
return "c";
|
|
@@ -479,6 +497,9 @@ export function detectFiletype(filePath) {
|
|
|
479
497
|
return "scala";
|
|
480
498
|
case "html":
|
|
481
499
|
case "htm":
|
|
500
|
+
case "xhtml":
|
|
501
|
+
case "xml":
|
|
502
|
+
case "svg":
|
|
482
503
|
return "html";
|
|
483
504
|
case "yaml":
|
|
484
505
|
case "yml":
|
|
@@ -487,6 +508,8 @@ export function detectFiletype(filePath) {
|
|
|
487
508
|
case "lhs":
|
|
488
509
|
return "haskell";
|
|
489
510
|
case "css":
|
|
511
|
+
case "scss":
|
|
512
|
+
case "less":
|
|
490
513
|
return "css";
|
|
491
514
|
case "jl":
|
|
492
515
|
return "julia";
|
package/dist/diff-utils.test.js
CHANGED
|
@@ -459,6 +459,41 @@ describe("getOldFileName", () => {
|
|
|
459
459
|
});
|
|
460
460
|
});
|
|
461
461
|
// ============================================================================
|
|
462
|
+
// --commit with range syntax (HEAD~2..HEAD)
|
|
463
|
+
// ============================================================================
|
|
464
|
+
describe("--commit with range syntax", () => {
|
|
465
|
+
it("should use git diff instead of git show for two-dot range", () => {
|
|
466
|
+
// --commit with range redirects to base, which uses the two-dot path
|
|
467
|
+
const cmd = buildGitCommand({ commit: "HEAD~2..HEAD" });
|
|
468
|
+
expect(cmd).toStartWith("git diff HEAD~2..HEAD");
|
|
469
|
+
expect(cmd).not.toContain("git show");
|
|
470
|
+
});
|
|
471
|
+
it("should use git diff instead of git show for three-dot range", () => {
|
|
472
|
+
// --commit with range redirects to base, which uses the three-dot path
|
|
473
|
+
const cmd = buildGitCommand({ commit: "main...feature" });
|
|
474
|
+
expect(cmd).toStartWith("git diff main...feature");
|
|
475
|
+
expect(cmd).not.toContain("git show");
|
|
476
|
+
});
|
|
477
|
+
it("should use git diff for named ref range", () => {
|
|
478
|
+
const cmd = buildGitCommand({ commit: "origin/main..HEAD" });
|
|
479
|
+
expect(cmd).toStartWith("git diff origin/main..HEAD");
|
|
480
|
+
expect(cmd).not.toContain("git show");
|
|
481
|
+
});
|
|
482
|
+
it("should produce same command whether range comes via --commit or positional base", () => {
|
|
483
|
+
const viaCommit = buildGitCommand({ commit: "HEAD~2..HEAD" });
|
|
484
|
+
const viaBase = buildGitCommand({ base: "HEAD~2..HEAD" });
|
|
485
|
+
expect(viaCommit).toBe(viaBase);
|
|
486
|
+
});
|
|
487
|
+
it("should still use git show for a single commit ref", () => {
|
|
488
|
+
const cmd = buildGitCommand({ commit: "HEAD" });
|
|
489
|
+
expect(cmd).toStartWith("git show HEAD");
|
|
490
|
+
});
|
|
491
|
+
it("should still use git show for a single hash", () => {
|
|
492
|
+
const cmd = buildGitCommand({ commit: "abc123" });
|
|
493
|
+
expect(cmd).toStartWith("git show abc123");
|
|
494
|
+
});
|
|
495
|
+
});
|
|
496
|
+
// ============================================================================
|
|
462
497
|
// buildGitCommand includes rename detection
|
|
463
498
|
// ============================================================================
|
|
464
499
|
describe("buildGitCommand with rename detection", () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-copy-selection.d.ts","sourceRoot":"","sources":["../../src/hooks/use-copy-selection.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"use-copy-selection.d.ts","sourceRoot":"","sources":["../../src/hooks/use-copy-selection.ts"],"names":[],"mappings":"AAiFA;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,mDAAmD;IACnD,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC/B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,gBAAgB,IAAI,qBAAqB,CAsBxD"}
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
// Automatically copies selected text to clipboard when user releases mouse button.
|
|
3
3
|
// Uses native clipboard commands (pbcopy, xclip, etc.) with OSC52 fallback.
|
|
4
4
|
import { useRenderer } from "@opentuah/react";
|
|
5
|
-
import
|
|
5
|
+
import childProcess from "child_process";
|
|
6
6
|
/**
|
|
7
7
|
* Copy text to system clipboard using native commands.
|
|
8
8
|
* Falls back to OSC52 escape sequence for terminal clipboard (works over SSH).
|
|
9
9
|
*/
|
|
10
|
-
async function copyToClipboard(text) {
|
|
10
|
+
async function copyToClipboard(text, copyOsc52) {
|
|
11
11
|
const platform = process.platform;
|
|
12
12
|
// Try native clipboard commands
|
|
13
13
|
try {
|
|
@@ -52,16 +52,15 @@ async function copyToClipboard(text) {
|
|
|
52
52
|
catch {
|
|
53
53
|
// Native clipboard failed, fall through to OSC52
|
|
54
54
|
}
|
|
55
|
-
// Fallback: OSC52
|
|
56
|
-
|
|
57
|
-
process.stdout.write(`\x1b]52;c;${encoded}\x07`);
|
|
55
|
+
// Fallback: renderer OSC52 utility (works in many terminals, including over SSH)
|
|
56
|
+
copyOsc52(text);
|
|
58
57
|
}
|
|
59
58
|
/**
|
|
60
59
|
* Spawn a clipboard command and pipe text to it
|
|
61
60
|
*/
|
|
62
61
|
function spawnClipboard(cmd, args, text) {
|
|
63
62
|
return new Promise((resolve, reject) => {
|
|
64
|
-
const proc = spawn(cmd, args, { stdio: ["pipe", "ignore", "ignore"] });
|
|
63
|
+
const proc = childProcess.spawn(cmd, args, { stdio: ["pipe", "ignore", "ignore"] });
|
|
65
64
|
proc.on("error", reject);
|
|
66
65
|
proc.on("close", (code) => {
|
|
67
66
|
if (code === 0)
|
|
@@ -99,11 +98,13 @@ export function useCopySelection() {
|
|
|
99
98
|
const selection = renderer.getSelection();
|
|
100
99
|
if (!selection)
|
|
101
100
|
return;
|
|
101
|
+
if (selection.isDragging)
|
|
102
|
+
return;
|
|
102
103
|
const text = selection.getSelectedText();
|
|
103
104
|
if (!text || text.length === 0)
|
|
104
105
|
return;
|
|
105
106
|
try {
|
|
106
|
-
await copyToClipboard(text);
|
|
107
|
+
await copyToClipboard(text, (value) => renderer.copyToClipboardOSC52(value));
|
|
107
108
|
}
|
|
108
109
|
catch {
|
|
109
110
|
// Silent fail - user can manually copy if needed
|
package/dist/image.d.ts
CHANGED
|
@@ -129,5 +129,6 @@ export declare function renderFrameToOgImage(frame: CapturedFrame, options?: OgI
|
|
|
129
129
|
*/
|
|
130
130
|
export declare function renderDiffToOgImage(diffContent: string, options?: OgImageOptions & {
|
|
131
131
|
cols?: number;
|
|
132
|
+
stabilizeMs?: number;
|
|
132
133
|
}): Promise<Buffer>;
|
|
133
134
|
//# sourceMappingURL=image.d.ts.map
|
package/dist/image.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../src/image.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../src/image.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAEnD,OAAO,EAQL,KAAK,UAAU,EACf,KAAK,WAAW,EACjB,MAAM,oBAAoB,CAAA;AAG3B,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,CAAA;AAMvC,MAAM,WAAW,qBAAqB;IACpC,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,4CAA4C;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,wCAAwC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,4CAA4C;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,6DAA6D;IAC7D,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,CAAA;IAChC,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,6BAA6B;IAC7B,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,oCAAoC;IACpC,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,0CAA0C;IAC1C,UAAU,EAAE,MAAM,CAAA;IAClB,iCAAiC;IACjC,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,4CAA4C;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,wCAAwC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,4CAA4C;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,uDAAuD;IACvD,MAAM,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,CAAA;IAChC,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,yCAAyC;IACzC,UAAU,EAAE,MAAM,CAAA;IAClB,4CAA4C;IAC5C,YAAY,EAAE,MAAM,CAAA;IACpB,yDAAyD;IACzD,QAAQ,EAAE,MAAM,CAAA;IAChB,uBAAuB;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,qBAAqB;IACrB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,4BAA4B;IAC5B,YAAY,EAAE,MAAM,CAAA;IACpB,mCAAmC;IACnC,eAAe,EAAE,MAAM,CAAA;IACvB,0DAA0D;IAC1D,aAAa,EAAE,MAAM,CAAA;IACrB,0CAA0C;IAC1C,YAAY,EAAE,MAAM,CAAA;CACrB;AAqBD;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,aAAa,EACpB,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,YAAY,CAAC,CA2BvB;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE;IACP,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,GAAG,qBAA0B,GAC7B,OAAO,CAAC,YAAY,CAAC,CAmBvB;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE;IACP,KAAK,EAAE,GAAG,EAAE,CAAA;IACZ,UAAU,EAAE,GAAG,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,GAAG,qBAAqB,GACxB,OAAO,CAAC,YAAY,CAAC,CAqBvB;AAMD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,aAAa,EACpB,OAAO,GAAE,cAAmB,GAC3B,aAAa,CA+Bf;AAED;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,aAAa,EACpB,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,MAAM,CAAC,CAwBjB;AAED;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,cAAc,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GACrE,OAAO,CAAC,MAAM,CAAC,CA2BjB"}
|
package/dist/image.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"annotations-context.d.ts","sourceRoot":"","sources":["../../src/routes/annotations-context.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"annotations-context.d.ts","sourceRoot":"","sources":["../../src/routes/annotations-context.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AAE5D,KAAK,QAAQ,GAAG;IACd,WAAW,EAAE,WAAW,CAAA;IACxB,WAAW,EAAE;QACX,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG;YAAE,QAAQ,IAAI,MAAM,CAAA;SAAE,CAAA;QAChD,GAAG,CAAC,EAAE,EAAE;YAAE,QAAQ,IAAI,MAAM,CAAA;SAAE,GAAG;YAC/B,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;SAC3C,CAAA;KACF,CAAA;CACF,CAAA;AAgED,QAAA,MAAM,KAAK;cAAwB,QAAQ;yCAAK,CAAA;AA2BhD,OAAO,EAAE,KAAK,IAAI,uBAAuB,EAAE,CAAA"}
|
|
@@ -1,9 +1,46 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "hono/jsx/jsx-runtime";
|
|
2
|
-
/** @jsxImportSource hono/jsx */
|
|
3
1
|
// Route: GET /v/:id/annotations
|
|
4
|
-
// Returns all annotations
|
|
5
|
-
//
|
|
2
|
+
// Returns all annotations as markdown, matching agentation's generateOutput format.
|
|
3
|
+
// This is the format agents and LLMs consume best.
|
|
6
4
|
import { Hono } from "hono";
|
|
5
|
+
function generateMarkdown(annotations, diffUrl) {
|
|
6
|
+
if (annotations.length === 0)
|
|
7
|
+
return "No annotations yet.\n";
|
|
8
|
+
let output = `## Page Feedback: ${diffUrl}\n\n`;
|
|
9
|
+
for (let i = 0; i < annotations.length; i++) {
|
|
10
|
+
const a = annotations[i];
|
|
11
|
+
output += `### ${i + 1}. ${a.element || a.elementPath}\n`;
|
|
12
|
+
if (a.elementPath) {
|
|
13
|
+
output += `**Location:** ${a.elementPath}\n`;
|
|
14
|
+
}
|
|
15
|
+
if (a.anchor) {
|
|
16
|
+
output += `**Anchor:** ${a.anchor}\n`;
|
|
17
|
+
}
|
|
18
|
+
if (a.selectedText) {
|
|
19
|
+
output += `**Selected text:** "${a.selectedText}"\n`;
|
|
20
|
+
}
|
|
21
|
+
if (a.nearbyText && !a.selectedText) {
|
|
22
|
+
output += `**Context:** ${a.nearbyText.slice(0, 100)}\n`;
|
|
23
|
+
}
|
|
24
|
+
if (a.status && a.status !== "pending") {
|
|
25
|
+
output += `**Status:** ${a.status}\n`;
|
|
26
|
+
}
|
|
27
|
+
if (a.severity) {
|
|
28
|
+
output += `**Severity:** ${a.severity}\n`;
|
|
29
|
+
}
|
|
30
|
+
if (a.intent) {
|
|
31
|
+
output += `**Intent:** ${a.intent}\n`;
|
|
32
|
+
}
|
|
33
|
+
output += `**Feedback:** ${a.comment}\n`;
|
|
34
|
+
if (a.thread && a.thread.length > 0) {
|
|
35
|
+
output += "\n";
|
|
36
|
+
for (const msg of a.thread) {
|
|
37
|
+
output += `> **${msg.role}:** ${msg.content}\n`;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
output += "\n";
|
|
41
|
+
}
|
|
42
|
+
return output.trim() + "\n";
|
|
43
|
+
}
|
|
7
44
|
const route = new Hono();
|
|
8
45
|
route.get("/v/:id/annotations", async (c) => {
|
|
9
46
|
const id = c.req.param("id");
|
|
@@ -18,43 +55,11 @@ route.get("/v/:id/annotations", async (c) => {
|
|
|
18
55
|
req.headers.set("x-partykit-room", id);
|
|
19
56
|
const resp = await stub.fetch(req);
|
|
20
57
|
const annotations = (await resp.json());
|
|
21
|
-
const format = c.req.query("format");
|
|
22
|
-
// JSON format for agents/bots
|
|
23
|
-
if (format === "json") {
|
|
24
|
-
return c.json({
|
|
25
|
-
diffId: id,
|
|
26
|
-
diffUrl: `${new URL(c.req.url).origin}/v/${id}`,
|
|
27
|
-
count: annotations.length,
|
|
28
|
-
annotations,
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
// HTML format for humans
|
|
32
58
|
const origin = new URL(c.req.url).origin;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
.header a:hover { text-decoration: underline; }
|
|
39
|
-
.count { color: #8b949e; font-size: 14px; margin-bottom: 24px; }
|
|
40
|
-
.annotation { max-width: 720px; margin: 0 auto 20px; background: #151b23; border: 1px solid #2d3440; border-radius: 10px; padding: 16px; }
|
|
41
|
-
.meta { display: flex; gap: 12px; align-items: center; margin-bottom: 8px; font-size: 13px; color: #8b949e; }
|
|
42
|
-
.badge { padding: 2px 8px; border-radius: 4px; font-size: 11px; font-weight: 600; text-transform: uppercase; }
|
|
43
|
-
.badge-pending { background: #1f3044; color: #58a6ff; }
|
|
44
|
-
.badge-resolved { background: #1a3520; color: #3fb950; }
|
|
45
|
-
.badge-dismissed { background: #3d1f20; color: #f85149; }
|
|
46
|
-
.badge-acknowledged { background: #3b2e1a; color: #d29922; }
|
|
47
|
-
.badge-blocking { background: #3d1f20; color: #f85149; }
|
|
48
|
-
.badge-important { background: #3b2e1a; color: #d29922; }
|
|
49
|
-
.badge-suggestion { background: #1f3044; color: #58a6ff; }
|
|
50
|
-
.comment { font-size: 15px; line-height: 1.6; margin: 8px 0; }
|
|
51
|
-
.context { font-size: 13px; color: #8b949e; margin-top: 8px; }
|
|
52
|
-
.context code { background: #1c2128; padding: 2px 6px; border-radius: 4px; font-family: ui-monospace, monospace; }
|
|
53
|
-
.thread { margin-top: 12px; border-top: 1px solid #2d3440; padding-top: 12px; }
|
|
54
|
-
.thread-msg { margin-bottom: 8px; font-size: 13px; }
|
|
55
|
-
.thread-role { font-weight: 600; color: #58a6ff; }
|
|
56
|
-
.thread-role.agent { color: #d29922; }
|
|
57
|
-
.empty { max-width: 720px; margin: 40px auto; text-align: center; color: #8b949e; }
|
|
58
|
-
` })] }), _jsxs("body", { children: [_jsxs("div", { class: "header", children: [_jsx("h1", { children: "Annotations" }), _jsx("a", { href: `${origin}/v/${id}`, children: "Back to diff" }), _jsxs("div", { class: "count", children: [annotations.length, " annotation", annotations.length !== 1 ? "s" : ""] })] }), annotations.length === 0 ? (_jsx("div", { class: "empty", children: "No annotations yet" })) : (annotations.map((ann) => (_jsxs("div", { class: "annotation", children: [_jsxs("div", { class: "meta", children: [ann.userName && _jsx("span", { children: ann.userName }), ann.status && (_jsx("span", { class: `badge badge-${ann.status}`, children: ann.status })), ann.severity && (_jsx("span", { class: `badge badge-${ann.severity}`, children: ann.severity })), ann.intent && _jsx("span", { children: ann.intent }), ann.createdAt && (_jsx("span", { children: new Date(ann.createdAt).toLocaleString() }))] }), _jsx("div", { class: "comment", children: ann.comment }), (ann.elementPath || ann.anchor || ann.nearbyText || ann.selectedText) && (_jsxs("div", { class: "context", children: [ann.anchor && (_jsxs("div", { children: ["Anchor: ", _jsx("code", { children: ann.anchor })] })), ann.elementPath && (_jsxs("div", { children: ["Element: ", _jsx("code", { children: ann.elementPath })] })), ann.selectedText && (_jsxs("div", { children: ["Selected: \"", ann.selectedText, "\""] })), ann.nearbyText && (_jsxs("div", { children: ["Nearby: \"", ann.nearbyText, "\""] }))] })), ann.thread && ann.thread.length > 0 && (_jsx("div", { class: "thread", children: ann.thread.map((msg, i) => (_jsxs("div", { class: "thread-msg", children: [_jsxs("span", { class: `thread-role ${msg.role}`, children: [msg.role, ":"] }), " ", msg.content] }, i))) }))] }, ann.id))))] })] }));
|
|
59
|
+
const diffUrl = `${origin}/v/${id}`;
|
|
60
|
+
const markdown = generateMarkdown(annotations, diffUrl);
|
|
61
|
+
return c.text(markdown, 200, {
|
|
62
|
+
"Content-Type": "text/markdown; charset=utf-8",
|
|
63
|
+
});
|
|
59
64
|
});
|
|
60
65
|
export { route as annotationsContextRoute };
|
package/dist/web-utils.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CapturedFrame } from "@opentuah/core";
|
|
1
|
+
import type { CapturedFrame, CapturedLine } from "@opentuah/core";
|
|
2
2
|
import type { IndexedHunk, ReviewYaml } from "./review/types.js";
|
|
3
3
|
export declare const WORKER_URL: string;
|
|
4
4
|
export interface CaptureOptions {
|
|
@@ -12,6 +12,9 @@ export interface CaptureOptions {
|
|
|
12
12
|
viewMode?: "split" | "unified";
|
|
13
13
|
/** Show privacy/expiry notice block at top (default: false, enabled for web uploads) */
|
|
14
14
|
showNotice?: boolean;
|
|
15
|
+
/** How long to wait for async rendering (tree-sitter) to stabilize.
|
|
16
|
+
* Default: 500ms for interactive TUI, use 100ms for batch/web mode. */
|
|
17
|
+
stabilizeMs?: number;
|
|
15
18
|
}
|
|
16
19
|
export interface UploadResult {
|
|
17
20
|
url: string;
|
|
@@ -25,6 +28,17 @@ export declare function renderDiffToFrame(diffContent: string, options: CaptureO
|
|
|
25
28
|
* e.g. "src/components/foo-bar.tsx" → "src-components-foo-bar-tsx"
|
|
26
29
|
*/
|
|
27
30
|
export declare function slugifyFileName(name: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* Extract line numbers from a captured diff line's spans.
|
|
33
|
+
* In split view each row has two line number columns (old + new):
|
|
34
|
+
* " " "29" " - " ...content... " " "29" " + " ...content...
|
|
35
|
+
* In unified view there's only one.
|
|
36
|
+
*
|
|
37
|
+
* Returns the new-file (right) line number when available,
|
|
38
|
+
* falling back to the old-file (left) number for deleted-only rows.
|
|
39
|
+
* Returns null for non-diff lines (headers, hunk markers, etc.).
|
|
40
|
+
*/
|
|
41
|
+
export declare function extractLineNumber(line: CapturedLine): string | null;
|
|
28
42
|
/**
|
|
29
43
|
* Build line-indexed anchors from file section layout positions.
|
|
30
44
|
* This avoids regex detection on rendered text, which can produce
|
|
@@ -50,6 +64,10 @@ export declare function captureResponsiveHtml(diffContent: string, options: {
|
|
|
50
64
|
baseRows: number;
|
|
51
65
|
themeName: string;
|
|
52
66
|
title?: string;
|
|
67
|
+
/** Stabilization timeout for tree-sitter highlighting (default: 100ms for web) */
|
|
68
|
+
stabilizeMs?: number;
|
|
69
|
+
/** Skip OG image generation for faster URL delivery */
|
|
70
|
+
skipOgImage?: boolean;
|
|
53
71
|
}): Promise<{
|
|
54
72
|
htmlDesktop: string;
|
|
55
73
|
htmlMobile: string;
|
|
@@ -80,6 +98,10 @@ export declare function captureReviewResponsiveHtml(options: {
|
|
|
80
98
|
baseRows: number;
|
|
81
99
|
themeName: string;
|
|
82
100
|
title?: string;
|
|
101
|
+
/** Stabilization timeout for tree-sitter highlighting (default: 100ms for web) */
|
|
102
|
+
stabilizeMs?: number;
|
|
103
|
+
/** Skip OG image generation for faster URL delivery */
|
|
104
|
+
skipOgImage?: boolean;
|
|
83
105
|
}): Promise<{
|
|
84
106
|
htmlDesktop: string;
|
|
85
107
|
htmlMobile: string;
|
|
@@ -89,6 +111,12 @@ export declare function captureReviewResponsiveHtml(options: {
|
|
|
89
111
|
* Upload HTML to the critique.work worker
|
|
90
112
|
*/
|
|
91
113
|
export declare function uploadHtml(htmlDesktop: string, htmlMobile: string, ogImage?: Buffer | null): Promise<UploadResult>;
|
|
114
|
+
/**
|
|
115
|
+
* Upload OG image to an existing diff via PATCH.
|
|
116
|
+
* Called in the background after the initial upload returns the URL.
|
|
117
|
+
* Uses a 5s timeout to prevent hanging the process after URL is printed.
|
|
118
|
+
*/
|
|
119
|
+
export declare function uploadOgImage(id: string, ogImage: Buffer): Promise<void>;
|
|
92
120
|
/**
|
|
93
121
|
* Open a URL in the default browser
|
|
94
122
|
*/
|
package/dist/web-utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web-utils.d.ts","sourceRoot":"","sources":["../src/web-utils.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAiB,aAAa,EAA+B,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"web-utils.d.ts","sourceRoot":"","sources":["../src/web-utils.tsx"],"names":[],"mappings":"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"}
|