@yadsh/dsh-qa-surface 0.2.0 → 0.3.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/CHANGELOG.md +84 -1
- package/README.md +87 -12
- package/compatibility.json +11 -3
- package/docs/ARCHITECTURE.md +1 -1
- package/docs/COMPATIBILITY.md +1 -1
- package/docs/CONFIGURATION.md +88 -1
- package/docs/SOURCES-MIGRATION.md +28 -0
- package/docs/SOURCES-PROVENANCE-AUDIT.md +88 -0
- package/docs/SPEC-dsh-qa-surface-accounts.md +219 -0
- package/docs/SPEC-dsh-qa-surface-sources-provenance.md +1692 -0
- package/lib/accounts/index.js +2 -0
- package/lib/accounts/index.js.map +1 -0
- package/lib/accounts/store.js +478 -0
- package/lib/accounts/store.js.map +1 -0
- package/lib/attestation.js.map +1 -1
- package/lib/cli.js +143 -0
- package/lib/cli.js.map +1 -0
- package/lib/client/QaAccountsController.js +329 -0
- package/lib/client/QaAccountsController.js.map +1 -0
- package/lib/client/QaSessionController.js +203 -127
- package/lib/client/QaSessionController.js.map +1 -1
- package/lib/client/QaSurface.js +234 -72
- package/lib/client/QaSurface.js.map +1 -1
- package/lib/client/QaTranscriptAdapter.js +27 -241
- package/lib/client/QaTranscriptAdapter.js.map +1 -1
- package/lib/client/attestation.js +6 -0
- package/lib/client/attestation.js.map +1 -1
- package/lib/client/components/Markdown.js +54 -13
- package/lib/client/components/Markdown.js.map +1 -1
- package/lib/client/components/QaAuthGate.js +40 -0
- package/lib/client/components/QaAuthGate.js.map +1 -0
- package/lib/client/components/QaChangelog.js +112 -0
- package/lib/client/components/QaChangelog.js.map +1 -0
- package/lib/client/components/QaMessage.js +47 -17
- package/lib/client/components/QaMessage.js.map +1 -1
- package/lib/client/components/QaSidebar.js +63 -20
- package/lib/client/components/QaSidebar.js.map +1 -1
- package/lib/client/components/QaSourcesDrawer.js +113 -32
- package/lib/client/components/QaSourcesDrawer.js.map +1 -1
- package/lib/client/components/QaTurnRail.js +281 -0
- package/lib/client/components/QaTurnRail.js.map +1 -0
- package/lib/client/components/QaWelcomeNotice.js +125 -0
- package/lib/client/components/QaWelcomeNotice.js.map +1 -0
- package/lib/client/components/QaWidthHandle.js +142 -0
- package/lib/client/components/QaWidthHandle.js.map +1 -0
- package/lib/client/components/source-refs.js +78 -0
- package/lib/client/components/source-refs.js.map +1 -0
- package/lib/client/create-session.js +51 -0
- package/lib/client/create-session.js.map +1 -0
- package/lib/client/index.js +100 -12
- package/lib/client/index.js.map +1 -1
- package/lib/client/project-session-state.js +78 -0
- package/lib/client/project-session-state.js.map +1 -0
- package/lib/client/session-admission.js +38 -0
- package/lib/client/session-admission.js.map +1 -0
- package/lib/client/session-assets.js +52 -0
- package/lib/client/session-assets.js.map +1 -0
- package/lib/client/session-sources.js +61 -0
- package/lib/client/session-sources.js.map +1 -0
- package/lib/client/settlement.js +24 -0
- package/lib/client/settlement.js.map +1 -0
- package/lib/client/styles.js +151 -9
- package/lib/client/styles.js.map +1 -1
- package/lib/client/tool-presentation.js +102 -0
- package/lib/client/tool-presentation.js.map +1 -0
- package/lib/client/turn-sources.js +98 -0
- package/lib/client/turn-sources.js.map +1 -0
- package/lib/client/types.js +2 -0
- package/lib/client/types.js.map +1 -1
- package/lib/client/use-session-ui-state.js +68 -0
- package/lib/client/use-session-ui-state.js.map +1 -0
- package/lib/client/use-transcript-view.js +44 -0
- package/lib/client/use-transcript-view.js.map +1 -0
- package/lib/client.js +4649 -861
- package/lib/client.js.map +1 -1
- package/lib/config.js +218 -102
- package/lib/config.js.map +1 -1
- package/lib/entry-redirect.js +44 -0
- package/lib/entry-redirect.js.map +1 -0
- package/lib/host-route.js +25 -1
- package/lib/host-route.js.map +1 -1
- package/lib/index.js +209 -23
- package/lib/index.js.map +1 -1
- package/lib/launch-token.js +42 -0
- package/lib/launch-token.js.map +1 -0
- package/lib/provenance/collector.js +40 -0
- package/lib/provenance/collector.js.map +1 -0
- package/lib/provenance/connectors.js +147 -0
- package/lib/provenance/connectors.js.map +1 -0
- package/lib/provenance/dedupe.js +89 -0
- package/lib/provenance/dedupe.js.map +1 -0
- package/lib/provenance/extractors.js +340 -0
- package/lib/provenance/extractors.js.map +1 -0
- package/lib/provenance/file-preview.js +39 -0
- package/lib/provenance/file-preview.js.map +1 -0
- package/lib/provenance/host-store.js +387 -0
- package/lib/provenance/host-store.js.map +1 -0
- package/lib/provenance/index.js +9 -0
- package/lib/provenance/index.js.map +1 -0
- package/lib/provenance/normalize.js +128 -0
- package/lib/provenance/normalize.js.map +1 -0
- package/lib/provenance/reported.js +53 -0
- package/lib/provenance/reported.js.map +1 -0
- package/lib/provenance/types.js +2 -0
- package/lib/provenance/types.js.map +1 -0
- package/lib/resolve-config.js +161 -0
- package/lib/resolve-config.js.map +1 -1
- package/lib/secure-session.js +50 -8
- package/lib/secure-session.js.map +1 -1
- package/lib/typert.host.js +599 -6
- package/lib/typert.remote-client.d.ts +19 -3
- package/lib/typert.remote-client.js +471 -3
- package/lib/types/accounts/index.d.ts +2 -0
- package/lib/types/accounts/store.d.ts +121 -0
- package/lib/types/attestation.d.ts +1 -1
- package/lib/types/cli.d.ts +9 -0
- package/lib/types/client/QaAccountsController.d.ts +95 -0
- package/lib/types/client/QaConfigController.d.ts +1 -1
- package/lib/types/client/QaSessionController.d.ts +46 -7
- package/lib/types/client/QaSurface.d.ts +8 -3
- package/lib/types/client/QaTranscriptAdapter.d.ts +5 -10
- package/lib/types/client/components/Markdown.d.ts +11 -1
- package/lib/types/client/components/QaAgentsDrawer.d.ts +1 -1
- package/lib/types/client/components/QaAuthGate.d.ts +15 -0
- package/lib/types/client/components/QaChangelog.d.ts +21 -0
- package/lib/types/client/components/QaMessage.d.ts +10 -3
- package/lib/types/client/components/QaSidebar.d.ts +30 -2
- package/lib/types/client/components/QaSourcesDrawer.d.ts +15 -3
- package/lib/types/client/components/QaTurnRail.d.ts +59 -0
- package/lib/types/client/components/QaWelcomeNotice.d.ts +27 -0
- package/lib/types/client/components/QaWidthHandle.d.ts +36 -0
- package/lib/types/client/components/source-refs.d.ts +16 -0
- package/lib/types/client/create-session.d.ts +16 -0
- package/lib/types/client/index.d.ts +1 -0
- package/lib/types/client/project-session-state.d.ts +30 -0
- package/lib/types/client/session-admission.d.ts +23 -0
- package/lib/types/client/session-assets.d.ts +20 -0
- package/lib/types/client/session-sources.d.ts +28 -0
- package/lib/types/client/settlement.d.ts +6 -0
- package/lib/types/client/tool-presentation.d.ts +6 -0
- package/lib/types/client/turn-sources.d.ts +14 -0
- package/lib/types/client/types.d.ts +73 -9
- package/lib/types/client/use-session-ui-state.d.ts +35 -0
- package/lib/types/client/use-transcript-view.d.ts +20 -0
- package/lib/types/entry-redirect.d.ts +20 -0
- package/lib/types/host-route.d.ts +14 -1
- package/lib/types/index.d.ts +47 -3
- package/lib/types/launch-token.d.ts +21 -0
- package/lib/types/provenance/collector.d.ts +26 -0
- package/lib/types/provenance/connectors.d.ts +11 -0
- package/lib/types/provenance/dedupe.d.ts +6 -0
- package/lib/types/provenance/extractors.d.ts +14 -0
- package/lib/types/provenance/file-preview.d.ts +10 -0
- package/lib/types/provenance/host-store.d.ts +54 -0
- package/lib/types/provenance/index.d.ts +10 -0
- package/lib/types/provenance/normalize.d.ts +13 -0
- package/lib/types/provenance/reported.d.ts +5 -0
- package/lib/types/provenance/types.d.ts +78 -0
- package/lib/types/secure-session.d.ts +11 -2
- package/lib/types/types.d.ts +167 -11
- package/package.json +58 -41
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { memo, useCallback, useEffect, useId, useRef, useState, } from "react";
|
|
3
|
+
/** Transcript attribute marking the message slot that opens a turn. */
|
|
4
|
+
export const QA_TURN_ANCHOR_ATTRIBUTE = "data-dsh-qa-turn-anchor";
|
|
5
|
+
/** Scroll distance from the floor at which the rail still calls it "at bottom". */
|
|
6
|
+
export const QA_TURN_FOLLOW_PX = 96;
|
|
7
|
+
/** The reading line: reading offset from the scrollport top while scrolling. */
|
|
8
|
+
export const QA_TURN_READING_PX = 96;
|
|
9
|
+
/** Where a jump lands its prompt row, mirroring the harness chat rail. */
|
|
10
|
+
const QA_TURN_LAND_PX = 24;
|
|
11
|
+
const PROMPT_CLIP = 140;
|
|
12
|
+
const RESPONSE_CLIP = 220;
|
|
13
|
+
function clipPreview(text, max) {
|
|
14
|
+
const flat = text.replace(/\s+/gu, " ").trim();
|
|
15
|
+
if (flat.length <= max)
|
|
16
|
+
return flat;
|
|
17
|
+
return `${flat.slice(0, max - 1).trimEnd()}…`;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Rail ladder of the visible transcript: every user prompt opens a turn, the
|
|
21
|
+
* first non-empty answer after it fills the response preview. Hidden variant
|
|
22
|
+
* answers never reach this list because callers pass the already-filtered
|
|
23
|
+
* messages.
|
|
24
|
+
*/
|
|
25
|
+
export function buildTurnRailItems(messages) {
|
|
26
|
+
const items = [];
|
|
27
|
+
for (const message of messages) {
|
|
28
|
+
if (message.role === "user") {
|
|
29
|
+
items.push({
|
|
30
|
+
turn: items.length + 1,
|
|
31
|
+
id: message.id,
|
|
32
|
+
prompt: clipPreview(message.text, PROMPT_CLIP),
|
|
33
|
+
response: "",
|
|
34
|
+
});
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
if (message.role !== "assistant" || items.length === 0)
|
|
38
|
+
continue;
|
|
39
|
+
const current = items.at(-1);
|
|
40
|
+
if (current === undefined || current.response !== "")
|
|
41
|
+
continue;
|
|
42
|
+
const response = clipPreview(message.text, RESPONSE_CLIP);
|
|
43
|
+
if (response !== "")
|
|
44
|
+
items[items.length - 1] = { ...current, response };
|
|
45
|
+
}
|
|
46
|
+
return items;
|
|
47
|
+
}
|
|
48
|
+
/** Deep equality guard so the memoized rail skips streaming commits. */
|
|
49
|
+
export function sameTurnRailItems(left, right) {
|
|
50
|
+
if (left === right)
|
|
51
|
+
return true;
|
|
52
|
+
if (left.length !== right.length)
|
|
53
|
+
return false;
|
|
54
|
+
return left.every((item, index) => {
|
|
55
|
+
const other = right[index];
|
|
56
|
+
return (other !== undefined &&
|
|
57
|
+
item.turn === other.turn &&
|
|
58
|
+
item.id === other.id &&
|
|
59
|
+
item.prompt === other.prompt &&
|
|
60
|
+
item.response === other.response);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Turn owning the transcript's reading line, or the newest one while the
|
|
65
|
+
* reader follows the live tail. Anchors above the line are scanned in flow
|
|
66
|
+
* order; the last one at or above it owns the mark.
|
|
67
|
+
*/
|
|
68
|
+
export function computeActiveTurn(scroller, items) {
|
|
69
|
+
if (items.length === 0)
|
|
70
|
+
return null;
|
|
71
|
+
const last = items.at(-1);
|
|
72
|
+
if (last === undefined)
|
|
73
|
+
return null;
|
|
74
|
+
if (scroller.scrollHeight - scroller.scrollTop - scroller.clientHeight <=
|
|
75
|
+
QA_TURN_FOLLOW_PX + 1) {
|
|
76
|
+
return last.turn;
|
|
77
|
+
}
|
|
78
|
+
const line = scroller.getBoundingClientRect().top +
|
|
79
|
+
Math.min(QA_TURN_READING_PX, scroller.clientHeight * 0.2);
|
|
80
|
+
const turnByAnchor = new Map(items.map((item) => [item.id, item.turn]));
|
|
81
|
+
const first = items[0];
|
|
82
|
+
if (first === undefined)
|
|
83
|
+
return null;
|
|
84
|
+
let next = first.turn;
|
|
85
|
+
for (const row of scroller.querySelectorAll(`[${QA_TURN_ANCHOR_ATTRIBUTE}]`)) {
|
|
86
|
+
if (row.getBoundingClientRect().top > line)
|
|
87
|
+
break;
|
|
88
|
+
const turn = turnByAnchor.get(row.getAttribute(QA_TURN_ANCHOR_ATTRIBUTE) ?? "");
|
|
89
|
+
if (turn !== undefined)
|
|
90
|
+
next = turn;
|
|
91
|
+
}
|
|
92
|
+
return next;
|
|
93
|
+
}
|
|
94
|
+
/** Fixed pitch between neighbouring marks; overflow scrolls inside the frame. */
|
|
95
|
+
const TURN_SPACING_PX = 10;
|
|
96
|
+
/** Rail padding above the first mark and below the last one, per end. */
|
|
97
|
+
const RAIL_INSET_PX = 6;
|
|
98
|
+
/** Fade band the mask reserves at a scrollable end. */
|
|
99
|
+
const FADE_PX = 24;
|
|
100
|
+
const RAIL_AT_REST = {
|
|
101
|
+
top: 0,
|
|
102
|
+
canScrollUp: false,
|
|
103
|
+
canScrollDown: false,
|
|
104
|
+
};
|
|
105
|
+
function railScrollState(scroller) {
|
|
106
|
+
const top = scroller.scrollTop;
|
|
107
|
+
return {
|
|
108
|
+
top,
|
|
109
|
+
canScrollUp: top > 1,
|
|
110
|
+
canScrollDown: top < scroller.scrollHeight - scroller.clientHeight - 1,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function sameRailScrollState(left, right) {
|
|
114
|
+
return (left.top === right.top &&
|
|
115
|
+
left.canScrollUp === right.canScrollUp &&
|
|
116
|
+
left.canScrollDown === right.canScrollDown);
|
|
117
|
+
}
|
|
118
|
+
function itemAtPointer(items, frame, scrollTop, clientY) {
|
|
119
|
+
const rect = frame.getBoundingClientRect();
|
|
120
|
+
const offset = clientY - rect.top + scrollTop - RAIL_INSET_PX;
|
|
121
|
+
const index = Math.max(0, Math.min(items.length - 1, Math.round(offset / TURN_SPACING_PX)));
|
|
122
|
+
return items[index];
|
|
123
|
+
}
|
|
124
|
+
function QaTurnRailView({ items, activeTurn, busyTurn, scrollerRef, onNavigate, }) {
|
|
125
|
+
const slotRef = useRef(null);
|
|
126
|
+
const ladderRef = useRef(null);
|
|
127
|
+
/** While the pointer works the rail, follow must not move it under the hand. */
|
|
128
|
+
const pointerInsideRef = useRef(false);
|
|
129
|
+
const [previewTurn, setPreviewTurn] = useState(null);
|
|
130
|
+
const [scrollState, setScrollState] = useState(RAIL_AT_REST);
|
|
131
|
+
const previewId = useId();
|
|
132
|
+
// The band the marks centre in is the transcript scrollport's own height;
|
|
133
|
+
// publish it as a custom property so the frame can centre without knowing
|
|
134
|
+
// the header/composer layout around it.
|
|
135
|
+
useEffect(() => {
|
|
136
|
+
const slot = slotRef.current;
|
|
137
|
+
const scroller = scrollerRef.current;
|
|
138
|
+
if (slot === null || scroller === null)
|
|
139
|
+
return;
|
|
140
|
+
const apply = () => {
|
|
141
|
+
slot.style.setProperty("--dsh-qa-rail-band", `${scroller.clientHeight}px`);
|
|
142
|
+
};
|
|
143
|
+
apply();
|
|
144
|
+
if (typeof ResizeObserver === "undefined")
|
|
145
|
+
return;
|
|
146
|
+
const observer = new ResizeObserver(apply);
|
|
147
|
+
observer.observe(scroller);
|
|
148
|
+
return () => {
|
|
149
|
+
observer.disconnect();
|
|
150
|
+
};
|
|
151
|
+
}, [scrollerRef]);
|
|
152
|
+
const syncScrollState = useCallback(() => {
|
|
153
|
+
const ladder = ladderRef.current;
|
|
154
|
+
if (ladder === null)
|
|
155
|
+
return;
|
|
156
|
+
const next = railScrollState(ladder);
|
|
157
|
+
setScrollState((current) => sameRailScrollState(current, next) ? current : next);
|
|
158
|
+
}, []);
|
|
159
|
+
// Frame resizes (band changes) move the overflow edges without a scroll
|
|
160
|
+
// event; item count changes move the content height the same way.
|
|
161
|
+
useEffect(() => {
|
|
162
|
+
const ladder = ladderRef.current;
|
|
163
|
+
if (ladder === null || typeof ResizeObserver === "undefined")
|
|
164
|
+
return;
|
|
165
|
+
const observer = new ResizeObserver(syncScrollState);
|
|
166
|
+
observer.observe(ladder);
|
|
167
|
+
return () => {
|
|
168
|
+
observer.disconnect();
|
|
169
|
+
};
|
|
170
|
+
}, [syncScrollState]);
|
|
171
|
+
useEffect(() => {
|
|
172
|
+
syncScrollState();
|
|
173
|
+
}, [items.length, syncScrollState]);
|
|
174
|
+
// Keep the active mark visible: centre it whenever it leaves the scrollport,
|
|
175
|
+
// unless the reader's pointer is working the rail.
|
|
176
|
+
useEffect(() => {
|
|
177
|
+
const ladder = ladderRef.current;
|
|
178
|
+
const index = items.findIndex((item) => item.turn === activeTurn);
|
|
179
|
+
if (ladder === null || index < 0 || pointerInsideRef.current)
|
|
180
|
+
return;
|
|
181
|
+
const markTop = index * TURN_SPACING_PX + RAIL_INSET_PX;
|
|
182
|
+
const viewTop = ladder.scrollTop;
|
|
183
|
+
const viewHeight = ladder.clientHeight;
|
|
184
|
+
if (viewHeight <= 0 ||
|
|
185
|
+
(markTop >= viewTop + FADE_PX &&
|
|
186
|
+
markTop <= viewTop + viewHeight - FADE_PX)) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
const target = Math.max(0, markTop - viewHeight / 2);
|
|
190
|
+
const reduced = typeof matchMedia === "function" &&
|
|
191
|
+
matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
192
|
+
if (typeof ladder.scrollTo === "function") {
|
|
193
|
+
ladder.scrollTo({ top: target, behavior: reduced ? "auto" : "smooth" });
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
ladder.scrollTop = target;
|
|
197
|
+
}
|
|
198
|
+
syncScrollState();
|
|
199
|
+
}, [activeTurn, items, syncScrollState]);
|
|
200
|
+
if (items.length < 2)
|
|
201
|
+
return null;
|
|
202
|
+
const previewIndex = items.findIndex((item) => item.turn === previewTurn);
|
|
203
|
+
const preview = previewIndex < 0 ? undefined : items[previewIndex];
|
|
204
|
+
const previewPosition = previewIndex < 0 ? undefined : previewIndex * TURN_SPACING_PX;
|
|
205
|
+
const previewAtPointer = (event) => {
|
|
206
|
+
const scrollTop = ladderRef.current?.scrollTop ?? 0;
|
|
207
|
+
setPreviewTurn(itemAtPointer(items, event.currentTarget, scrollTop, event.clientY)
|
|
208
|
+
?.turn ?? null);
|
|
209
|
+
};
|
|
210
|
+
const navigateAtPointer = (event) => {
|
|
211
|
+
const scrollTop = ladderRef.current?.scrollTop ?? 0;
|
|
212
|
+
const item = itemAtPointer(items, event.currentTarget, scrollTop, event.clientY);
|
|
213
|
+
if (item !== undefined)
|
|
214
|
+
onNavigate(item);
|
|
215
|
+
};
|
|
216
|
+
const ladderClasses = ["dsh-qa-rail__scroll"];
|
|
217
|
+
if (scrollState.canScrollUp)
|
|
218
|
+
ladderClasses.push("dsh-qa-rail__scroll--fade-top");
|
|
219
|
+
if (scrollState.canScrollDown) {
|
|
220
|
+
ladderClasses.push("dsh-qa-rail__scroll--fade-bottom");
|
|
221
|
+
}
|
|
222
|
+
return (_jsx("div", { ref: slotRef, className: "dsh-qa-rail", children: _jsxs("nav", { className: "dsh-qa-rail__frame", style: {
|
|
223
|
+
"--dsh-qa-rail-natural": `${(items.length - 1) * TURN_SPACING_PX + 2 * RAIL_INSET_PX}px`,
|
|
224
|
+
"--dsh-qa-rail-scroll-top": `${scrollState.top}px`,
|
|
225
|
+
}, "aria-label": "\u041F\u0435\u0440\u0435\u0445\u043E\u0434 \u043F\u043E \u0432\u043E\u043F\u0440\u043E\u0441\u0430\u043C", onClick: navigateAtPointer, onPointerMove: previewAtPointer, onPointerEnter: () => {
|
|
226
|
+
pointerInsideRef.current = true;
|
|
227
|
+
}, onPointerLeave: () => {
|
|
228
|
+
pointerInsideRef.current = false;
|
|
229
|
+
setPreviewTurn(null);
|
|
230
|
+
}, children: [_jsx("div", { ref: ladderRef, className: ladderClasses.join(" "), onScroll: () => {
|
|
231
|
+
syncScrollState();
|
|
232
|
+
}, children: _jsx("div", { className: "dsh-qa-rail__marks", children: items.map((item, index) => {
|
|
233
|
+
const active = item.turn === activeTurn;
|
|
234
|
+
const showingPreview = item.turn === previewTurn;
|
|
235
|
+
const classes = ["dsh-qa-rail__mark"];
|
|
236
|
+
if (active)
|
|
237
|
+
classes.push("dsh-qa-rail__mark--active");
|
|
238
|
+
else if (showingPreview) {
|
|
239
|
+
classes.push("dsh-qa-rail__mark--preview");
|
|
240
|
+
}
|
|
241
|
+
if (item.turn === busyTurn)
|
|
242
|
+
classes.push("dsh-qa-rail__mark--busy");
|
|
243
|
+
return (_jsx("div", { className: "dsh-qa-rail__pos", style: {
|
|
244
|
+
"--dsh-qa-rail-pos": `${index * TURN_SPACING_PX}px`,
|
|
245
|
+
}, children: _jsx("button", { type: "button", className: classes.join(" "), "aria-label": `К вопросу ${item.turn}`, "aria-current": active ? "true" : undefined, "aria-busy": item.turn === busyTurn ? "true" : undefined, "aria-describedby": showingPreview ? previewId : undefined, onClick: (event) => {
|
|
246
|
+
event.stopPropagation();
|
|
247
|
+
onNavigate(item);
|
|
248
|
+
}, onFocus: () => {
|
|
249
|
+
setPreviewTurn(item.turn);
|
|
250
|
+
}, onBlur: () => {
|
|
251
|
+
setPreviewTurn(null);
|
|
252
|
+
} }) }, item.turn));
|
|
253
|
+
}) }) }), preview !== undefined && previewPosition !== undefined ? (_jsxs("div", { id: previewId, role: "tooltip", className: "dsh-qa-rail__preview", style: {
|
|
254
|
+
"--dsh-qa-rail-pos": `${previewPosition}px`,
|
|
255
|
+
}, children: [_jsx("div", { className: "dsh-qa-rail__preview-prompt", children: preview.prompt }), preview.response === "" ? null : (_jsx("div", { className: "dsh-qa-rail__preview-response", children: preview.response }))] })) : null] }) }));
|
|
256
|
+
}
|
|
257
|
+
function sameRailProps(previous, next) {
|
|
258
|
+
return (previous.activeTurn === next.activeTurn &&
|
|
259
|
+
previous.busyTurn === next.busyTurn &&
|
|
260
|
+
previous.scrollerRef === next.scrollerRef &&
|
|
261
|
+
previous.onNavigate === next.onNavigate &&
|
|
262
|
+
sameTurnRailItems(previous.items, next.items));
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Fixed-pitch rail of every turn of the visible transcript, floating over the
|
|
266
|
+
* transcript's right gutter: the active mark follows the reading line, a
|
|
267
|
+
* hover/focus preview shows the prompt and answer, and a click lands the
|
|
268
|
+
* transcript on that turn. Memoized like the harness rail — the transcript
|
|
269
|
+
* re-renders on every streaming delta, and the rail only changes when a turn
|
|
270
|
+
* is added or becomes active.
|
|
271
|
+
*/
|
|
272
|
+
export const QaTurnRail = memo(QaTurnRailView, sameRailProps);
|
|
273
|
+
/** Land the transcript on a turn's prompt row, harness-style. */
|
|
274
|
+
export function turnScrollTarget(scroller, row) {
|
|
275
|
+
const top = scroller.scrollTop +
|
|
276
|
+
row.getBoundingClientRect().top -
|
|
277
|
+
scroller.getBoundingClientRect().top;
|
|
278
|
+
const max = Math.max(0, scroller.scrollHeight - scroller.clientHeight);
|
|
279
|
+
return Math.min(max, Math.max(0, top - QA_TURN_LAND_PX));
|
|
280
|
+
}
|
|
281
|
+
//# sourceMappingURL=QaTurnRail.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QaTurnRail.js","sourceRoot":"","sources":["../../../src/client/components/QaTurnRail.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useEffect, useRef, useState, } from "react";
|
|
3
|
+
import { createPortal } from "react-dom";
|
|
4
|
+
/** Bump when the notice changes materially and must be acknowledged again. */
|
|
5
|
+
export const QA_WELCOME_NOTICE_VERSION = "2026-09-12.1";
|
|
6
|
+
export const QA_WELCOME_NOTICE_COPY = Object.freeze({
|
|
7
|
+
title: "Перед началом тестирования",
|
|
8
|
+
paragraphs: Object.freeze([
|
|
9
|
+
"Этот помощник разработан не с нуля: он основан на DeepSeek Harness. Платформа находится в preview, поэтому возможны ошибки, нестабильная работа и изменения поведения.",
|
|
10
|
+
"На этапе тестирования заданные вопросы и полученные ответы будут анализироваться для повышения качества помощника. Пожалуйста, задавайте преимущественно вопросы, связанные с работой.",
|
|
11
|
+
"Помощник использует локальные модели. Данные обрабатываются внутри контура и никуда за его пределы не передаются.",
|
|
12
|
+
]),
|
|
13
|
+
continueLabel: "Понятно, продолжить",
|
|
14
|
+
});
|
|
15
|
+
const QA_WELCOME_ACKNOWLEDGED_EVENT = "dsh-qa-welcome-acknowledged";
|
|
16
|
+
function acknowledged(storage, key) {
|
|
17
|
+
try {
|
|
18
|
+
return storage.getItem(key) === QA_WELCOME_NOTICE_VERSION;
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function focusable(root) {
|
|
25
|
+
return [
|
|
26
|
+
...root.querySelectorAll("button:not([disabled]), a[href], input:not([disabled]), [tabindex]:not([tabindex='-1'])"),
|
|
27
|
+
].filter((element) => !element.hidden);
|
|
28
|
+
}
|
|
29
|
+
/** Route-scoped replacement for DSH's stock `welcome-notice` onboarding step. */
|
|
30
|
+
export function QaWelcomeNotice(props) {
|
|
31
|
+
const [isAcknowledged, setAcknowledged] = useState(() => acknowledged(props.storage, props.storageKey));
|
|
32
|
+
const completed = useRef(false);
|
|
33
|
+
const dialog = useRef(null);
|
|
34
|
+
const continueButton = useRef(null);
|
|
35
|
+
const complete = useCallback(() => {
|
|
36
|
+
if (completed.current)
|
|
37
|
+
return;
|
|
38
|
+
completed.current = true;
|
|
39
|
+
props.complete?.();
|
|
40
|
+
}, [props.complete]);
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
if (isAcknowledged)
|
|
43
|
+
complete();
|
|
44
|
+
}, [complete, isAcknowledged]);
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
if (isAcknowledged)
|
|
47
|
+
return;
|
|
48
|
+
const appRoot = document.getElementById("root");
|
|
49
|
+
const wasInert = appRoot?.inert;
|
|
50
|
+
if (appRoot !== null)
|
|
51
|
+
appRoot.inert = true;
|
|
52
|
+
continueButton.current?.focus();
|
|
53
|
+
return () => {
|
|
54
|
+
if (appRoot !== null)
|
|
55
|
+
appRoot.inert = wasInert ?? false;
|
|
56
|
+
};
|
|
57
|
+
}, [isAcknowledged]);
|
|
58
|
+
const confirm = useCallback(() => {
|
|
59
|
+
try {
|
|
60
|
+
props.storage.setItem(props.storageKey, QA_WELCOME_NOTICE_VERSION);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// A denied localStorage write only costs persistence across reloads.
|
|
64
|
+
}
|
|
65
|
+
setAcknowledged(true);
|
|
66
|
+
window.dispatchEvent(new CustomEvent(QA_WELCOME_ACKNOWLEDGED_EVENT, {
|
|
67
|
+
detail: props.storageKey,
|
|
68
|
+
}));
|
|
69
|
+
complete();
|
|
70
|
+
}, [complete, props.storage, props.storageKey]);
|
|
71
|
+
const trapKeys = useCallback((event) => {
|
|
72
|
+
if (event.key === "Escape") {
|
|
73
|
+
event.preventDefault();
|
|
74
|
+
event.stopPropagation();
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if (event.key !== "Tab" || dialog.current === null)
|
|
78
|
+
return;
|
|
79
|
+
const items = focusable(dialog.current);
|
|
80
|
+
if (items.length === 0) {
|
|
81
|
+
event.preventDefault();
|
|
82
|
+
dialog.current.focus();
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const first = items[0];
|
|
86
|
+
const last = items.at(-1);
|
|
87
|
+
if (event.shiftKey && document.activeElement === first) {
|
|
88
|
+
event.preventDefault();
|
|
89
|
+
last?.focus();
|
|
90
|
+
}
|
|
91
|
+
else if (!event.shiftKey && document.activeElement === last) {
|
|
92
|
+
event.preventDefault();
|
|
93
|
+
first?.focus();
|
|
94
|
+
}
|
|
95
|
+
}, []);
|
|
96
|
+
if (isAcknowledged)
|
|
97
|
+
return null;
|
|
98
|
+
return createPortal(_jsx("div", { className: "dsh-qa-onboarding", onKeyDown: trapKeys, children: _jsxs("div", { ref: dialog, className: "dsh-qa-onboarding__panel", role: "dialog", "aria-modal": "true", "aria-labelledby": "dsh-qa-onboarding-title", "aria-describedby": "dsh-qa-onboarding-description", tabIndex: -1, children: [_jsx("div", { className: "dsh-qa-onboarding__mark", "aria-hidden": "true", children: _jsxs("svg", { viewBox: "0 0 24 24", children: [_jsx("path", { d: "M12 3.5 20 8v8l-8 4.5L4 16V8l8-4.5Z" }), _jsx("path", { d: "m8.75 12 2 2 4.5-4.5" })] }) }), _jsxs("div", { className: "dsh-qa-onboarding__content", children: [_jsx("h1", { id: "dsh-qa-onboarding-title", className: "dsh-qa-onboarding__title", children: QA_WELCOME_NOTICE_COPY.title }), _jsx("div", { id: "dsh-qa-onboarding-description", className: "dsh-qa-onboarding__description", children: QA_WELCOME_NOTICE_COPY.paragraphs.map((paragraph) => (_jsx("p", { children: paragraph }, paragraph))) }), _jsx("div", { className: "dsh-qa-onboarding__actions", children: _jsx("button", { ref: continueButton, type: "button", className: "dsh-qa-onboarding__continue", onClick: confirm, children: QA_WELCOME_NOTICE_COPY.continueLabel }) })] })] }) }), document.body);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Invisible shadow for DSH's stock welcome step. The host coordinator removes
|
|
102
|
+
* onboarding content as soon as a chat stops being blank, so the visible QA
|
|
103
|
+
* notice is owned by the route overlay above instead of this lifecycle.
|
|
104
|
+
*/
|
|
105
|
+
export function QaWelcomeNoticeStep(props) {
|
|
106
|
+
const [isAcknowledged, setAcknowledged] = useState(() => acknowledged(props.storage, props.storageKey));
|
|
107
|
+
const completed = useRef(false);
|
|
108
|
+
useEffect(() => {
|
|
109
|
+
const handleAcknowledged = (event) => {
|
|
110
|
+
if (event instanceof CustomEvent && event.detail === props.storageKey) {
|
|
111
|
+
setAcknowledged(true);
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
window.addEventListener(QA_WELCOME_ACKNOWLEDGED_EVENT, handleAcknowledged);
|
|
115
|
+
return () => window.removeEventListener(QA_WELCOME_ACKNOWLEDGED_EVENT, handleAcknowledged);
|
|
116
|
+
}, [props.storageKey]);
|
|
117
|
+
useEffect(() => {
|
|
118
|
+
if (!isAcknowledged || completed.current)
|
|
119
|
+
return;
|
|
120
|
+
completed.current = true;
|
|
121
|
+
props.complete();
|
|
122
|
+
}, [isAcknowledged, props.complete]);
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=QaWelcomeNotice.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QaWelcomeNotice.js","sourceRoot":"","sources":["../../../src/client/components/QaWelcomeNotice.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useEffect, useLayoutEffect, useRef, useState, } from "react";
|
|
3
|
+
/** DSH's dragged content-width floor; a lower operator cap still wins. */
|
|
4
|
+
export const QA_CONTENT_MIN_WIDTH = 640;
|
|
5
|
+
/**
|
|
6
|
+
* Space kept outside the content: 88px per side leaves room for the handle,
|
|
7
|
+
* its inset, and a safe zone that remains draggable in both directions.
|
|
8
|
+
*/
|
|
9
|
+
export const QA_CONTENT_EDGE_BUDGET = 176;
|
|
10
|
+
const QA_ADAPTIVE_MIN_WIDTH = 680;
|
|
11
|
+
const QA_ADAPTIVE_MAX_WIDTH = 920;
|
|
12
|
+
export function readQaContentWidth(storage, key) {
|
|
13
|
+
try {
|
|
14
|
+
const raw = storage.getItem(key);
|
|
15
|
+
if (raw === null)
|
|
16
|
+
return null;
|
|
17
|
+
const value = Number(raw);
|
|
18
|
+
return Number.isFinite(value) && value > 0 ? value : null;
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export function writeQaContentWidth(storage, key, width) {
|
|
25
|
+
try {
|
|
26
|
+
storage.setItem(key, `${width}`);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
// Denied durable storage only costs persistence across reloads.
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/** Resolve the centered content width for the currently available column. */
|
|
33
|
+
export function resolveQaContentWidth(columnWidth, preference, maxContentWidth) {
|
|
34
|
+
const available = Math.max(0, columnWidth - QA_CONTENT_EDGE_BUDGET);
|
|
35
|
+
const maximum = Math.min(maxContentWidth, available);
|
|
36
|
+
const minimum = Math.min(QA_CONTENT_MIN_WIDTH, maximum);
|
|
37
|
+
const adaptive = Math.min(maxContentWidth, Math.max(QA_ADAPTIVE_MIN_WIDTH, Math.min(columnWidth * 0.64, QA_ADAPTIVE_MAX_WIDTH)));
|
|
38
|
+
const requested = preference ?? adaptive;
|
|
39
|
+
return Math.min(Math.max(requested, minimum), maximum);
|
|
40
|
+
}
|
|
41
|
+
/** Pointer-captured, rAF-throttled symmetric content-width handle. */
|
|
42
|
+
export function QaWidthHandle(props) {
|
|
43
|
+
const [dragging, setDragging] = useState(false);
|
|
44
|
+
const base = useRef(0);
|
|
45
|
+
const origin = useRef(0);
|
|
46
|
+
const latest = useRef(0);
|
|
47
|
+
const frame = useRef(null);
|
|
48
|
+
const callbacks = useRef(props);
|
|
49
|
+
callbacks.current = props;
|
|
50
|
+
const outwardWidth = () => {
|
|
51
|
+
const delta = latest.current - origin.current;
|
|
52
|
+
const outward = callbacks.current.side === "right" ? delta : -delta;
|
|
53
|
+
return base.current + outward * 2;
|
|
54
|
+
};
|
|
55
|
+
const cancelFrame = useCallback(() => {
|
|
56
|
+
if (frame.current === null)
|
|
57
|
+
return;
|
|
58
|
+
cancelAnimationFrame(frame.current);
|
|
59
|
+
frame.current = null;
|
|
60
|
+
}, []);
|
|
61
|
+
useEffect(() => cancelFrame, [cancelFrame]);
|
|
62
|
+
const onPointerDown = useCallback((event) => {
|
|
63
|
+
event.preventDefault();
|
|
64
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
65
|
+
origin.current = event.clientX;
|
|
66
|
+
latest.current = event.clientX;
|
|
67
|
+
base.current = callbacks.current.onStart();
|
|
68
|
+
setDragging(true);
|
|
69
|
+
}, []);
|
|
70
|
+
const onPointerMove = useCallback((event) => {
|
|
71
|
+
const box = event.currentTarget.getBoundingClientRect();
|
|
72
|
+
event.currentTarget.style.setProperty("--dsh-qa-width-handle-pointer-y", `${event.clientY - box.top}px`);
|
|
73
|
+
if (!event.currentTarget.hasPointerCapture(event.pointerId))
|
|
74
|
+
return;
|
|
75
|
+
latest.current = event.clientX;
|
|
76
|
+
frame.current ??= requestAnimationFrame(() => {
|
|
77
|
+
frame.current = null;
|
|
78
|
+
callbacks.current.onDrag(outwardWidth());
|
|
79
|
+
});
|
|
80
|
+
}, []);
|
|
81
|
+
const onPointerUp = useCallback((event) => {
|
|
82
|
+
if (!event.currentTarget.hasPointerCapture(event.pointerId))
|
|
83
|
+
return;
|
|
84
|
+
event.currentTarget.releasePointerCapture(event.pointerId);
|
|
85
|
+
cancelFrame();
|
|
86
|
+
latest.current = event.clientX;
|
|
87
|
+
if (latest.current !== origin.current) {
|
|
88
|
+
callbacks.current.onCommit(outwardWidth());
|
|
89
|
+
}
|
|
90
|
+
setDragging(false);
|
|
91
|
+
callbacks.current.onEnd();
|
|
92
|
+
}, [cancelFrame]);
|
|
93
|
+
const onPointerCancel = useCallback(() => {
|
|
94
|
+
cancelFrame();
|
|
95
|
+
setDragging(false);
|
|
96
|
+
callbacks.current.onEnd();
|
|
97
|
+
}, [cancelFrame]);
|
|
98
|
+
return (_jsx("div", { className: "dsh-qa-width-handle", "data-side": props.side, "data-width-handle": props.side, "data-dragging": dragging || undefined, onPointerDown: onPointerDown, onPointerMove: onPointerMove, onPointerUp: onPointerUp, onPointerCancel: onPointerCancel, onLostPointerCapture: onPointerCancel }));
|
|
99
|
+
}
|
|
100
|
+
export function useQaContentWidth({ active, root, storage, storageKey, maxContentWidth, }) {
|
|
101
|
+
const publish = useCallback(() => {
|
|
102
|
+
const element = root.current;
|
|
103
|
+
if (element === null)
|
|
104
|
+
return;
|
|
105
|
+
const preference = readQaContentWidth(storage, storageKey);
|
|
106
|
+
const width = resolveQaContentWidth(element.offsetWidth, preference, maxContentWidth);
|
|
107
|
+
element.style.setProperty("--dsh-qa-content-width", `${width}px`);
|
|
108
|
+
}, [maxContentWidth, root, storage, storageKey]);
|
|
109
|
+
useLayoutEffect(() => {
|
|
110
|
+
if (!active)
|
|
111
|
+
return;
|
|
112
|
+
const element = root.current;
|
|
113
|
+
if (element === null)
|
|
114
|
+
return;
|
|
115
|
+
publish();
|
|
116
|
+
const observer = new ResizeObserver(publish);
|
|
117
|
+
observer.observe(element);
|
|
118
|
+
return () => observer.disconnect();
|
|
119
|
+
}, [active, publish, root]);
|
|
120
|
+
const onStart = useCallback(() => {
|
|
121
|
+
const element = root.current;
|
|
122
|
+
if (element === null)
|
|
123
|
+
return maxContentWidth;
|
|
124
|
+
return resolveQaContentWidth(element.offsetWidth, readQaContentWidth(storage, storageKey), maxContentWidth);
|
|
125
|
+
}, [maxContentWidth, root, storage, storageKey]);
|
|
126
|
+
const onDrag = useCallback((requestedWidth) => {
|
|
127
|
+
const element = root.current;
|
|
128
|
+
if (element === null)
|
|
129
|
+
return;
|
|
130
|
+
const width = resolveQaContentWidth(element.offsetWidth, requestedWidth, maxContentWidth);
|
|
131
|
+
element.style.setProperty("--dsh-qa-content-width", `${width}px`);
|
|
132
|
+
}, [maxContentWidth, root]);
|
|
133
|
+
const onCommit = useCallback((requestedWidth) => {
|
|
134
|
+
const element = root.current;
|
|
135
|
+
if (element === null)
|
|
136
|
+
return;
|
|
137
|
+
const width = resolveQaContentWidth(element.offsetWidth, requestedWidth, maxContentWidth);
|
|
138
|
+
writeQaContentWidth(storage, storageKey, width);
|
|
139
|
+
}, [maxContentWidth, root, storage, storageKey]);
|
|
140
|
+
return { onStart, onDrag, onCommit, onEnd: publish };
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=QaWidthHandle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QaWidthHandle.js","sourceRoot":"","sources":["../../../src/client/components/QaWidthHandle.tsx"],"names":[],"mappings":"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"}
|