dsh-retrace 0.4.13 → 0.4.15
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.bundle.js +9 -3
- package/lib/client.js +20 -3
- package/lib/dynamic-client.js +9 -3
- package/lib/prewrite-guard.js +6 -4
- package/package.json +1 -1
package/lib/client.bundle.js
CHANGED
|
@@ -488,6 +488,10 @@ function useMessageSeq(useSession, messageId) {
|
|
|
488
488
|
});
|
|
489
489
|
}
|
|
490
490
|
var SHADOW_SAFETY_RATIO = 0.4;
|
|
491
|
+
var SHADOW_MIN_ROWS_FOR_RATIO = 20;
|
|
492
|
+
function shadowDegraded(keys, rowCount) {
|
|
493
|
+
return keys !== null && rowCount > SHADOW_MIN_ROWS_FOR_RATIO && keys.length / rowCount > SHADOW_SAFETY_RATIO;
|
|
494
|
+
}
|
|
491
495
|
function hiddenKeysFor(shadowedSeqs, nodes) {
|
|
492
496
|
if (!Array.isArray(shadowedSeqs) || shadowedSeqs.length === 0) return null;
|
|
493
497
|
const hidden = new Set(shadowedSeqs);
|
|
@@ -515,6 +519,7 @@ var EMPTY_HIDE_PLAN = Object.freeze({
|
|
|
515
519
|
hiddenFor: () => null,
|
|
516
520
|
planFor: () => null,
|
|
517
521
|
unionRatio: 0,
|
|
522
|
+
rowCount: 0,
|
|
518
523
|
firstMarkerKey: null
|
|
519
524
|
});
|
|
520
525
|
var PLUGIN_PSEUDO_KINDS = /* @__PURE__ */ new Set(["user-actions", "retrace-reference", "recall-marker"]);
|
|
@@ -545,7 +550,7 @@ function useMarkerHidePlan(useSession) {
|
|
|
545
550
|
const union = /* @__PURE__ */ new Set();
|
|
546
551
|
for (const marker of markers) {
|
|
547
552
|
const keys = hiddenKeysFor(marker.data?.shadowedSeqs, nodes);
|
|
548
|
-
const degraded = keys
|
|
553
|
+
const degraded = shadowDegraded(keys, rowCount);
|
|
549
554
|
plans.set(marker.key, { keys: degraded ? null : keys, degraded });
|
|
550
555
|
if (keys !== null) for (const key of keys) union.add(key);
|
|
551
556
|
}
|
|
@@ -554,6 +559,7 @@ function useMarkerHidePlan(useSession) {
|
|
|
554
559
|
planFor: (key) => plans.get(key) ?? null,
|
|
555
560
|
hiddenFor: (key) => plans.get(key)?.keys ?? null,
|
|
556
561
|
unionRatio: rowCount > 0 ? union.size / rowCount : 0,
|
|
562
|
+
rowCount,
|
|
557
563
|
firstMarkerKey: markers[0].key
|
|
558
564
|
};
|
|
559
565
|
return hidePlanCacheValue;
|
|
@@ -567,7 +573,7 @@ function rowHiddenByKey(snapshot, rowKey) {
|
|
|
567
573
|
if (node.kind !== "recall-marker" || node.data?.compact) continue;
|
|
568
574
|
const keys = hiddenKeysFor(node.data?.shadowedSeqs, nodes);
|
|
569
575
|
if (keys === null) continue;
|
|
570
|
-
if (
|
|
576
|
+
if (shadowDegraded(keys, rowCount)) continue;
|
|
571
577
|
if (keys.includes(rowKey)) return true;
|
|
572
578
|
}
|
|
573
579
|
return false;
|
|
@@ -806,7 +812,7 @@ function RecallMarkerRow({ node, useSession, t }) {
|
|
|
806
812
|
const count = Array.isArray(shadowedSeqs) ? shadowedSeqs.length : 0;
|
|
807
813
|
const label = op === "recall" ? count > 1 ? t("marker.recallMany", { count }) : t("marker.recallOne") : op === "regenerate" ? t("marker.regenerate") : t("marker.edit");
|
|
808
814
|
const degradedHint = !legacy && plan?.degraded === true ? (0, import_react.createElement)("div", { key: "degraded", className: "dsh-rt-marker-hint" }, t("marker.degradedHint")) : null;
|
|
809
|
-
const unionHint = !legacy && hidePlan.firstMarkerKey === node.key && hidePlan.unionRatio > SHADOW_SAFETY_RATIO ? (0, import_react.createElement)(
|
|
815
|
+
const unionHint = !legacy && hidePlan.firstMarkerKey === node.key && hidePlan.rowCount > SHADOW_MIN_ROWS_FOR_RATIO && hidePlan.unionRatio > SHADOW_SAFETY_RATIO ? (0, import_react.createElement)(
|
|
810
816
|
"div",
|
|
811
817
|
{ key: "union", className: "dsh-rt-marker-hint" },
|
|
812
818
|
t("marker.unionHint", { count: Math.round(hidePlan.unionRatio * 100) })
|
package/lib/client.js
CHANGED
|
@@ -565,6 +565,21 @@ function useMessageSeq(useSession, messageId) {
|
|
|
565
565
|
*/
|
|
566
566
|
const SHADOW_SAFETY_RATIO = 0.4
|
|
567
567
|
|
|
568
|
+
/**
|
|
569
|
+
* 短会话豁免阈值(2026-09-01,独立审查问题 B 的 client 侧另一半;
|
|
570
|
+
* 09-01 用户实测调大至 20):行数 ≤ 本值的会话永不触发 40% 降级——否则
|
|
571
|
+
* 小会话撤回/编辑 2-4 条消息就 >40%,被误判为「大范围操作」降级为不隐藏
|
|
572
|
+
* (用户实测:「已撤回 4 条消息 + 此操作涉及大范围对话…」= 小会话误伤)。
|
|
573
|
+
* 与 host 侧 ROLLBACK_MIN_SURFACE=20(surface 节点)同源:短会话豁免只在
|
|
574
|
+
* 大会话按比例判定。20 行 ≈ 10 轮 ≈ 20 条消息,正常撤回/编辑远小于此。
|
|
575
|
+
*/
|
|
576
|
+
const SHADOW_MIN_ROWS_FOR_RATIO = 20
|
|
577
|
+
|
|
578
|
+
/** 40% 降级判定(短会话豁免版):行数足够大才按比例判定。 */
|
|
579
|
+
function shadowDegraded(keys, rowCount) {
|
|
580
|
+
return keys !== null && rowCount > SHADOW_MIN_ROWS_FOR_RATIO && keys.length / rowCount > SHADOW_SAFETY_RATIO
|
|
581
|
+
}
|
|
582
|
+
|
|
568
583
|
/**
|
|
569
584
|
* Every chat-node key that should disappear when `shadowedSeqs` are recalled:
|
|
570
585
|
* the shadowed message rows themselves, plus the per-turn action row (copy /
|
|
@@ -617,6 +632,7 @@ const EMPTY_HIDE_PLAN = Object.freeze({
|
|
|
617
632
|
hiddenFor: () => null,
|
|
618
633
|
planFor: () => null,
|
|
619
634
|
unionRatio: 0,
|
|
635
|
+
rowCount: 0,
|
|
620
636
|
firstMarkerKey: null,
|
|
621
637
|
})
|
|
622
638
|
|
|
@@ -660,7 +676,7 @@ function useMarkerHidePlan(useSession) {
|
|
|
660
676
|
const union = new Set()
|
|
661
677
|
for (const marker of markers) {
|
|
662
678
|
const keys = hiddenKeysFor(marker.data?.shadowedSeqs, nodes)
|
|
663
|
-
const degraded = keys
|
|
679
|
+
const degraded = shadowDegraded(keys, rowCount)
|
|
664
680
|
plans.set(marker.key, { keys: degraded ? null : keys, degraded })
|
|
665
681
|
if (keys !== null) for (const key of keys) union.add(key)
|
|
666
682
|
}
|
|
@@ -669,6 +685,7 @@ function useMarkerHidePlan(useSession) {
|
|
|
669
685
|
planFor: (key) => plans.get(key) ?? null,
|
|
670
686
|
hiddenFor: (key) => plans.get(key)?.keys ?? null,
|
|
671
687
|
unionRatio: rowCount > 0 ? union.size / rowCount : 0,
|
|
688
|
+
rowCount,
|
|
672
689
|
firstMarkerKey: markers[0].key,
|
|
673
690
|
}
|
|
674
691
|
return hidePlanCacheValue
|
|
@@ -689,7 +706,7 @@ function rowHiddenByKey(snapshot, rowKey) {
|
|
|
689
706
|
if (node.kind !== 'recall-marker' || node.data?.compact) continue // compact markers never hide rows
|
|
690
707
|
const keys = hiddenKeysFor(node.data?.shadowedSeqs, nodes)
|
|
691
708
|
if (keys === null) continue
|
|
692
|
-
if (
|
|
709
|
+
if (shadowDegraded(keys, rowCount)) continue // degraded: hides nothing
|
|
693
710
|
if (keys.includes(rowKey)) return true
|
|
694
711
|
}
|
|
695
712
|
return false
|
|
@@ -996,7 +1013,7 @@ function RecallMarkerRow({ node, useSession, t }) {
|
|
|
996
1013
|
const degradedHint = !legacy && plan?.degraded === true
|
|
997
1014
|
? createElement('div', { key: 'degraded', className: 'dsh-rt-marker-hint' }, t('marker.degradedHint'))
|
|
998
1015
|
: null
|
|
999
|
-
const unionHint = !legacy && hidePlan.firstMarkerKey === node.key && hidePlan.unionRatio > SHADOW_SAFETY_RATIO
|
|
1016
|
+
const unionHint = !legacy && hidePlan.firstMarkerKey === node.key && hidePlan.rowCount > SHADOW_MIN_ROWS_FOR_RATIO && hidePlan.unionRatio > SHADOW_SAFETY_RATIO
|
|
1000
1017
|
? createElement('div', { key: 'union', className: 'dsh-rt-marker-hint' },
|
|
1001
1018
|
t('marker.unionHint', { count: Math.round(hidePlan.unionRatio * 100) }))
|
|
1002
1019
|
: null
|
package/lib/dynamic-client.js
CHANGED
|
@@ -494,6 +494,10 @@ return {
|
|
|
494
494
|
});
|
|
495
495
|
}
|
|
496
496
|
var SHADOW_SAFETY_RATIO = 0.4;
|
|
497
|
+
var SHADOW_MIN_ROWS_FOR_RATIO = 20;
|
|
498
|
+
function shadowDegraded(keys, rowCount) {
|
|
499
|
+
return keys !== null && rowCount > SHADOW_MIN_ROWS_FOR_RATIO && keys.length / rowCount > SHADOW_SAFETY_RATIO;
|
|
500
|
+
}
|
|
497
501
|
function hiddenKeysFor(shadowedSeqs, nodes) {
|
|
498
502
|
if (!Array.isArray(shadowedSeqs) || shadowedSeqs.length === 0) return null;
|
|
499
503
|
const hidden = new Set(shadowedSeqs);
|
|
@@ -521,6 +525,7 @@ return {
|
|
|
521
525
|
hiddenFor: () => null,
|
|
522
526
|
planFor: () => null,
|
|
523
527
|
unionRatio: 0,
|
|
528
|
+
rowCount: 0,
|
|
524
529
|
firstMarkerKey: null
|
|
525
530
|
});
|
|
526
531
|
var PLUGIN_PSEUDO_KINDS = /* @__PURE__ */ new Set(["user-actions", "retrace-reference", "recall-marker"]);
|
|
@@ -551,7 +556,7 @@ return {
|
|
|
551
556
|
const union = /* @__PURE__ */ new Set();
|
|
552
557
|
for (const marker of markers) {
|
|
553
558
|
const keys = hiddenKeysFor(marker.data?.shadowedSeqs, nodes);
|
|
554
|
-
const degraded = keys
|
|
559
|
+
const degraded = shadowDegraded(keys, rowCount);
|
|
555
560
|
plans.set(marker.key, { keys: degraded ? null : keys, degraded });
|
|
556
561
|
if (keys !== null) for (const key of keys) union.add(key);
|
|
557
562
|
}
|
|
@@ -560,6 +565,7 @@ return {
|
|
|
560
565
|
planFor: (key) => plans.get(key) ?? null,
|
|
561
566
|
hiddenFor: (key) => plans.get(key)?.keys ?? null,
|
|
562
567
|
unionRatio: rowCount > 0 ? union.size / rowCount : 0,
|
|
568
|
+
rowCount,
|
|
563
569
|
firstMarkerKey: markers[0].key
|
|
564
570
|
};
|
|
565
571
|
return hidePlanCacheValue;
|
|
@@ -573,7 +579,7 @@ return {
|
|
|
573
579
|
if (node.kind !== "recall-marker" || node.data?.compact) continue;
|
|
574
580
|
const keys = hiddenKeysFor(node.data?.shadowedSeqs, nodes);
|
|
575
581
|
if (keys === null) continue;
|
|
576
|
-
if (
|
|
582
|
+
if (shadowDegraded(keys, rowCount)) continue;
|
|
577
583
|
if (keys.includes(rowKey)) return true;
|
|
578
584
|
}
|
|
579
585
|
return false;
|
|
@@ -812,7 +818,7 @@ return {
|
|
|
812
818
|
const count = Array.isArray(shadowedSeqs) ? shadowedSeqs.length : 0;
|
|
813
819
|
const label = op === "recall" ? count > 1 ? t("marker.recallMany", { count }) : t("marker.recallOne") : op === "regenerate" ? t("marker.regenerate") : t("marker.edit");
|
|
814
820
|
const degradedHint = !legacy && plan?.degraded === true ? (0, import_react.createElement)("div", { key: "degraded", className: "dsh-rt-marker-hint" }, t("marker.degradedHint")) : null;
|
|
815
|
-
const unionHint = !legacy && hidePlan.firstMarkerKey === node.key && hidePlan.unionRatio > SHADOW_SAFETY_RATIO ? (0, import_react.createElement)(
|
|
821
|
+
const unionHint = !legacy && hidePlan.firstMarkerKey === node.key && hidePlan.rowCount > SHADOW_MIN_ROWS_FOR_RATIO && hidePlan.unionRatio > SHADOW_SAFETY_RATIO ? (0, import_react.createElement)(
|
|
816
822
|
"div",
|
|
817
823
|
{ key: "union", className: "dsh-rt-marker-hint" },
|
|
818
824
|
t("marker.unionHint", { count: Math.round(hidePlan.unionRatio * 100) })
|
package/lib/prewrite-guard.js
CHANGED
|
@@ -44,11 +44,13 @@ import { editorError } from './host-core.js'
|
|
|
44
44
|
export const ROLLBACK_RATIO = 0.4
|
|
45
45
|
|
|
46
46
|
/**
|
|
47
|
-
* 短会话豁免阈值(2026-08-31 独立审查问题 B
|
|
48
|
-
*
|
|
49
|
-
*
|
|
47
|
+
* 短会话豁免阈值(2026-08-31 独立审查问题 B,2026-09-01 用户实测调大):
|
|
48
|
+
* surface 节点 ≤ 20(≈ 10 轮 ≈ 20 条消息)的会话不做回档幅度拦截——
|
|
49
|
+
* 否则 4-7 轮小会话撤回/编辑 100% 被拒(用户实测「一共没几个对话,点击就提示
|
|
50
|
+
* 遮蔽 100%」)。事故防御针对**大会话**的「编辑早期消息遮蔽几十轮」,
|
|
51
|
+
* 20 条以内的小会话无此风险。与 client 侧 SHADOW_MIN_ROWS_FOR_RATIO 同源。
|
|
50
52
|
*/
|
|
51
|
-
export const ROLLBACK_MIN_SURFACE =
|
|
53
|
+
export const ROLLBACK_MIN_SURFACE = 20
|
|
52
54
|
|
|
53
55
|
/**
|
|
54
56
|
* 该 marker 是否来自 rollback(restore op)——rollback 本身就是「从快照点
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-retrace",
|
|
3
3
|
"description": "Retrace · 回溯 — Recall, edit-and-resend, regenerate, and conversation/artifact versioning (timeline, rollback, fork map) for DeepSeek Harness — Web and Desktop",
|
|
4
|
-
"version": "0.4.
|
|
4
|
+
"version": "0.4.15",
|
|
5
5
|
"packageManager": "pnpm@11.7.0",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "lib/index.js",
|