dsh-sidenote 0.8.3 → 0.8.5
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/lib/client.js +375 -160
- package/lib/index.js +5 -1
- package/lib/types/client/annotate/anchor.d.ts +2 -2
- package/lib/types/client/annotate/overlay.d.ts +1 -0
- package/lib/types/client/annotate/selection.d.ts +6 -14
- package/lib/types/client/annotations/format.d.ts +1 -1
- package/lib/types/client/annotations/model.d.ts +10 -6
- package/lib/types/client/annotations/source.d.ts +5 -0
- package/lib/types/client/host/dom.d.ts +5 -1
- package/lib/types/client/host/replyDefaults.d.ts +19 -0
- package/lib/types/client/locales.d.ts +2 -0
- package/lib/types/client/preferences.d.ts +6 -3
- package/lib/types/client/sidechat/context.d.ts +1 -0
- package/lib/types/settings.d.ts +4 -0
- package/package.json +1 -1
- package/src/client/annotate/anchor.ts +32 -22
- package/src/client/annotate/annotate.module.css +10 -5
- package/src/client/annotate/overlay.tsx +89 -51
- package/src/client/annotate/selection.ts +26 -30
- package/src/client/annotations/format.ts +7 -3
- package/src/client/annotations/model.ts +50 -16
- package/src/client/annotations/send.ts +11 -2
- package/src/client/annotations/source.ts +56 -8
- package/src/client/host/dom.ts +14 -1
- package/src/client/host/replyDefaults.ts +38 -0
- package/src/client/host/submission.ts +9 -2
- package/src/client/index.tsx +8 -2
- package/src/client/locales.ts +4 -0
- package/src/client/preferences.ts +19 -14
- package/src/client/settings.tsx +9 -0
- package/src/client/sidechat/ContextProgress.tsx +1 -1
- package/src/client/sidechat/context.ts +3 -2
- package/src/settings.ts +2 -0
package/lib/client.js
CHANGED
|
@@ -330,7 +330,18 @@ window.__ModuleLoader__.load({
|
|
|
330
330
|
/** Internal conversation DOM seams, validated by the pinned host journeys.
|
|
331
331
|
* Main message markers and composer seats have no public replacement API. */
|
|
332
332
|
const MAIN_ASSISTANT = "[data-chat-flow-kind=\"assistant-step\"]";
|
|
333
|
-
const NON_QUOTE = "button, [role=\"button\"], input, textarea, select, [contenteditable=\"true\"], [data-code-block-banner], [data-variant=\"think\"], [data-sidenote-no-quote]";
|
|
333
|
+
const NON_QUOTE = "button, [role=\"button\"], input, textarea, select, [contenteditable=\"true\"], [data-code-block-banner], [data-variant=\"think\"], [data-chat-group-part=\"reasoning\"], [data-sidenote-no-quote]";
|
|
334
|
+
const PROCESS_UI = "[data-variant=\"think\"], [data-chat-group-part=\"reasoning\"], [data-chat-flow-kind=\"tool-call\"], [data-chat-flow-kind=\"tool-result\"], [data-chat-flow-kind=\"turn-process\"], [data-context-kind=\"thinking\"], [data-context-kind=\"tool\"]";
|
|
335
|
+
/** Collapsed process rows can remain mounted, including during their animation. */
|
|
336
|
+
function quoteNodeVisible(node) {
|
|
337
|
+
for (let element = elementOf(node); element !== null; element = element.parentElement) {
|
|
338
|
+
if (element.matches("[hidden], [data-turn-process-hidden], [data-turn-process-inline]")) return false;
|
|
339
|
+
if (element instanceof HTMLDetailsElement && !element.open && !element.querySelector(":scope > summary")?.contains(node)) return false;
|
|
340
|
+
const style = getComputedStyle(element);
|
|
341
|
+
if (style.display === "none" || style.visibility === "hidden") return false;
|
|
342
|
+
}
|
|
343
|
+
return true;
|
|
344
|
+
}
|
|
334
345
|
function nativeAssistantBodies(root = document) {
|
|
335
346
|
return [...root.querySelectorAll(MAIN_ASSISTANT)];
|
|
336
347
|
}
|
|
@@ -349,6 +360,7 @@ window.__ModuleLoader__.load({
|
|
|
349
360
|
view: conversation ?? document.body,
|
|
350
361
|
anchor,
|
|
351
362
|
key: anchor.dataset.chatAnchorKey,
|
|
363
|
+
turn: body.closest("[data-chat-turn]")?.dataset.chatTurn,
|
|
352
364
|
sessionId,
|
|
353
365
|
surface: "main",
|
|
354
366
|
streaming: body.hasAttribute("data-streaming") || body.querySelector("[data-streaming]") !== null
|
|
@@ -659,7 +671,8 @@ window.__ModuleLoader__.load({
|
|
|
659
671
|
const inbox = inboxFaceOf(binding);
|
|
660
672
|
const nodes = () => chat.getLegacy()?.nodes ?? [];
|
|
661
673
|
const maxSeq = Math.max(-1, ...nodes().map((node) => node.seq ?? -1));
|
|
662
|
-
const
|
|
674
|
+
const queuedBefore = queuedMessages(binding, inbox);
|
|
675
|
+
const queueIds = new Set(queuedBefore.map((message) => message.messageId ?? message.id));
|
|
663
676
|
const previousError = binding.session.getSnapshot().promptError;
|
|
664
677
|
const previousNoticeSeq = input.notices?.getSnapshot()?.seq ?? -1;
|
|
665
678
|
const off = [];
|
|
@@ -695,7 +708,10 @@ window.__ModuleLoader__.load({
|
|
|
695
708
|
};
|
|
696
709
|
const check = () => {
|
|
697
710
|
if (!submitted || settled) return;
|
|
698
|
-
if (nodes().some((node) =>
|
|
711
|
+
if (nodes().some((node) => {
|
|
712
|
+
const id = node.messageId ?? node.id;
|
|
713
|
+
return (node.kind === "user" || node.kind === "steering") && (node.seq ?? -1) > maxSeq && matches(node) && (id === void 0 ? !queuedBefore.some(matches) : !queueIds.has(id));
|
|
714
|
+
}) || queuedMessages(binding, inbox).some((message) => {
|
|
699
715
|
const id = message.messageId ?? message.id;
|
|
700
716
|
return id !== void 0 && !queueIds.has(id) && matches(message);
|
|
701
717
|
})) {
|
|
@@ -750,7 +766,7 @@ window.__ModuleLoader__.load({
|
|
|
750
766
|
let dockRegistered = false;
|
|
751
767
|
let report = {
|
|
752
768
|
versions: {
|
|
753
|
-
sidenote: "0.8.
|
|
769
|
+
sidenote: "0.8.5",
|
|
754
770
|
dsh: "unknown",
|
|
755
771
|
betterSidebar: null
|
|
756
772
|
},
|
|
@@ -950,6 +966,8 @@ window.__ModuleLoader__.load({
|
|
|
950
966
|
settingsDescription: "Choose the actions available when you select conversation text.",
|
|
951
967
|
hideNativeQuote: "Hide native quote",
|
|
952
968
|
hideNativeQuoteHint: "Hide the Quote action in main and side chats.",
|
|
969
|
+
showSideChatNote: "Add a note before asking in side chat",
|
|
970
|
+
showSideChatNoteHint: "Turn off to add selected text directly to side chat and write your question there.",
|
|
953
971
|
settingsSaving: "Saving…",
|
|
954
972
|
settingsLoading: "Loading preferences…",
|
|
955
973
|
settingsUnavailable: "Preferences are unavailable. Reload the page to reconnect.",
|
|
@@ -1125,6 +1143,8 @@ window.__ModuleLoader__.load({
|
|
|
1125
1143
|
settingsDescription: "调整划选对话文字时显示的操作。",
|
|
1126
1144
|
hideNativeQuote: "隐藏原生引用",
|
|
1127
1145
|
hideNativeQuoteHint: "在主对话和侧边聊天中隐藏“引用”按钮。",
|
|
1146
|
+
showSideChatNote: "侧边提问前填写注解",
|
|
1147
|
+
showSideChatNoteHint: "关闭后,划选内容直接添加到侧边聊天,可在侧聊输入框中继续提问。",
|
|
1128
1148
|
settingsSaving: "正在保存…",
|
|
1129
1149
|
settingsLoading: "正在加载偏好设置…",
|
|
1130
1150
|
settingsUnavailable: "暂时无法读取设置,请刷新页面重新连接。",
|
|
@@ -1405,12 +1425,12 @@ window.__ModuleLoader__.load({
|
|
|
1405
1425
|
}
|
|
1406
1426
|
var diagnostics_module_css_default = {
|
|
1407
1427
|
"trigger": "tGe0LW_trigger",
|
|
1408
|
-
"header": "tGe0LW_header",
|
|
1409
1428
|
"list": "tGe0LW_list",
|
|
1410
|
-
"
|
|
1429
|
+
"header": "tGe0LW_header",
|
|
1411
1430
|
"panel": "tGe0LW_panel",
|
|
1412
|
-
"
|
|
1413
|
-
"
|
|
1431
|
+
"actions": "tGe0LW_actions",
|
|
1432
|
+
"description": "tGe0LW_description",
|
|
1433
|
+
"versions": "tGe0LW_versions"
|
|
1414
1434
|
};
|
|
1415
1435
|
//#endregion
|
|
1416
1436
|
//#region src/client/diagnostics/index.tsx
|
|
@@ -1718,9 +1738,13 @@ window.__ModuleLoader__.load({
|
|
|
1718
1738
|
if (typeof a.text !== "string" || typeof a.anchorText !== "string") return null;
|
|
1719
1739
|
if (typeof a.occurrence !== "number") return null;
|
|
1720
1740
|
if (a.state !== "active" && a.state !== "sent") return null;
|
|
1741
|
+
if (a.anchors !== void 0) {
|
|
1742
|
+
if (!Array.isArray(a.anchors) || a.anchors.length < 2) return null;
|
|
1743
|
+
for (const anchor of a.anchors) if (!anchor || typeof anchor.anchorKey !== "string" || !anchor.anchorKey || typeof anchor.anchorText !== "string" || !anchor.anchorText.trim() || !Number.isSafeInteger(anchor.occurrence) || anchor.occurrence < 0) return null;
|
|
1744
|
+
}
|
|
1721
1745
|
return {
|
|
1722
1746
|
id: a.id,
|
|
1723
|
-
number: a.number,
|
|
1747
|
+
number: a.state === "sent" && typeof a.localNumber === "number" ? a.localNumber : a.number,
|
|
1724
1748
|
sessionId: a.sessionId,
|
|
1725
1749
|
sourceSessionId: typeof a.sourceSessionId === "string" && a.sourceSessionId !== "" ? a.sourceSessionId : void 0,
|
|
1726
1750
|
sourceSurface: a.sourceSurface === "main" || a.sourceSurface === "side" ? a.sourceSurface : void 0,
|
|
@@ -1728,6 +1752,7 @@ window.__ModuleLoader__.load({
|
|
|
1728
1752
|
text: a.text,
|
|
1729
1753
|
anchorText: a.anchorText,
|
|
1730
1754
|
occurrence: a.occurrence,
|
|
1755
|
+
...a.anchors ? { anchors: a.anchors } : {},
|
|
1731
1756
|
note: typeof a.note === "string" ? a.note : "",
|
|
1732
1757
|
state: a.state,
|
|
1733
1758
|
createdAt: typeof a.createdAt === "number" ? a.createdAt : 0
|
|
@@ -1737,11 +1762,24 @@ window.__ModuleLoader__.load({
|
|
|
1737
1762
|
let annotations = [];
|
|
1738
1763
|
let nextId = 1;
|
|
1739
1764
|
let version = 0;
|
|
1740
|
-
/** Per-session next display number. */
|
|
1741
|
-
const counters = /* @__PURE__ */ new Map();
|
|
1742
1765
|
const listeners = /* @__PURE__ */ new Set();
|
|
1743
1766
|
const submissions = /* @__PURE__ */ new Map();
|
|
1744
1767
|
const idleSubmission = { pending: false };
|
|
1768
|
+
const countActiveOf = (sessionId) => annotations.reduce((n, a) => n + (a.sessionId === sessionId && a.state === "active" ? 1 : 0), 0);
|
|
1769
|
+
/** 只重排目标会话的待发送编号,已发送编号保持冻结。 */
|
|
1770
|
+
const renumberActive = (sessionId) => {
|
|
1771
|
+
const numbers = /* @__PURE__ */ new Map();
|
|
1772
|
+
annotations.filter((a) => a.sessionId === sessionId && a.state === "active").sort((left, right) => left.id - right.id).forEach((annotation, index) => {
|
|
1773
|
+
numbers.set(annotation.id, index + 1);
|
|
1774
|
+
});
|
|
1775
|
+
annotations = annotations.map((a) => {
|
|
1776
|
+
const number = numbers.get(a.id);
|
|
1777
|
+
return number === void 0 || a.number === number ? a : {
|
|
1778
|
+
...a,
|
|
1779
|
+
number
|
|
1780
|
+
};
|
|
1781
|
+
});
|
|
1782
|
+
};
|
|
1745
1783
|
let store = storage ?? null;
|
|
1746
1784
|
if (storage === void 0) try {
|
|
1747
1785
|
store = globalThis.localStorage ?? null;
|
|
@@ -1772,7 +1810,6 @@ window.__ModuleLoader__.load({
|
|
|
1772
1810
|
const revived = reviveStored(item);
|
|
1773
1811
|
if (revived === null) continue;
|
|
1774
1812
|
annotations.push(revived);
|
|
1775
|
-
counters.set(revived.sessionId, Math.max(counters.get(revived.sessionId) ?? 0, revived.number));
|
|
1776
1813
|
nextId = Math.max(nextId, revived.id + 1);
|
|
1777
1814
|
}
|
|
1778
1815
|
}
|
|
@@ -1805,6 +1842,7 @@ window.__ModuleLoader__.load({
|
|
|
1805
1842
|
version += 1;
|
|
1806
1843
|
for (const fn of [...listeners]) fn();
|
|
1807
1844
|
};
|
|
1845
|
+
for (const sessionId of new Set(annotations.map((a) => a.sessionId))) renumberActive(sessionId);
|
|
1808
1846
|
const replace = (id, patch) => {
|
|
1809
1847
|
const target = annotations.find((a) => a.id === id);
|
|
1810
1848
|
annotations = annotations.map((a) => a.id === id ? {
|
|
@@ -1829,8 +1867,7 @@ window.__ModuleLoader__.load({
|
|
|
1829
1867
|
};
|
|
1830
1868
|
},
|
|
1831
1869
|
add(draft) {
|
|
1832
|
-
const number = (
|
|
1833
|
-
counters.set(draft.sessionId, number);
|
|
1870
|
+
const number = countActiveOf(draft.sessionId) + 1;
|
|
1834
1871
|
const annotation = {
|
|
1835
1872
|
id: nextId,
|
|
1836
1873
|
number,
|
|
@@ -1841,6 +1878,7 @@ window.__ModuleLoader__.load({
|
|
|
1841
1878
|
text: draft.text,
|
|
1842
1879
|
anchorText: draft.anchorText,
|
|
1843
1880
|
occurrence: draft.occurrence,
|
|
1881
|
+
...draft.anchors ? { anchors: draft.anchors } : {},
|
|
1844
1882
|
note: draft.note,
|
|
1845
1883
|
state: "active",
|
|
1846
1884
|
createdAt: now()
|
|
@@ -1859,10 +1897,11 @@ window.__ModuleLoader__.load({
|
|
|
1859
1897
|
const target = annotations.find((a) => a.id === id);
|
|
1860
1898
|
if (target === void 0) return;
|
|
1861
1899
|
annotations = annotations.filter((a) => a.id !== id);
|
|
1900
|
+
renumberActive(target.sessionId);
|
|
1862
1901
|
persistTouched([target.sessionId]);
|
|
1863
1902
|
notify();
|
|
1864
1903
|
},
|
|
1865
|
-
markSent(ids) {
|
|
1904
|
+
markSent(ids, frozenNumbers) {
|
|
1866
1905
|
if (ids.length === 0) return;
|
|
1867
1906
|
const idSet = new Set(ids);
|
|
1868
1907
|
if (!annotations.some((a) => idSet.has(a.id) && a.state === "active")) return;
|
|
@@ -1872,9 +1911,11 @@ window.__ModuleLoader__.load({
|
|
|
1872
1911
|
touched.add(a.sessionId);
|
|
1873
1912
|
return {
|
|
1874
1913
|
...a,
|
|
1875
|
-
state: "sent"
|
|
1914
|
+
state: "sent",
|
|
1915
|
+
number: frozenNumbers?.get(a.id) ?? a.number
|
|
1876
1916
|
};
|
|
1877
1917
|
});
|
|
1918
|
+
for (const sessionId of touched) renumberActive(sessionId);
|
|
1878
1919
|
persistTouched([...touched]);
|
|
1879
1920
|
notify();
|
|
1880
1921
|
},
|
|
@@ -1888,7 +1929,7 @@ window.__ModuleLoader__.load({
|
|
|
1888
1929
|
return annotations.filter((a) => a.sessionId === sessionId && a.state === "active");
|
|
1889
1930
|
},
|
|
1890
1931
|
countActive(sessionId) {
|
|
1891
|
-
return
|
|
1932
|
+
return countActiveOf(sessionId);
|
|
1892
1933
|
},
|
|
1893
1934
|
sessions() {
|
|
1894
1935
|
return [...new Set(annotations.map((a) => a.sessionId))];
|
|
@@ -2238,7 +2279,7 @@ window.__ModuleLoader__.load({
|
|
|
2238
2279
|
}
|
|
2239
2280
|
/** 协议头识别(zh/en 都认):整行匹配。 */
|
|
2240
2281
|
const PROTOCOL_HEADER_RE = /^(?:我批注了以下 (\d+) 处内容:|I annotated (\d+) passage\(s\) of the conversation above:)$/;
|
|
2241
|
-
const ANNOTATION_RE = /<annotation id="(\d+)"
|
|
2282
|
+
const ANNOTATION_RE = /<annotation id="(\d+)"(?: local="(\d+)")?(?: scope="[^"]*")?>\s*<quote>([\s\S]*?)<\/quote>\s*(?:<note>([\s\S]*?)<\/note>\s*)?<\/annotation>/y;
|
|
2242
2283
|
const REFLOW_RE = /<reflow\s+source="([^"]*)"(?:\s+reason="([^"]*)")?\s*>([\s\S]*?)<\/reflow>/y;
|
|
2243
2284
|
/**
|
|
2244
2285
|
* 气泡 tooltip / 面板留痕 chip 的展示拍平:剥掉 <问>/<答> 协议标签只留内容行
|
|
@@ -2276,14 +2317,16 @@ window.__ModuleLoader__.load({
|
|
|
2276
2317
|
const headerMatch = /^([^\n]*)\n/.exec(rest);
|
|
2277
2318
|
if (headerMatch !== null && PROTOCOL_HEADER_RE.test(headerMatch[1] ?? "")) {
|
|
2278
2319
|
let cursor = pos + headerMatch[0].length;
|
|
2320
|
+
const legacyGuidance = /^Annotation ids stay stable within (?:their session scope|this conversation)\.[^\n]*\n/.exec(text.slice(cursor));
|
|
2321
|
+
if (legacyGuidance) cursor += legacyGuidance[0].length;
|
|
2279
2322
|
for (;;) {
|
|
2280
2323
|
ANNOTATION_RE.lastIndex = cursor;
|
|
2281
2324
|
const m = ANNOTATION_RE.exec(text);
|
|
2282
2325
|
if (m === null) break;
|
|
2283
2326
|
annotations.push({
|
|
2284
|
-
id: Number(m[1]),
|
|
2285
|
-
quote: m[
|
|
2286
|
-
note: (m[
|
|
2327
|
+
id: Number(m[2] ?? m[1]),
|
|
2328
|
+
quote: m[3] ?? "",
|
|
2329
|
+
note: (m[4] ?? "").trim()
|
|
2287
2330
|
});
|
|
2288
2331
|
cursor = skipBlank(text, ANNOTATION_RE.lastIndex);
|
|
2289
2332
|
}
|
|
@@ -2309,33 +2352,33 @@ window.__ModuleLoader__.load({
|
|
|
2309
2352
|
document.head.appendChild(tag);
|
|
2310
2353
|
}
|
|
2311
2354
|
var annotations_module_css_default = {
|
|
2312
|
-
"
|
|
2313
|
-
"
|
|
2314
|
-
"
|
|
2315
|
-
"sentChips": "SVnebq_sentChips",
|
|
2316
|
-
"contextSource": "SVnebq_contextSource",
|
|
2317
|
-
"sentChevronOpen": "SVnebq_sentChevronOpen",
|
|
2318
|
-
"contextPanel": "SVnebq_contextPanel",
|
|
2319
|
-
"contextContent": "SVnebq_contextContent",
|
|
2355
|
+
"contextNumber": "SVnebq_contextNumber",
|
|
2356
|
+
"contextLabel": "SVnebq_contextLabel",
|
|
2357
|
+
"contextEditor": "SVnebq_contextEditor",
|
|
2320
2358
|
"sentChipGroup": "SVnebq_sentChipGroup",
|
|
2359
|
+
"sentChip": "SVnebq_sentChip",
|
|
2321
2360
|
"chipMain": "SVnebq_chipMain",
|
|
2322
|
-
"
|
|
2323
|
-
"
|
|
2324
|
-
"contextAction": "SVnebq_contextAction",
|
|
2325
|
-
"contextNumber": "SVnebq_contextNumber",
|
|
2361
|
+
"contextText": "SVnebq_contextText",
|
|
2362
|
+
"chipClearAll": "SVnebq_chipClearAll",
|
|
2326
2363
|
"storageNotice": "SVnebq_storageNotice",
|
|
2327
|
-
"
|
|
2364
|
+
"contextContent": "SVnebq_contextContent",
|
|
2365
|
+
"sentChevron": "SVnebq_sentChevron",
|
|
2366
|
+
"sentChevronOpen": "SVnebq_sentChevronOpen",
|
|
2367
|
+
"userContextHost": "SVnebq_userContextHost",
|
|
2328
2368
|
"sentPreview": "SVnebq_sentPreview",
|
|
2329
|
-
"
|
|
2369
|
+
"contextActions": "SVnebq_contextActions",
|
|
2330
2370
|
"contextFooter": "SVnebq_contextFooter",
|
|
2331
|
-
"
|
|
2371
|
+
"contextAppear": "SVnebq_contextAppear",
|
|
2332
2372
|
"contextList": "SVnebq_contextList",
|
|
2333
|
-
"
|
|
2334
|
-
"chipDismissShade": "SVnebq_chipDismissShade",
|
|
2373
|
+
"contextPanel": "SVnebq_contextPanel",
|
|
2335
2374
|
"chip": "SVnebq_chip",
|
|
2336
|
-
"
|
|
2337
|
-
"
|
|
2338
|
-
"
|
|
2375
|
+
"contextAction": "SVnebq_contextAction",
|
|
2376
|
+
"sentChips": "SVnebq_sentChips",
|
|
2377
|
+
"chipWrap": "SVnebq_chipWrap",
|
|
2378
|
+
"chipDismiss": "SVnebq_chipDismiss",
|
|
2379
|
+
"contextSource": "SVnebq_contextSource",
|
|
2380
|
+
"contextItem": "SVnebq_contextItem",
|
|
2381
|
+
"chipDismissShade": "SVnebq_chipDismissShade"
|
|
2339
2382
|
};
|
|
2340
2383
|
//#endregion
|
|
2341
2384
|
//#region src/client/annotations/NativeUserContext.tsx
|
|
@@ -2809,38 +2852,38 @@ window.__ModuleLoader__.load({
|
|
|
2809
2852
|
document.head.appendChild(tag);
|
|
2810
2853
|
}
|
|
2811
2854
|
var sidechat_module_css_default = {
|
|
2855
|
+
"root": "_5KEEsG_root",
|
|
2812
2856
|
"progress": "_5KEEsG_progress",
|
|
2857
|
+
"progressProcess": "_5KEEsG_progressProcess",
|
|
2858
|
+
"nativeToolbarActions": "_5KEEsG_nativeToolbarActions",
|
|
2859
|
+
"nativeToolbar": "_5KEEsG_nativeToolbar",
|
|
2860
|
+
"stateDetail": "_5KEEsG_stateDetail",
|
|
2861
|
+
"headerSide": "_5KEEsG_headerSide",
|
|
2862
|
+
"nativeConversation": "_5KEEsG_nativeConversation",
|
|
2863
|
+
"emptyText": "_5KEEsG_emptyText",
|
|
2864
|
+
"contextChevron": "_5KEEsG_contextChevron",
|
|
2865
|
+
"contextHint": "_5KEEsG_contextHint",
|
|
2866
|
+
"progressEntry": "_5KEEsG_progressEntry",
|
|
2867
|
+
"progressPreview": "_5KEEsG_progressPreview",
|
|
2868
|
+
"nativeAction": "_5KEEsG_nativeAction",
|
|
2869
|
+
"reflowAction": "_5KEEsG_reflowAction",
|
|
2870
|
+
"chatView": "_5KEEsG_chatView",
|
|
2813
2871
|
"contextColumn": "_5KEEsG_contextColumn",
|
|
2814
|
-
"emptyTitle": "_5KEEsG_emptyTitle",
|
|
2815
|
-
"contextUserRow": "_5KEEsG_contextUserRow",
|
|
2816
|
-
"progressDetail": "_5KEEsG_progressDetail",
|
|
2817
2872
|
"contextChevronOpen": "_5KEEsG_contextChevronOpen",
|
|
2873
|
+
"mainContext": "_5KEEsG_mainContext",
|
|
2874
|
+
"emptyTitle": "_5KEEsG_emptyTitle",
|
|
2818
2875
|
"errorRow": "_5KEEsG_errorRow",
|
|
2819
|
-
"
|
|
2820
|
-
"
|
|
2821
|
-
"
|
|
2822
|
-
"
|
|
2876
|
+
"progressDetail": "_5KEEsG_progressDetail",
|
|
2877
|
+
"historyToggle": "_5KEEsG_historyToggle",
|
|
2878
|
+
"nativeHost": "_5KEEsG_nativeHost",
|
|
2879
|
+
"progressEntries": "_5KEEsG_progressEntries",
|
|
2823
2880
|
"progressLatest": "_5KEEsG_progressLatest",
|
|
2824
|
-
"
|
|
2881
|
+
"progressContent": "_5KEEsG_progressContent",
|
|
2882
|
+
"stateScreen": "_5KEEsG_stateScreen",
|
|
2825
2883
|
"contextImage": "_5KEEsG_contextImage",
|
|
2826
|
-
"progressEntries": "_5KEEsG_progressEntries",
|
|
2827
|
-
"nativeConversation": "_5KEEsG_nativeConversation",
|
|
2828
|
-
"nativeHost": "_5KEEsG_nativeHost",
|
|
2829
|
-
"chatView": "_5KEEsG_chatView",
|
|
2830
2884
|
"contextBubble": "_5KEEsG_contextBubble",
|
|
2831
|
-
"
|
|
2832
|
-
"
|
|
2833
|
-
"mainContext": "_5KEEsG_mainContext",
|
|
2834
|
-
"stateScreen": "_5KEEsG_stateScreen",
|
|
2835
|
-
"stateDetail": "_5KEEsG_stateDetail",
|
|
2836
|
-
"progressPreview": "_5KEEsG_progressPreview",
|
|
2837
|
-
"nativeToolbar": "_5KEEsG_nativeToolbar",
|
|
2838
|
-
"contextChevron": "_5KEEsG_contextChevron",
|
|
2839
|
-
"contextHint": "_5KEEsG_contextHint",
|
|
2840
|
-
"progressProcess": "_5KEEsG_progressProcess",
|
|
2841
|
-
"headerSide": "_5KEEsG_headerSide",
|
|
2842
|
-
"progressEntry": "_5KEEsG_progressEntry",
|
|
2843
|
-
"emptyIcon": "_5KEEsG_emptyIcon"
|
|
2885
|
+
"emptyIcon": "_5KEEsG_emptyIcon",
|
|
2886
|
+
"contextUserRow": "_5KEEsG_contextUserRow"
|
|
2844
2887
|
};
|
|
2845
2888
|
//#endregion
|
|
2846
2889
|
//#region src/client/sidechat/ContextProgress.tsx
|
|
@@ -2914,6 +2957,7 @@ window.__ModuleLoader__.load({
|
|
|
2914
2957
|
"data-sidenote-quote-body": entry.messageKey ? "" : void 0,
|
|
2915
2958
|
"data-sidenote-message-role": entry.messageKey ? "assistant" : void 0,
|
|
2916
2959
|
"data-sidenote-message-key": entry.messageKey,
|
|
2960
|
+
"data-sidenote-turn": entry.turn === void 0 ? void 0 : `history:${entry.turn}`,
|
|
2917
2961
|
"data-sidenote-streaming": live && unfinished ? "true" : "false",
|
|
2918
2962
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.MarkdownText, {
|
|
2919
2963
|
text: entry.text,
|
|
@@ -3492,7 +3536,10 @@ ${body}
|
|
|
3492
3536
|
return {
|
|
3493
3537
|
...entry,
|
|
3494
3538
|
key,
|
|
3495
|
-
...node.kind === "assistant" && entry.kind === "reply" ? {
|
|
3539
|
+
...node.kind === "assistant" && entry.kind === "reply" ? {
|
|
3540
|
+
messageKey: `a:${node.seq}`,
|
|
3541
|
+
turn: node.turn
|
|
3542
|
+
} : {},
|
|
3496
3543
|
...node.kind !== "user" && node.kind !== "steering" && images.length && index === entries.length - 1 ? { images } : {}
|
|
3497
3544
|
};
|
|
3498
3545
|
});
|
|
@@ -6218,7 +6265,7 @@ ${body}
|
|
|
6218
6265
|
/** Explicit side bodies are the sole exception to the legacy sidebar exclusion. */
|
|
6219
6266
|
function quoteSourceOf(node, currentSessionId) {
|
|
6220
6267
|
const element = elementOf(node);
|
|
6221
|
-
if (element
|
|
6268
|
+
if (!element || element.closest(`button, [role="button"], input, textarea, select, [contenteditable="true"], [data-code-block-banner], [data-variant="think"], [data-chat-group-part="reasoning"], [data-sidenote-no-quote], [data-variant="think"], [data-chat-group-part="reasoning"], [data-chat-flow-kind="tool-call"], [data-chat-flow-kind="tool-result"], [data-chat-flow-kind="turn-process"], [data-context-kind="thinking"], [data-context-kind="tool"]`) !== null) return null;
|
|
6222
6269
|
const body = element?.closest("[data-sidenote-quote-body]");
|
|
6223
6270
|
if (body !== void 0 && body !== null) {
|
|
6224
6271
|
const anchor = body.closest("[data-sidenote-message-key][data-sidenote-message-role=\"assistant\"]");
|
|
@@ -6232,6 +6279,7 @@ ${body}
|
|
|
6232
6279
|
sessionId,
|
|
6233
6280
|
surface: "side",
|
|
6234
6281
|
key: anchor.dataset.sidenoteMessageKey,
|
|
6282
|
+
turn: body.dataset.sidenoteTurn ?? body.closest("[data-chat-turn]")?.dataset.chatTurn,
|
|
6235
6283
|
streaming: body.dataset.sidenoteStreaming === "true"
|
|
6236
6284
|
};
|
|
6237
6285
|
}
|
|
@@ -6249,19 +6297,57 @@ ${body}
|
|
|
6249
6297
|
return source.key;
|
|
6250
6298
|
}
|
|
6251
6299
|
function sourceBodies(sessionId, surface, anchorKey, currentSessionId) {
|
|
6252
|
-
|
|
6253
|
-
return [...document.querySelectorAll("[data-sidenote-quote-body]"), ...nativeAssistantBodies()].filter((body) => {
|
|
6300
|
+
return (surface === "main" ? mainAnchorBodies(sessionId, anchorKey, currentSessionId) : [...document.querySelectorAll("[data-sidenote-quote-body]"), ...nativeAssistantBodies().filter((body) => !body.querySelector("[data-sidenote-quote-body]"))]).filter((body) => {
|
|
6254
6301
|
const source = quoteSourceOf(body, currentSessionId);
|
|
6255
|
-
return source?.surface ===
|
|
6302
|
+
return source?.surface === surface && source.sessionId === sessionId && sourceKey(source) === anchorKey;
|
|
6256
6303
|
});
|
|
6257
6304
|
}
|
|
6305
|
+
/** Admit the complete visible selection, never silently drop process content. */
|
|
6306
|
+
function quoteSourcesOfRange(range, currentSessionId) {
|
|
6307
|
+
const root = range.commonAncestorContainer;
|
|
6308
|
+
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
|
|
6309
|
+
const sources = [];
|
|
6310
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6311
|
+
for (let node = root.nodeType === Node.TEXT_NODE ? root : walker.nextNode(); node; node = walker.nextNode()) {
|
|
6312
|
+
if (!range.intersectsNode(node) || !quoteNodeVisible(node)) continue;
|
|
6313
|
+
const start = node === range.startContainer ? range.startOffset : 0;
|
|
6314
|
+
const end = node === range.endContainer ? range.endOffset : node.textContent.length;
|
|
6315
|
+
if (node.textContent.slice(start, end).trim() === "") continue;
|
|
6316
|
+
const element = elementOf(node);
|
|
6317
|
+
if (element.closest("[data-variant=\"think\"], [data-chat-group-part=\"reasoning\"], [data-chat-flow-kind=\"tool-call\"], [data-chat-flow-kind=\"tool-result\"], [data-chat-flow-kind=\"turn-process\"], [data-context-kind=\"thinking\"], [data-context-kind=\"tool\"]")) return null;
|
|
6318
|
+
if (element.closest("button, [role=\"button\"], input, textarea, select, [contenteditable=\"true\"], [data-code-block-banner], [data-variant=\"think\"], [data-chat-group-part=\"reasoning\"], [data-sidenote-no-quote]")) {
|
|
6319
|
+
const body = element.closest(`[data-sidenote-quote-body], ${MAIN_ASSISTANT}`);
|
|
6320
|
+
if (body && quoteSourceOf(body, currentSessionId)) continue;
|
|
6321
|
+
return null;
|
|
6322
|
+
}
|
|
6323
|
+
const source = quoteSourceOf(node, currentSessionId);
|
|
6324
|
+
if (!source || source.streaming) return null;
|
|
6325
|
+
const first = sources[0];
|
|
6326
|
+
if (first && (source.view !== first.view || source.sessionId !== first.sessionId || source.surface !== first.surface)) return null;
|
|
6327
|
+
if (seen.has(source.body)) continue;
|
|
6328
|
+
if (first && (!first.turn || source.turn !== first.turn || !first.key || !source.key)) return null;
|
|
6329
|
+
sources.push(source);
|
|
6330
|
+
seen.add(source.body);
|
|
6331
|
+
}
|
|
6332
|
+
return sources.length ? sources : null;
|
|
6333
|
+
}
|
|
6334
|
+
/** Trim each stored fragment to the actual selected text, excluding surrounding UI. */
|
|
6335
|
+
function quoteRangeOf(body, selection) {
|
|
6336
|
+
const nodes = quoteTextNodes(body).filter((node) => selection.intersectsNode(node) && (node !== selection.startContainer || selection.startOffset < node.length) && (node !== selection.endContainer || selection.endOffset > 0));
|
|
6337
|
+
const first = nodes[0], last = nodes.at(-1);
|
|
6338
|
+
if (!first || !last) return null;
|
|
6339
|
+
const range = document.createRange();
|
|
6340
|
+
range.setStart(first, first === selection.startContainer ? selection.startOffset : 0);
|
|
6341
|
+
range.setEnd(last, last === selection.endContainer ? selection.endOffset : last.length);
|
|
6342
|
+
return range;
|
|
6343
|
+
}
|
|
6258
6344
|
/** The same text-node projection is used at capture and when rebuilding anchors.
|
|
6259
6345
|
* Browser selections contain block newlines; anchor offsets deliberately do not. */
|
|
6260
6346
|
function quoteTextNodes(body) {
|
|
6261
6347
|
const walker = document.createTreeWalker(body, NodeFilter.SHOW_TEXT);
|
|
6262
6348
|
const nodes = [];
|
|
6263
6349
|
for (let node = walker.nextNode(); node; node = walker.nextNode()) {
|
|
6264
|
-
if (node.parentElement?.closest(
|
|
6350
|
+
if (node.parentElement?.closest(`button, [role="button"], input, textarea, select, [contenteditable="true"], [data-code-block-banner], [data-variant="think"], [data-chat-group-part="reasoning"], [data-sidenote-no-quote], [data-variant="think"], [data-chat-group-part="reasoning"], [data-chat-flow-kind="tool-call"], [data-chat-flow-kind="tool-result"], [data-chat-flow-kind="turn-process"], [data-context-kind="thinking"], [data-context-kind="tool"]`) !== null || !quoteNodeVisible(node)) continue;
|
|
6265
6351
|
if (node.parentElement !== null && getComputedStyle(node.parentElement).userSelect === "none") continue;
|
|
6266
6352
|
nodes.push(node);
|
|
6267
6353
|
}
|
|
@@ -6278,7 +6364,7 @@ ${body}
|
|
|
6278
6364
|
function selectedQuoteText(range, browserText, anchorText) {
|
|
6279
6365
|
if (browserText.replace(/\s/g, "") === anchorText.replace(/\s/g, "")) return browserText;
|
|
6280
6366
|
const fragment = range.cloneContents();
|
|
6281
|
-
for (const element of fragment.querySelectorAll(NON_QUOTE)) element.remove();
|
|
6367
|
+
for (const element of fragment.querySelectorAll(`${NON_QUOTE}, ${PROCESS_UI}, [hidden], [data-turn-process-hidden], [data-turn-process-inline]`)) element.remove();
|
|
6282
6368
|
const textOf = (node) => {
|
|
6283
6369
|
if (node.nodeType === Node.TEXT_NODE) return node.textContent ?? "";
|
|
6284
6370
|
if (node instanceof Element && node.tagName === "BR") return "\n";
|
|
@@ -6302,11 +6388,11 @@ ${body}
|
|
|
6302
6388
|
* toolbar through a small external-store controller. Mirrors the
|
|
6303
6389
|
* production-proven dsh-sidebar-qa contract, narrowed to assistant messages:
|
|
6304
6390
|
*
|
|
6305
|
-
* -
|
|
6306
|
-
*
|
|
6391
|
+
* - completed reply bodies in one view and Turn may be selected together;
|
|
6392
|
+
* - selected visible process/tool UI invalidates the whole selection;
|
|
6307
6393
|
* - `[data-streaming]` messages (still streaming) are excluded;
|
|
6308
6394
|
* - explicit side assistant bodies are admitted; other sidebar/plugin UI is
|
|
6309
|
-
* excluded;
|
|
6395
|
+
* excluded; every selected reply belongs to the same source view;
|
|
6310
6396
|
* - quote text is kept complete, while anchor offsets use one DOM projection.
|
|
6311
6397
|
*
|
|
6312
6398
|
* These are DSH-internal DOM attributes rather than a public contract — an
|
|
@@ -6338,24 +6424,38 @@ ${body}
|
|
|
6338
6424
|
const sel = window.getSelection();
|
|
6339
6425
|
if (sel === null || sel.isCollapsed || sel.rangeCount === 0) return null;
|
|
6340
6426
|
const range = sel.getRangeAt(0);
|
|
6341
|
-
const
|
|
6342
|
-
|
|
6343
|
-
|
|
6344
|
-
|
|
6427
|
+
const sources = quoteSourcesOfRange(range, currentSessionId);
|
|
6428
|
+
if (!sources) return null;
|
|
6429
|
+
const ranges = sources.map((source) => quoteRangeOf(source.body, range));
|
|
6430
|
+
if (ranges.some((fragment) => fragment === null)) return null;
|
|
6431
|
+
const fragments = ranges;
|
|
6432
|
+
const anchors = sources.map((source, index) => {
|
|
6433
|
+
const anchorText = projectedRangeText(source.body, fragments[index]);
|
|
6434
|
+
return {
|
|
6435
|
+
anchorKey: sourceKey(source),
|
|
6436
|
+
anchorText,
|
|
6437
|
+
occurrence: occurrenceOf(source.body, fragments[index], anchorText)
|
|
6438
|
+
};
|
|
6439
|
+
});
|
|
6440
|
+
const source = sources[0];
|
|
6441
|
+
const anchorText = anchors.map((anchor) => anchor.anchorText).join("");
|
|
6345
6442
|
if (anchorText.trim() === "") return null;
|
|
6346
|
-
const
|
|
6443
|
+
const browserText = sel.toString();
|
|
6444
|
+
const text = browserText.replace(/\s/g, "") === anchorText.replace(/\s/g, "") ? browserText : fragments.map((fragment, index) => selectedQuoteText(fragment, fragment.toString(), anchors[index].anchorText)).join("\n\n");
|
|
6347
6445
|
const rect = range.getBoundingClientRect();
|
|
6348
6446
|
return {
|
|
6349
6447
|
text,
|
|
6350
6448
|
anchorText,
|
|
6351
6449
|
anchorKey: sourceKey(source),
|
|
6352
|
-
occurrence:
|
|
6450
|
+
occurrence: anchors[0].occurrence,
|
|
6451
|
+
...anchors.length > 1 ? { anchors } : {},
|
|
6353
6452
|
rect: {
|
|
6354
6453
|
left: rect.left,
|
|
6355
6454
|
top: rect.top,
|
|
6356
6455
|
width: rect.width
|
|
6357
6456
|
},
|
|
6358
6457
|
range: range.cloneRange(),
|
|
6458
|
+
ranges: fragments,
|
|
6359
6459
|
sessionId: source.sessionId,
|
|
6360
6460
|
source
|
|
6361
6461
|
};
|
|
@@ -6379,7 +6479,7 @@ ${body}
|
|
|
6379
6479
|
} catch {
|
|
6380
6480
|
next = null;
|
|
6381
6481
|
}
|
|
6382
|
-
if (!(selection === null !== (next === null) || selection !== null && next !== null && (selection.anchorText !== next.anchorText || selection.anchorKey !== next.anchorKey || selection.sessionId !== next.sessionId || selection.source.view !== next.source.view || selection.source.surface !== next.source.surface || selection.rect.top !== next.rect.top || selection.rect.left !== next.rect.left || selection.rect.width !== next.rect.width))) return;
|
|
6482
|
+
if (!(selection === null !== (next === null) || selection !== null && next !== null && (selection.anchorText !== next.anchorText || selection.anchorKey !== next.anchorKey || selection.occurrence !== next.occurrence || JSON.stringify(selection.anchors) !== JSON.stringify(next.anchors) || selection.sessionId !== next.sessionId || selection.source.view !== next.source.view || selection.source.surface !== next.source.surface || selection.rect.top !== next.rect.top || selection.rect.left !== next.rect.left || selection.rect.width !== next.rect.width))) return;
|
|
6383
6483
|
selection = next;
|
|
6384
6484
|
notify();
|
|
6385
6485
|
};
|
|
@@ -6458,31 +6558,41 @@ ${body}
|
|
|
6458
6558
|
range.setEnd(endNode, endOffset);
|
|
6459
6559
|
return range;
|
|
6460
6560
|
}
|
|
6461
|
-
function
|
|
6561
|
+
function resolveRanges(annotation, cache, currentSessionId = "") {
|
|
6462
6562
|
try {
|
|
6463
6563
|
const sessionId = annotation.sourceSessionId ?? annotation.sessionId;
|
|
6464
6564
|
const surface = annotation.sourceSurface ?? "main";
|
|
6465
|
-
const
|
|
6565
|
+
const anchors = annotation.anchors ?? [annotation];
|
|
6566
|
+
const valid = (ranges, view) => ranges.length === anchors.length && ranges.every((range, index) => {
|
|
6466
6567
|
if (!range.startContainer.isConnected || !range.endContainer.isConnected) return false;
|
|
6467
|
-
const
|
|
6468
|
-
const
|
|
6469
|
-
|
|
6470
|
-
|
|
6568
|
+
const sources = quoteSourcesOfRange(range, currentSessionId);
|
|
6569
|
+
const source = sources?.[0];
|
|
6570
|
+
const anchor = anchors[index];
|
|
6571
|
+
return sources?.length === 1 && source !== void 0 && source.view === view && source.sessionId === sessionId && source.surface === surface && sourceKey(source) === anchor.anchorKey && projectedRangeText(source.body, range) === anchor.anchorText;
|
|
6572
|
+
});
|
|
6471
6573
|
const cached = cache.get(annotation.id);
|
|
6472
|
-
if (cached !== void 0 && valid(cached.
|
|
6574
|
+
if (cached !== void 0 && valid(cached.ranges, cached.view)) return cached.ranges;
|
|
6473
6575
|
cache.delete(annotation.id);
|
|
6474
|
-
|
|
6475
|
-
|
|
6476
|
-
|
|
6477
|
-
|
|
6478
|
-
|
|
6479
|
-
|
|
6480
|
-
|
|
6481
|
-
|
|
6482
|
-
|
|
6483
|
-
view
|
|
6576
|
+
const ranges = [];
|
|
6577
|
+
let view;
|
|
6578
|
+
for (const anchor of anchors) {
|
|
6579
|
+
if (!anchor.anchorKey || !anchor.anchorText) return null;
|
|
6580
|
+
const bodies = sourceBodies(sessionId, surface, anchor.anchorKey, currentSessionId).filter((body) => body.getClientRects().length > 0);
|
|
6581
|
+
if (bodies.length !== 1) return null;
|
|
6582
|
+
const body = bodies[0];
|
|
6583
|
+
const source = quoteSourceOf(body, currentSessionId);
|
|
6584
|
+
if (!source || view && source.view !== view) return null;
|
|
6585
|
+
view = source.view;
|
|
6586
|
+
const range = rangeOfOccurrence(body, anchor.anchorText, anchor.occurrence);
|
|
6587
|
+
if (!range) return null;
|
|
6588
|
+
ranges.push(range);
|
|
6589
|
+
}
|
|
6590
|
+
if (!view || !valid(ranges, view)) return null;
|
|
6591
|
+
cache.set(annotation.id, {
|
|
6592
|
+
ranges,
|
|
6593
|
+
view
|
|
6484
6594
|
});
|
|
6485
|
-
return
|
|
6595
|
+
return ranges;
|
|
6486
6596
|
} catch {
|
|
6487
6597
|
return null;
|
|
6488
6598
|
}
|
|
@@ -6568,7 +6678,7 @@ ${body}
|
|
|
6568
6678
|
}
|
|
6569
6679
|
//#endregion
|
|
6570
6680
|
//#region \0dsh-css:/home/runner/work/dsh-sidenote/dsh-sidenote/src/client/annotate/annotate.module.css.mjs
|
|
6571
|
-
const css$1 = "._SVViG_toolbar{z-index:50;background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l1,#00000014);user-select:none;border-radius:10px;flex-wrap:wrap;align-items:stretch;width:max-content;display:flex;position:fixed;overflow:hidden;transform:translate(-50%,-100%);box-shadow:0 4px 16px #0000001f}._SVViG_toolbarBelow{transform:translate(-50%)}._SVViG_toolbarButton{appearance:none;color:var(--dsw-alias-label-primary,#1f2329);cursor:pointer;white-space:nowrap;background:0 0;border:none;padding:7px 12px;font-size:13px;line-height:20px}._SVViG_toolbarButton+._SVViG_toolbarButton{border-left:1px solid var(--dsw-alias-border-l1,#00000014)}._SVViG_toolbarButton:hover{background:var(--dsw-alias-interactive-bg-hover,#0000000d)}._SVViG_toolbarButton:focus-visible{outline-offset:-3px;outline:2px solid #2f88ff}._SVViG_toolbarStatus{color:var(--dsw-alias-label-secondary,#646a73);flex-basis:100%;padding:6px 12px;font-size:12px;line-height:18px}._SVViG_badge{z-index:50;color:#fff;text-align:center;cursor:pointer;user-select:none;background:#2f88ff;border:none;border-radius:999px;width:18px;height:18px;padding:0;font-size:11px;font-weight:600;line-height:18px;position:fixed;transform:translateY(-50%);box-shadow:0 1px 4px #2f88ff73}._SVViG_badge:hover{background:#1f78f0}._SVViG_highlight{z-index:49;pointer-events:none;background:#2f88ff38;border-radius:2px;position:fixed}._SVViG_editorNew{z-index:50;background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l1,#00000014);border-radius:
|
|
6681
|
+
const css$1 = "._SVViG_toolbar{z-index:50;background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l1,#00000014);user-select:none;border-radius:10px;flex-wrap:wrap;align-items:stretch;width:max-content;display:flex;position:fixed;overflow:hidden;transform:translate(-50%,-100%);box-shadow:0 4px 16px #0000001f}._SVViG_toolbarBelow{transform:translate(-50%)}._SVViG_toolbarButton{appearance:none;color:var(--dsw-alias-label-primary,#1f2329);cursor:pointer;white-space:nowrap;background:0 0;border:none;padding:7px 12px;font-size:13px;line-height:20px}._SVViG_toolbarButton+._SVViG_toolbarButton{border-left:1px solid var(--dsw-alias-border-l1,#00000014)}._SVViG_toolbarButton:hover{background:var(--dsw-alias-interactive-bg-hover,#0000000d)}._SVViG_toolbarButton:focus-visible{outline-offset:-3px;outline:2px solid #2f88ff}._SVViG_toolbarStatus{color:var(--dsw-alias-label-secondary,#646a73);flex-basis:100%;padding:6px 12px;font-size:12px;line-height:18px}._SVViG_badge{z-index:50;color:#fff;text-align:center;cursor:pointer;user-select:none;background:#2f88ff;border:none;border-radius:999px;width:18px;height:18px;padding:0;font-size:11px;font-weight:600;line-height:18px;position:fixed;transform:translateY(-50%);box-shadow:0 1px 4px #2f88ff73}._SVViG_badge:hover{background:#1f78f0}._SVViG_highlight{z-index:49;pointer-events:none;background:#2f88ff38;border-radius:2px;position:fixed}._SVViG_editorNew{z-index:50;background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l1,#00000014);border-radius:18px;align-items:center;gap:8px;padding:6px 8px 6px 12px;display:flex;position:fixed;box-shadow:0 6px 24px #00000024}._SVViG_editorEdit{z-index:50;background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l1,#00000014);border-radius:14px;flex-direction:column;display:flex;position:fixed;overflow:hidden;box-shadow:0 8px 28px #00000029}._SVViG_editorInput{resize:none;min-width:0;min-height:21px;max-height:110px;color:var(--dsw-alias-label-primary,#1f2329);background:0 0;border:none;outline:none;flex:auto;padding:0;font-family:inherit;font-size:13px;line-height:22px;overflow-y:auto}._SVViG_editorTextarea{resize:none;color:var(--dsw-alias-label-primary,#1f2329);background:0 0;border:none;outline:none;padding:10px 12px 4px;font-family:inherit;font-size:13px;line-height:20px}._SVViG_editorInput::placeholder,._SVViG_editorTextarea::placeholder{color:var(--dsw-alias-label-caption,#8f959e)}._SVViG_editorAsk{z-index:50;background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l1,#00000014);border-radius:14px;flex-direction:column;gap:2px;padding:6px 8px 6px 12px;display:flex;position:fixed;box-shadow:0 6px 24px #00000024}._SVViG_editorAskRow{align-items:center;gap:8px;display:flex}._SVViG_editorTarget{color:var(--dsw-alias-label-caption,#8f959e);user-select:none;padding:2px 2px 0;font-size:11px;line-height:16px}._SVViG_confirmButton{color:#fff;cursor:pointer;background:#1f2329;border:none;border-radius:999px;flex:none;place-items:center;width:26px;height:26px;padding:0;display:grid}._SVViG_confirmButton:hover{background:#000}._SVViG_editorFooter{align-items:center;gap:8px;padding:6px 10px 8px;display:flex}._SVViG_editorSpacer{flex:auto}._SVViG_deleteButton{width:26px;height:26px;color:var(--dsw-alias-label-tertiary,#8f959e);cursor:pointer;background:0 0;border:none;border-radius:999px;place-items:center;padding:0;display:grid}._SVViG_deleteButton:hover{background:var(--dsw-alias-interactive-bg-hover,#0000000d);color:var(--dsw-alias-state-error-primary,#d53f3f)}._SVViG_cancelButton,._SVViG_saveButton{cursor:pointer;border:none;border-radius:999px;padding:4px 14px;font-size:13px;line-height:20px}._SVViG_cancelButton{background:var(--dsw-alias-interactive-bg-hover,#0000000d);color:var(--dsw-alias-label-primary,#1f2329)}._SVViG_saveButton{color:#fff;background:#1f2329}._SVViG_saveButton:hover{background:#000}._SVViG_editorError{color:#e5484d;white-space:normal;overflow-wrap:anywhere;padding:2px 2px 0;font-size:12px}._SVViG_badgeSent{background:var(--dsw-alias-label-caption,#8f959e);box-shadow:none;opacity:.75}._SVViG_badgeSent:hover{background:var(--dsw-alias-label-tertiary,#6b7075)}._SVViG_sentChip{border:1px solid var(--dsw-alias-border-l1,#0000001a);background:var(--dsw-alias-interactive-bg-hover,#0000000d);color:var(--dsw-alias-label-secondary,#3f454d);cursor:default;user-select:none;border-radius:999px;align-items:center;gap:4px;margin:0 0 6px;padding:1px 10px;font-size:12px;line-height:18px;display:inline-flex}._SVViG_sentCardTitle{color:var(--dsw-alias-label-tertiary,#8f959e);padding:2px 12px 0;font-size:12px;font-weight:600}._SVViG_sentCardQuote{color:var(--dsw-alias-label-secondary,#3f454d);border-left:2px solid var(--dsw-alias-border-l1,#0000001f);word-break:break-word;margin:4px 12px 0;padding:4px 12px;font-size:13px;line-height:20px}._SVViG_sentCardNote{color:var(--dsw-alias-label-primary,#1f2329);word-break:break-word;padding:4px 12px 10px;font-size:13px;line-height:20px}._SVViG_hint{z-index:50;background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l1,#00000014);max-width:320px;color:var(--dsw-alias-label-secondary,#3f454d);border-radius:12px;align-items:center;gap:10px;padding:10px 12px;font-size:12px;line-height:18px;animation:.25s ease-out _SVViG_dshSidenoteHintIn;display:flex;position:fixed;bottom:160px;right:24px;box-shadow:0 8px 28px #00000024}._SVViG_hintClose{width:20px;height:20px;color:var(--dsw-alias-label-tertiary,#8f959e);cursor:pointer;background:0 0;border:none;border-radius:999px;flex:none;place-items:center;padding:0;font-size:14px;line-height:1;display:grid}._SVViG_hintClose:hover{background:var(--dsw-alias-interactive-bg-hover,#0000000d);color:var(--dsw-alias-label-primary,#1f2329)}@keyframes _SVViG_dshSidenoteHintIn{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}._SVViG_sentChipRow{align-items:center;gap:6px;margin:0 0 6px;display:inline-flex}._SVViG_badgeSent{background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-tertiary,#8f959e);border:1.5px solid var(--dsw-alias-label-caption,#b0b5bb);box-shadow:none;opacity:1;line-height:15px}._SVViG_badgeSent:hover{background:var(--dsw-alias-interactive-bg-hover,#0000000a);color:var(--dsw-alias-label-secondary,#3f454d)}._SVViG_hint{background:color-mix(in srgb, var(--dsw-alias-bg-layer-1,#fff) 88%, transparent);backdrop-filter:blur(8px);bottom:130px}";
|
|
6572
6682
|
const tagId$1 = "dsh-sidenote/annotate.module.css";
|
|
6573
6683
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
|
|
6574
6684
|
const tag = document.createElement("style");
|
|
@@ -6578,35 +6688,35 @@ ${body}
|
|
|
6578
6688
|
document.head.appendChild(tag);
|
|
6579
6689
|
}
|
|
6580
6690
|
var annotate_module_css_default = {
|
|
6581
|
-
"confirmButton": "_SVViG_confirmButton",
|
|
6582
|
-
"hintClose": "_SVViG_hintClose",
|
|
6583
|
-
"dshSidenoteHintIn": "_SVViG_dshSidenoteHintIn",
|
|
6584
|
-
"toolbarButton": "_SVViG_toolbarButton",
|
|
6585
|
-
"deleteButton": "_SVViG_deleteButton",
|
|
6586
|
-
"editorAsk": "_SVViG_editorAsk",
|
|
6587
6691
|
"badge": "_SVViG_badge",
|
|
6588
|
-
"
|
|
6589
|
-
"
|
|
6692
|
+
"editorEdit": "_SVViG_editorEdit",
|
|
6693
|
+
"sentCardQuote": "_SVViG_sentCardQuote",
|
|
6694
|
+
"confirmButton": "_SVViG_confirmButton",
|
|
6590
6695
|
"saveButton": "_SVViG_saveButton",
|
|
6591
|
-
"editorTextarea": "_SVViG_editorTextarea",
|
|
6592
6696
|
"cancelButton": "_SVViG_cancelButton",
|
|
6593
|
-
"
|
|
6697
|
+
"sentCardNote": "_SVViG_sentCardNote",
|
|
6698
|
+
"toolbarBelow": "_SVViG_toolbarBelow",
|
|
6699
|
+
"sentCardTitle": "_SVViG_sentCardTitle",
|
|
6700
|
+
"editorError": "_SVViG_editorError",
|
|
6701
|
+
"sentChip": "_SVViG_sentChip",
|
|
6702
|
+
"highlight": "_SVViG_highlight",
|
|
6594
6703
|
"editorTarget": "_SVViG_editorTarget",
|
|
6704
|
+
"toolbarStatus": "_SVViG_toolbarStatus",
|
|
6705
|
+
"dshSidenoteHintIn": "_SVViG_dshSidenoteHintIn",
|
|
6706
|
+
"toolbarButton": "_SVViG_toolbarButton",
|
|
6595
6707
|
"editorAskRow": "_SVViG_editorAskRow",
|
|
6596
|
-
"highlight": "_SVViG_highlight",
|
|
6597
6708
|
"editorInput": "_SVViG_editorInput",
|
|
6709
|
+
"deleteButton": "_SVViG_deleteButton",
|
|
6710
|
+
"hintClose": "_SVViG_hintClose",
|
|
6598
6711
|
"toolbar": "_SVViG_toolbar",
|
|
6599
|
-
"
|
|
6600
|
-
"editorNew": "_SVViG_editorNew",
|
|
6601
|
-
"sentCardNote": "_SVViG_sentCardNote",
|
|
6602
|
-
"toolbarStatus": "_SVViG_toolbarStatus",
|
|
6603
|
-
"sentCardQuote": "_SVViG_sentCardQuote",
|
|
6604
|
-
"hint": "_SVViG_hint",
|
|
6605
|
-
"editorFooter": "_SVViG_editorFooter",
|
|
6606
|
-
"editorEdit": "_SVViG_editorEdit",
|
|
6712
|
+
"editorAsk": "_SVViG_editorAsk",
|
|
6607
6713
|
"editorSpacer": "_SVViG_editorSpacer",
|
|
6608
|
-
"
|
|
6609
|
-
"
|
|
6714
|
+
"badgeSent": "_SVViG_badgeSent",
|
|
6715
|
+
"editorFooter": "_SVViG_editorFooter",
|
|
6716
|
+
"hint": "_SVViG_hint",
|
|
6717
|
+
"editorNew": "_SVViG_editorNew",
|
|
6718
|
+
"sentChipRow": "_SVViG_sentChipRow",
|
|
6719
|
+
"editorTextarea": "_SVViG_editorTextarea"
|
|
6610
6720
|
};
|
|
6611
6721
|
//#endregion
|
|
6612
6722
|
//#region src/client/annotate/hint.tsx
|
|
@@ -6791,6 +6901,17 @@ ${body}
|
|
|
6791
6901
|
* so the selection survives until the click commits) and failure-safe (an
|
|
6792
6902
|
* error boundary around the tree; layout math is wrapped in anchor.ts).
|
|
6793
6903
|
*/
|
|
6904
|
+
/** 两种新建注解入口共用紧凑的多行输入高度。 */
|
|
6905
|
+
function useAutoGrowingNote(note) {
|
|
6906
|
+
const input = (0, react.useRef)(null);
|
|
6907
|
+
(0, react.useLayoutEffect)(() => {
|
|
6908
|
+
const element = input.current;
|
|
6909
|
+
if (!element) return;
|
|
6910
|
+
element.style.height = "auto";
|
|
6911
|
+
element.style.height = `${Math.min(element.scrollHeight, 110)}px`;
|
|
6912
|
+
}, [note]);
|
|
6913
|
+
return input;
|
|
6914
|
+
}
|
|
6794
6915
|
/** Badge anchor of a freshly captured selection (editor placement on create). */
|
|
6795
6916
|
function selectionBadgePoint(snapshot) {
|
|
6796
6917
|
const anchor = badgeAnchorOf(snapshot.range);
|
|
@@ -6880,11 +7001,11 @@ ${body}
|
|
|
6880
7001
|
text: snapshot.text,
|
|
6881
7002
|
anchorText: snapshot.anchorText,
|
|
6882
7003
|
occurrence: snapshot.occurrence,
|
|
7004
|
+
anchors: snapshot.anchors,
|
|
6883
7005
|
note: ""
|
|
6884
7006
|
});
|
|
6885
|
-
const cached = snapshot.range.cloneRange();
|
|
6886
7007
|
rangeCache.current.set(annotation.id, {
|
|
6887
|
-
|
|
7008
|
+
ranges: snapshot.ranges.map((range) => range.cloneRange()),
|
|
6888
7009
|
view: snapshot.source.view
|
|
6889
7010
|
});
|
|
6890
7011
|
setEditor({
|
|
@@ -6908,6 +7029,7 @@ ${body}
|
|
|
6908
7029
|
y: anchor.y,
|
|
6909
7030
|
abort: new AbortController(),
|
|
6910
7031
|
target,
|
|
7032
|
+
skipNote: !preference.showSideChatNote,
|
|
6911
7033
|
...targetTitle !== void 0 ? { targetTitle } : {}
|
|
6912
7034
|
});
|
|
6913
7035
|
controller.clear();
|
|
@@ -6928,13 +7050,18 @@ ${body}
|
|
|
6928
7050
|
text: snapshot.text,
|
|
6929
7051
|
anchorText: snapshot.anchorText,
|
|
6930
7052
|
occurrence: snapshot.occurrence,
|
|
7053
|
+
anchors: snapshot.anchors,
|
|
6931
7054
|
note
|
|
6932
7055
|
});
|
|
6933
7056
|
rangeCache.current.set(annotation.id, {
|
|
6934
|
-
|
|
7057
|
+
ranges: snapshot.ranges.map((range) => range.cloneRange()),
|
|
6935
7058
|
view: snapshot.source.view
|
|
6936
7059
|
});
|
|
6937
7060
|
setSideDraft((current) => current === sideDraft ? null : current);
|
|
7061
|
+
if (sideDraft.skipNote) {
|
|
7062
|
+
const view = [...document.querySelectorAll("[data-sidenote-chat-session]")].find((element) => element.dataset.sidenoteChatSession === target.childId);
|
|
7063
|
+
if (view) focusSideComposer(view);
|
|
7064
|
+
}
|
|
6938
7065
|
return true;
|
|
6939
7066
|
} catch {
|
|
6940
7067
|
return false;
|
|
@@ -6995,7 +7122,7 @@ ${body}
|
|
|
6995
7122
|
onSave: (note) => {
|
|
6996
7123
|
store.setNote(editingAnnotation.id, note);
|
|
6997
7124
|
closeEditor();
|
|
6998
|
-
const range = rangeCache.current.get(editingAnnotation.id)?.
|
|
7125
|
+
const range = rangeCache.current.get(editingAnnotation.id)?.ranges[0];
|
|
6999
7126
|
const source = range === void 0 ? null : quoteSourceOf(range.startContainer, currentSessionId);
|
|
7000
7127
|
if (source !== null) requestAnimationFrame(() => {
|
|
7001
7128
|
if (document.activeElement === document.body) focusSourceComposer(source);
|
|
@@ -7018,6 +7145,7 @@ ${body}
|
|
|
7018
7145
|
x: sideDraft.x,
|
|
7019
7146
|
y: sideDraft.y,
|
|
7020
7147
|
targetTitle: sideDraft.targetTitle,
|
|
7148
|
+
skipNote: sideDraft.skipNote,
|
|
7021
7149
|
bounds: sourceClip(sideDraft.snapshot.source),
|
|
7022
7150
|
onSave: commitSideDraft,
|
|
7023
7151
|
onCancel: () => {
|
|
@@ -7114,6 +7242,8 @@ ${body}
|
|
|
7114
7242
|
function SideChatNoteEditor(props) {
|
|
7115
7243
|
useLocaleTick();
|
|
7116
7244
|
const [note, setNote] = (0, react.useState)("");
|
|
7245
|
+
const [showNote, setShowNote] = (0, react.useState)(!props.skipNote);
|
|
7246
|
+
const noteInputRef = useAutoGrowingNote(note);
|
|
7117
7247
|
const [failed, setFailed] = (0, react.useState)(false);
|
|
7118
7248
|
const [pending, setPending] = (0, react.useState)(false);
|
|
7119
7249
|
const rootRef = (0, react.useRef)(null);
|
|
@@ -7143,6 +7273,7 @@ ${body}
|
|
|
7143
7273
|
if (cancelled.current) return;
|
|
7144
7274
|
saved.current = ok;
|
|
7145
7275
|
failedRef.current = !ok;
|
|
7276
|
+
if (!ok) setShowNote(true);
|
|
7146
7277
|
setFailed(!ok);
|
|
7147
7278
|
setPending(false);
|
|
7148
7279
|
};
|
|
@@ -7161,6 +7292,9 @@ ${body}
|
|
|
7161
7292
|
};
|
|
7162
7293
|
const saveRef = (0, react.useRef)(save);
|
|
7163
7294
|
saveRef.current = save;
|
|
7295
|
+
(0, react.useEffect)(() => {
|
|
7296
|
+
if (props.skipNote) saveRef.current();
|
|
7297
|
+
}, [props.skipNote]);
|
|
7164
7298
|
(0, react.useEffect)(() => {
|
|
7165
7299
|
const onKeyDown = (event) => {
|
|
7166
7300
|
if (event.key === "Escape") {
|
|
@@ -7192,16 +7326,20 @@ ${body}
|
|
|
7192
7326
|
style: {
|
|
7193
7327
|
left,
|
|
7194
7328
|
top,
|
|
7195
|
-
width
|
|
7329
|
+
width,
|
|
7330
|
+
maxHeight: (props.bounds?.bottom ?? window.innerHeight) - top - 8,
|
|
7331
|
+
overflowY: "auto"
|
|
7196
7332
|
},
|
|
7197
7333
|
children: [
|
|
7198
7334
|
props.targetTitle !== void 0 && props.targetTitle !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7199
7335
|
className: annotate_module_css_default.editorTarget,
|
|
7200
7336
|
children: t("sendToTarget", { title: props.targetTitle })
|
|
7201
7337
|
}),
|
|
7202
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7338
|
+
showNote && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7203
7339
|
className: annotate_module_css_default.editorAskRow,
|
|
7204
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("
|
|
7340
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
7341
|
+
ref: noteInputRef,
|
|
7342
|
+
rows: 1,
|
|
7205
7343
|
className: annotate_module_css_default.editorInput,
|
|
7206
7344
|
value: note,
|
|
7207
7345
|
placeholder: t("sideNotePlaceholder"),
|
|
@@ -7214,7 +7352,7 @@ ${body}
|
|
|
7214
7352
|
setFailed(false);
|
|
7215
7353
|
},
|
|
7216
7354
|
onKeyDown: (event) => {
|
|
7217
|
-
if (event.key !== "Enter") return;
|
|
7355
|
+
if (event.key !== "Enter" || event.shiftKey) return;
|
|
7218
7356
|
if (event.nativeEvent.isComposing || event.nativeEvent.keyCode === 229) return;
|
|
7219
7357
|
event.preventDefault();
|
|
7220
7358
|
save();
|
|
@@ -7252,12 +7390,13 @@ ${body}
|
|
|
7252
7390
|
const [hoveredId, setHoveredId] = (0, react.useState)(null);
|
|
7253
7391
|
const highlightId = props.editingId ?? hoveredId;
|
|
7254
7392
|
for (const annotation of annotations) {
|
|
7255
|
-
const
|
|
7256
|
-
if (
|
|
7393
|
+
const ranges = resolveRanges(annotation, props.cache, props.sessionId);
|
|
7394
|
+
if (ranges === null) continue;
|
|
7395
|
+
const range = ranges[0];
|
|
7257
7396
|
const source = quoteSourceOf(range.startContainer, props.sessionId);
|
|
7258
|
-
if (source === null) continue;
|
|
7397
|
+
if (source === null || source.sessionId !== annotation.sessionId) continue;
|
|
7259
7398
|
const clip = sourceClip(source);
|
|
7260
|
-
if (annotation.id === highlightId) highlight = highlightRectsOf
|
|
7399
|
+
if (annotation.id === highlightId) highlight = ranges.flatMap(highlightRectsOf).map((rect) => {
|
|
7261
7400
|
const left = Math.max(rect.left, clip.left), top = Math.max(rect.top, clip.top);
|
|
7262
7401
|
return {
|
|
7263
7402
|
left,
|
|
@@ -7325,6 +7464,7 @@ ${body}
|
|
|
7325
7464
|
const rootRef = (0, react.useRef)(null);
|
|
7326
7465
|
const noteRef = (0, react.useRef)(note);
|
|
7327
7466
|
noteRef.current = note;
|
|
7467
|
+
const noteInputRef = useAutoGrowingNote(note);
|
|
7328
7468
|
(0, react.useEffect)(() => {
|
|
7329
7469
|
const onKeyDown = (event) => {
|
|
7330
7470
|
if (event.key === "Escape") {
|
|
@@ -7359,7 +7499,9 @@ ${body}
|
|
|
7359
7499
|
style: {
|
|
7360
7500
|
left,
|
|
7361
7501
|
top,
|
|
7362
|
-
width
|
|
7502
|
+
width,
|
|
7503
|
+
maxHeight: (props.bounds?.bottom ?? window.innerHeight) - top - 8,
|
|
7504
|
+
overflowY: "auto"
|
|
7363
7505
|
},
|
|
7364
7506
|
children: [props.targetTitle !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7365
7507
|
className: annotate_module_css_default.editorTarget,
|
|
@@ -7367,16 +7509,18 @@ ${body}
|
|
|
7367
7509
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7368
7510
|
className: annotate_module_css_default.editorAskRow,
|
|
7369
7511
|
style: { flex: 1 },
|
|
7370
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("
|
|
7512
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
7513
|
+
ref: noteInputRef,
|
|
7371
7514
|
className: annotate_module_css_default.editorInput,
|
|
7372
7515
|
value: note,
|
|
7373
7516
|
placeholder: t("notePlaceholder"),
|
|
7517
|
+
rows: 1,
|
|
7374
7518
|
autoFocus: true,
|
|
7375
7519
|
onChange: (event) => {
|
|
7376
7520
|
setNote(event.target.value);
|
|
7377
7521
|
},
|
|
7378
7522
|
onKeyDown: (event) => {
|
|
7379
|
-
if (event.key !== "Enter") return;
|
|
7523
|
+
if (event.key !== "Enter" || event.shiftKey) return;
|
|
7380
7524
|
if (event.nativeEvent.isComposing || event.nativeEvent.keyCode === 229) return;
|
|
7381
7525
|
event.preventDefault();
|
|
7382
7526
|
save();
|
|
@@ -7810,6 +7954,7 @@ ${body}
|
|
|
7810
7954
|
cancelInputRollback(input);
|
|
7811
7955
|
const parts = [...options.leadingBlocks ?? []];
|
|
7812
7956
|
if (annotations.length > 0) parts.push(buildProtocolBlock(annotations));
|
|
7957
|
+
const wireNumbers = new Map(annotations.map((annotation) => [annotation.id, annotation.number]));
|
|
7813
7958
|
const block = parts.join("\n\n");
|
|
7814
7959
|
if (block === "") return false;
|
|
7815
7960
|
const draftBeforeWait = input.state.getSnapshot();
|
|
@@ -7831,7 +7976,10 @@ ${body}
|
|
|
7831
7976
|
}
|
|
7832
7977
|
receipt.submit(options.mode);
|
|
7833
7978
|
await receipt.outcome;
|
|
7834
|
-
store.markSent(annotations.filter((annotation) =>
|
|
7979
|
+
store.markSent(annotations.filter((annotation) => {
|
|
7980
|
+
const current = store.get(annotation.id);
|
|
7981
|
+
return current !== void 0 && current.state === "active" && (current === annotation || current.note === annotation.note && current.text === annotation.text);
|
|
7982
|
+
}).map((annotation) => annotation.id), wireNumbers);
|
|
7835
7983
|
return true;
|
|
7836
7984
|
} catch (error) {
|
|
7837
7985
|
rollbackInputPrefix(input, prefix, staged ? () => {
|
|
@@ -8206,7 +8354,7 @@ ${body}
|
|
|
8206
8354
|
}
|
|
8207
8355
|
//#endregion
|
|
8208
8356
|
//#region src/client/preferences.ts
|
|
8209
|
-
/** Share
|
|
8357
|
+
/** Share host-backed preferences between every main and side conversation. */
|
|
8210
8358
|
function createSidenotePreferences(form) {
|
|
8211
8359
|
const listeners = /* @__PURE__ */ new Set();
|
|
8212
8360
|
let saving = false;
|
|
@@ -8215,6 +8363,7 @@ ${body}
|
|
|
8215
8363
|
const state = form.getSnapshot();
|
|
8216
8364
|
return {
|
|
8217
8365
|
hidden: state.value?.hideNativeQuote ?? true,
|
|
8366
|
+
showSideChatNote: state.value?.showSideChatNote ?? true,
|
|
8218
8367
|
status: state.status,
|
|
8219
8368
|
writable: state.writable,
|
|
8220
8369
|
saving,
|
|
@@ -8227,6 +8376,20 @@ ${body}
|
|
|
8227
8376
|
for (const listener of listeners) listener();
|
|
8228
8377
|
};
|
|
8229
8378
|
const unsubscribe = form.subscribe(publish);
|
|
8379
|
+
const set = async (field, value) => {
|
|
8380
|
+
if (saving || snapshot.status !== "ready" || !snapshot.writable) return;
|
|
8381
|
+
saving = true;
|
|
8382
|
+
failed = false;
|
|
8383
|
+
publish();
|
|
8384
|
+
try {
|
|
8385
|
+
failed = !await form.set(field, value);
|
|
8386
|
+
} catch {
|
|
8387
|
+
failed = true;
|
|
8388
|
+
} finally {
|
|
8389
|
+
saving = false;
|
|
8390
|
+
publish();
|
|
8391
|
+
}
|
|
8392
|
+
};
|
|
8230
8393
|
return {
|
|
8231
8394
|
getSnapshot: () => snapshot,
|
|
8232
8395
|
subscribe(listener) {
|
|
@@ -8235,20 +8398,8 @@ ${body}
|
|
|
8235
8398
|
listeners.delete(listener);
|
|
8236
8399
|
};
|
|
8237
8400
|
},
|
|
8238
|
-
|
|
8239
|
-
|
|
8240
|
-
saving = true;
|
|
8241
|
-
failed = false;
|
|
8242
|
-
publish();
|
|
8243
|
-
try {
|
|
8244
|
-
failed = !await form.set("hideNativeQuote", hidden);
|
|
8245
|
-
} catch {
|
|
8246
|
-
failed = true;
|
|
8247
|
-
} finally {
|
|
8248
|
-
saving = false;
|
|
8249
|
-
publish();
|
|
8250
|
-
}
|
|
8251
|
-
},
|
|
8401
|
+
setHidden: (hidden) => set("hideNativeQuote", hidden),
|
|
8402
|
+
setShowSideChatNote: (show) => set("showSideChatNote", show),
|
|
8252
8403
|
dispose() {
|
|
8253
8404
|
unsubscribe();
|
|
8254
8405
|
listeners.clear();
|
|
@@ -8267,15 +8418,15 @@ ${body}
|
|
|
8267
8418
|
document.head.appendChild(tag);
|
|
8268
8419
|
}
|
|
8269
8420
|
var settings_module_css_default = {
|
|
8270
|
-
"
|
|
8421
|
+
"hint": "_2xJwMG_hint",
|
|
8271
8422
|
"description": "_2xJwMG_description",
|
|
8272
|
-
"error": "_2xJwMG_error",
|
|
8273
8423
|
"status": "_2xJwMG_status",
|
|
8274
8424
|
"row": "_2xJwMG_row",
|
|
8275
|
-
"
|
|
8276
|
-
"
|
|
8425
|
+
"page": "_2xJwMG_page",
|
|
8426
|
+
"copy": "_2xJwMG_copy",
|
|
8277
8427
|
"title": "_2xJwMG_title",
|
|
8278
|
-
"
|
|
8428
|
+
"label": "_2xJwMG_label",
|
|
8429
|
+
"error": "_2xJwMG_error"
|
|
8279
8430
|
};
|
|
8280
8431
|
//#endregion
|
|
8281
8432
|
//#region src/client/settings.tsx
|
|
@@ -8322,6 +8473,32 @@ ${body}
|
|
|
8322
8473
|
}
|
|
8323
8474
|
})]
|
|
8324
8475
|
}),
|
|
8476
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8477
|
+
className: settings_module_css_default.row,
|
|
8478
|
+
role: "group",
|
|
8479
|
+
"aria-labelledby": `${id}-side-note-label`,
|
|
8480
|
+
"aria-describedby": `${id}-side-note-description`,
|
|
8481
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8482
|
+
className: settings_module_css_default.copy,
|
|
8483
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8484
|
+
id: `${id}-side-note-label`,
|
|
8485
|
+
className: settings_module_css_default.label,
|
|
8486
|
+
children: t("showSideChatNote")
|
|
8487
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
8488
|
+
id: `${id}-side-note-description`,
|
|
8489
|
+
className: settings_module_css_default.hint,
|
|
8490
|
+
children: t("showSideChatNoteHint")
|
|
8491
|
+
})]
|
|
8492
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Switch, {
|
|
8493
|
+
checked: state.showSideChatNote,
|
|
8494
|
+
label: t("showSideChatNote"),
|
|
8495
|
+
title: t("showSideChatNoteHint"),
|
|
8496
|
+
disabled: state.status !== "ready" || !state.writable || state.saving,
|
|
8497
|
+
onChange: (show) => {
|
|
8498
|
+
preferences.setShowSideChatNote(show);
|
|
8499
|
+
}
|
|
8500
|
+
})]
|
|
8501
|
+
}),
|
|
8325
8502
|
state.saving && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
8326
8503
|
className: settings_module_css_default.status,
|
|
8327
8504
|
role: "status",
|
|
@@ -8365,6 +8542,41 @@ ${body}
|
|
|
8365
8542
|
}, ({ size }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconListPenOutline16, { size })));
|
|
8366
8543
|
}
|
|
8367
8544
|
//#endregion
|
|
8545
|
+
//#region src/client/host/replyDefaults.ts
|
|
8546
|
+
function initializeFinalReplies(sidenote, chat) {
|
|
8547
|
+
let stopped = false;
|
|
8548
|
+
let attempted = false;
|
|
8549
|
+
const initialize = () => {
|
|
8550
|
+
if (stopped || attempted) return;
|
|
8551
|
+
const own = sidenote.getSnapshot(), target = chat.getSnapshot();
|
|
8552
|
+
if (own.status !== "ready" || target.status !== "ready" || !own.writable || !target.writable || !own.value || !target.value || own.revision === void 0 || target.revision === void 0) return;
|
|
8553
|
+
if (own.value.finalRepliesDefaultAttempted) return;
|
|
8554
|
+
attempted = true;
|
|
8555
|
+
(async () => {
|
|
8556
|
+
if (!await sidenote.mutate([{
|
|
8557
|
+
op: "set",
|
|
8558
|
+
path: ["finalRepliesDefaultAttempted"],
|
|
8559
|
+
value: true
|
|
8560
|
+
}], own.revision) || stopped) return;
|
|
8561
|
+
if (target.value.foldedReplies !== "final") await chat.mutate([{
|
|
8562
|
+
op: "set",
|
|
8563
|
+
path: ["foldedReplies"],
|
|
8564
|
+
value: "final"
|
|
8565
|
+
}], target.revision);
|
|
8566
|
+
})().catch(() => {
|
|
8567
|
+
console.warn("[dsh-sidenote] 最终回答显示偏好初始化未完成,保留当前设置。");
|
|
8568
|
+
});
|
|
8569
|
+
};
|
|
8570
|
+
const unsubscribeOwn = sidenote.subscribe(initialize);
|
|
8571
|
+
const unsubscribeChat = chat.subscribe(initialize);
|
|
8572
|
+
initialize();
|
|
8573
|
+
return () => {
|
|
8574
|
+
stopped = true;
|
|
8575
|
+
unsubscribeOwn();
|
|
8576
|
+
unsubscribeChat();
|
|
8577
|
+
};
|
|
8578
|
+
}
|
|
8579
|
+
//#endregion
|
|
8368
8580
|
//#region src/client/index.tsx
|
|
8369
8581
|
const inject = [
|
|
8370
8582
|
"sessions",
|
|
@@ -8387,10 +8599,13 @@ ${body}
|
|
|
8387
8599
|
sweepOrphanedSideChatMeta();
|
|
8388
8600
|
const reflow = createReflowStore();
|
|
8389
8601
|
const annotations = createAnnotationStore();
|
|
8390
|
-
const
|
|
8602
|
+
const forms = ctx.get("configForms");
|
|
8603
|
+
const form = forms.get("side-chat");
|
|
8604
|
+
const preferences = createSidenotePreferences(form);
|
|
8391
8605
|
ctx.effect(() => () => {
|
|
8392
8606
|
preferences.dispose();
|
|
8393
8607
|
}, "dsh-sidenote: preferences");
|
|
8608
|
+
ctx.effect(() => initializeFinalReplies(form, forms.get("ui-chat")), "dsh-sidenote: final replies default");
|
|
8394
8609
|
registerSidenoteSettings(ctx, preferences);
|
|
8395
8610
|
registerSideChat(ctx, reflow, annotations);
|
|
8396
8611
|
registerAnnotations(ctx, reflow, annotations, preferences);
|