@vintasoftware/pr-review-canvas 0.1.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.
- package/LICENSE +202 -0
- package/README.md +192 -0
- package/bin/pr-review.mjs +5 -0
- package/docs/reference.md +340 -0
- package/package.json +74 -0
- package/pr-review.config.example.yml +68 -0
- package/prompts/chat-seed.md +64 -0
- package/prompts/generation-format.md +255 -0
- package/prompts/generation-strict.md +34 -0
- package/prompts/generation-surfacing.md +67 -0
- package/prompts/layers-default.md +13 -0
- package/prompts/quality-standards.md +32 -0
- package/skills/pr-review-canvas/SKILL.md +177 -0
- package/src/acpx/acpx.ts +530 -0
- package/src/acpx/agents.ts +85 -0
- package/src/acpx/events.ts +216 -0
- package/src/acpx/ndjson.ts +69 -0
- package/src/acpx/preflight.ts +44 -0
- package/src/canvas/export.ts +95 -0
- package/src/canvas/import.ts +138 -0
- package/src/canvas/name.ts +55 -0
- package/src/canvas/zip.ts +123 -0
- package/src/chat/chat-manager.ts +389 -0
- package/src/chat/context.ts +160 -0
- package/src/chat/seed.ts +71 -0
- package/src/chat/threads.ts +114 -0
- package/src/cli.ts +199 -0
- package/src/commands.ts +424 -0
- package/src/config.ts +142 -0
- package/src/contract/api.ts +190 -0
- package/src/contract/canvas-manifest.ts +29 -0
- package/src/contract/chat.ts +76 -0
- package/src/contract/comments.ts +96 -0
- package/src/contract/discovery.ts +20 -0
- package/src/contract/generation-context.ts +77 -0
- package/src/contract/keys.ts +14 -0
- package/src/contract/links.ts +5 -0
- package/src/contract/mermaid-fences.ts +4 -0
- package/src/contract/review-artifact.ts +324 -0
- package/src/contract/settings.ts +144 -0
- package/src/contract/state.ts +46 -0
- package/src/contract/validation.ts +43 -0
- package/src/git/diff-collector.ts +151 -0
- package/src/git/git.ts +115 -0
- package/src/git/lang.ts +1 -0
- package/src/git/materialize.ts +79 -0
- package/src/git/patch-lines.ts +60 -0
- package/src/github/attachments.ts +288 -0
- package/src/github/capabilities.ts +112 -0
- package/src/github/comments.ts +132 -0
- package/src/github/gh.ts +196 -0
- package/src/github/post-comment.ts +104 -0
- package/src/github/post-review.ts +44 -0
- package/src/github/pr.ts +133 -0
- package/src/github/review-body.ts +72 -0
- package/src/github/threads.ts +63 -0
- package/src/paths.ts +10 -0
- package/src/project-config.ts +219 -0
- package/src/prompt-files.ts +26 -0
- package/src/review/diagram-nodes.ts +227 -0
- package/src/review/doctor.ts +139 -0
- package/src/review/glob.ts +33 -0
- package/src/review/install-skill.ts +107 -0
- package/src/review/normalize.ts +209 -0
- package/src/review/prepare.ts +165 -0
- package/src/review/prompt.ts +233 -0
- package/src/review/publish.ts +209 -0
- package/src/review/skill-command.ts +4 -0
- package/src/review/test-paths.ts +32 -0
- package/src/review/text-length.ts +15 -0
- package/src/review/trim-caps.ts +114 -0
- package/src/review/validate-folds.ts +110 -0
- package/src/review/validate.ts +520 -0
- package/src/server/app.ts +46 -0
- package/src/server/bundle.ts +266 -0
- package/src/server/capped-body.ts +62 -0
- package/src/server/context.ts +174 -0
- package/src/server/env.ts +7 -0
- package/src/server/errors.ts +65 -0
- package/src/server/html.ts +140 -0
- package/src/server/node-server.ts +42 -0
- package/src/server/routes/api.ts +256 -0
- package/src/server/routes/chat-routes.ts +221 -0
- package/src/server/routes/pages.ts +64 -0
- package/src/server/routes/review-routes.ts +245 -0
- package/src/server/routes/static.ts +114 -0
- package/src/server/security.ts +104 -0
- package/src/server/sse.ts +67 -0
- package/src/store/atomic-json.ts +68 -0
- package/src/store/canvas-store.ts +120 -0
- package/src/store/data-dir.ts +29 -0
- package/src/store/derived-store.ts +93 -0
- package/src/store/pr-store.ts +69 -0
- package/src/store/settings-store.ts +152 -0
- package/src/store/state-store.ts +121 -0
- package/static/js/anchors.js +141 -0
- package/static/js/api.js +542 -0
- package/static/js/app.js +418 -0
- package/static/js/ask.js +35 -0
- package/static/js/chat-context.js +137 -0
- package/static/js/chat-scroll.js +114 -0
- package/static/js/chat.js +843 -0
- package/static/js/code-folds.js +200 -0
- package/static/js/commands.js +110 -0
- package/static/js/comment-link.js +37 -0
- package/static/js/composer.js +241 -0
- package/static/js/contract-types.d.ts +59 -0
- package/static/js/deep-link.js +160 -0
- package/static/js/diagram.js +582 -0
- package/static/js/diff-decorations.js +204 -0
- package/static/js/diff-renderer.js +860 -0
- package/static/js/dom.js +145 -0
- package/static/js/download.js +52 -0
- package/static/js/empty-state.js +161 -0
- package/static/js/errors.js +135 -0
- package/static/js/fences.js +90 -0
- package/static/js/header.js +134 -0
- package/static/js/hunks.js +62 -0
- package/static/js/import-zone.js +95 -0
- package/static/js/interactions.js +952 -0
- package/static/js/keyboard.js +131 -0
- package/static/js/keys.js +97 -0
- package/static/js/lang.js +54 -0
- package/static/js/layers.js +596 -0
- package/static/js/links.js +150 -0
- package/static/js/markdown.js +232 -0
- package/static/js/mermaid-fences.js +55 -0
- package/static/js/nav.js +91 -0
- package/static/js/overview.js +85 -0
- package/static/js/points.js +247 -0
- package/static/js/progress.js +49 -0
- package/static/js/proposed-comment.js +133 -0
- package/static/js/quick-questions.js +216 -0
- package/static/js/regenerate.js +69 -0
- package/static/js/review-session.js +257 -0
- package/static/js/scroll-spy.js +66 -0
- package/static/js/selection.js +193 -0
- package/static/js/settings.js +206 -0
- package/static/js/signoff.js +171 -0
- package/static/js/skin.js +56 -0
- package/static/js/store.js +35 -0
- package/static/js/theme.js +56 -0
- package/static/js/threads.js +78 -0
- package/static/js/vendor.d.ts +15 -0
- package/static/styles/base.css +223 -0
- package/static/styles/chat-tools.css +130 -0
- package/static/styles/chat.css +140 -0
- package/static/styles/commands.css +156 -0
- package/static/styles/diff.css +258 -0
- package/static/styles/header.css +114 -0
- package/static/styles/layout.css +123 -0
- package/static/styles/panels.css +152 -0
- package/static/styles/responsive.css +80 -0
- package/static/styles/review-actions.css +124 -0
- package/static/styles/review.css +473 -0
- package/static/styles/skin-github.css +356 -0
- package/static/styles.css +14 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
// Where the transcript stands: following the answer, or left where the reader put it. Pure, so
|
|
3
|
+
// the rules are testable without a scrolling element; chat.js applies the result to the DOM.
|
|
4
|
+
|
|
5
|
+
/** Within this many pixels of the bottom counts as "at the bottom". */
|
|
6
|
+
export const PIN_THRESHOLD_PX = 48
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {{ pinned: boolean, unseen: number, firstUnseenId: string | null }} ChatScrollState
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @typedef {{ type: 'scroll', atBottom: boolean }
|
|
14
|
+
* | { type: 'append', id: string, belowFold: boolean }
|
|
15
|
+
* | { type: 'send' }
|
|
16
|
+
* | { type: 'jump' }
|
|
17
|
+
* | { type: 'thread-switch', pinned: boolean }} ChatScrollAction
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/** @type {ChatScrollState} */
|
|
21
|
+
export const INITIAL_SCROLL_STATE = { pinned: true, unseen: 0, firstUnseenId: null }
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* True when the element is scrolled to within the threshold of its bottom.
|
|
25
|
+
* @param {{ scrollTop: number, scrollHeight: number, clientHeight: number }} el
|
|
26
|
+
*/
|
|
27
|
+
export function isAtBottom(el) {
|
|
28
|
+
return el.scrollHeight - el.scrollTop - el.clientHeight <= PIN_THRESHOLD_PX
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @param {ChatScrollState} state
|
|
33
|
+
* @param {ChatScrollAction} action
|
|
34
|
+
* @returns {ChatScrollState}
|
|
35
|
+
*/
|
|
36
|
+
export function chatScrollReducer(state, action) {
|
|
37
|
+
switch (action.type) {
|
|
38
|
+
case 'scroll':
|
|
39
|
+
// Scrolling back to the bottom by hand counts as catching up.
|
|
40
|
+
return action.atBottom ? { pinned: true, unseen: 0, firstUnseenId: null } : { ...state, pinned: false }
|
|
41
|
+
case 'append':
|
|
42
|
+
// While pinned the new content is being scrolled into view, so nothing is unseen; content
|
|
43
|
+
// that lands inside the part already on screen is not unseen either.
|
|
44
|
+
if (state.pinned || !action.belowFold) {
|
|
45
|
+
return state
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
pinned: false,
|
|
49
|
+
unseen: state.unseen + 1,
|
|
50
|
+
firstUnseenId: state.firstUnseenId ?? action.id,
|
|
51
|
+
}
|
|
52
|
+
case 'send':
|
|
53
|
+
return { pinned: true, unseen: 0, firstUnseenId: null }
|
|
54
|
+
case 'jump':
|
|
55
|
+
// The jump scrolls to the first unseen message, which is not the bottom; the scroll event
|
|
56
|
+
// that follows decides whether to re-pin.
|
|
57
|
+
return { pinned: false, unseen: 0, firstUnseenId: null }
|
|
58
|
+
case 'thread-switch':
|
|
59
|
+
return { pinned: action.pinned, unseen: 0, firstUnseenId: null }
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* The bubble's text, or null when there is nothing to catch up on.
|
|
65
|
+
* @param {ChatScrollState} state
|
|
66
|
+
*/
|
|
67
|
+
export function unseenLabel(state) {
|
|
68
|
+
if (state.unseen === 0) {
|
|
69
|
+
return null
|
|
70
|
+
}
|
|
71
|
+
return state.unseen === 1 ? '1 new message ↓' : `${state.unseen} new messages ↓`
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* How to scroll: instantly while following an answer, smoothly when the reader jumps, and never
|
|
76
|
+
* smoothly for a reader who asked for less motion.
|
|
77
|
+
* @param {'follow' | 'jump'} reason
|
|
78
|
+
* @param {boolean} reducedMotion
|
|
79
|
+
* @returns {ScrollBehavior}
|
|
80
|
+
*/
|
|
81
|
+
export function scrollBehavior(reason, reducedMotion) {
|
|
82
|
+
return reason === 'follow' || reducedMotion ? 'auto' : 'smooth'
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Whether a wheel turn over the chat pane should move the transcript instead of the page.
|
|
87
|
+
*
|
|
88
|
+
* The pane is pinned to the viewport, so a wheel over its header, its controls, or its composer
|
|
89
|
+
* would otherwise scroll the page behind it and leave the transcript where it was. Redirecting
|
|
90
|
+
* keeps one pane under one pointer. A turn that starts inside the transcript already lands there,
|
|
91
|
+
* and a turn inside a control that scrolls its own text belongs to that control.
|
|
92
|
+
*
|
|
93
|
+
* @param {{ pinned: boolean, insideTranscript: boolean, zooming: boolean, insideOwnScroller: boolean }} at
|
|
94
|
+
* @returns {boolean}
|
|
95
|
+
*/
|
|
96
|
+
export function redirectsWheelToTranscript(at) {
|
|
97
|
+
if (!at.pinned || at.zooming || at.insideTranscript || at.insideOwnScroller) {
|
|
98
|
+
return false
|
|
99
|
+
}
|
|
100
|
+
return true
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* True when an element can still scroll in the direction a wheel turn asks for. Used to leave a
|
|
105
|
+
* composer that has its own overflow in charge of its own text.
|
|
106
|
+
* @param {{ scrollTop: number, scrollHeight: number, clientHeight: number }} el
|
|
107
|
+
* @param {number} deltaY
|
|
108
|
+
*/
|
|
109
|
+
export function canScrollBy(el, deltaY) {
|
|
110
|
+
if (deltaY < 0) {
|
|
111
|
+
return el.scrollTop > 0
|
|
112
|
+
}
|
|
113
|
+
return el.scrollTop + el.clientHeight < el.scrollHeight - 1
|
|
114
|
+
}
|