dsh-brief-sidebar 0.9.0 → 0.9.2

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 CHANGED
@@ -516,6 +516,106 @@ window.__ModuleLoader__.load({
516
516
  return sessionPaths.filter((path) => !active.has(normalized(path)));
517
517
  }
518
518
  //#endregion
519
+ //#region src/client/summary/FoldToggle.tsx
520
+ /**
521
+ * The two group chrome pieces the summary sections share: a counted group
522
+ * title, and the toggle that folds a group away.
523
+ *
524
+ * Extracted because the deliverables section (本回合 / 更早改动) and the recall
525
+ * section (活跃召回 / 其余历史召回) now fold a history group the same way. Two
526
+ * private copies of the same button would drift the first time either section
527
+ * touches padding — and the whole point of the split is that a reader can tell
528
+ * "what is live now" from "what the session also contains" without learning a
529
+ * different layout per section.
530
+ *
531
+ * Colours come from `--dsw-alias-*` tokens only (skin contract, enforced by
532
+ * `tests/purity.spec.ts`).
533
+ */
534
+ /** Section-level title under the section header: quieter, same left gutter. */
535
+ const GROUP_HEADER_STYLE = {
536
+ padding: "8px 12px 0",
537
+ color: "var(--dsw-alias-label-tertiary)",
538
+ fontSize: 11,
539
+ fontWeight: 600
540
+ };
541
+ /** The fold switch: full-width hit area, tertiary text, chevron at the end. */
542
+ const TOGGLE_STYLE = {
543
+ background: "none",
544
+ border: "none",
545
+ font: "inherit",
546
+ fontSize: 12,
547
+ color: "var(--dsw-alias-label-tertiary)",
548
+ cursor: "pointer",
549
+ display: "flex",
550
+ alignItems: "center",
551
+ gap: 4,
552
+ padding: "6px 12px",
553
+ textAlign: "left",
554
+ width: "calc(100% - 24px)"
555
+ };
556
+ /** The note beside a folded group (e.g. how many the capped list left out). */
557
+ const CAPTION_STYLE = {
558
+ padding: "0 12px 6px",
559
+ color: "var(--dsw-alias-label-tertiary)",
560
+ fontSize: 11,
561
+ lineHeight: "16px"
562
+ };
563
+ const CHEVRON_STYLE$1 = (open) => ({
564
+ flexShrink: 0,
565
+ transition: "transform 0.16s",
566
+ transform: open ? "rotate(180deg)" : "none"
567
+ });
568
+ /**
569
+ * A counted group title. Renders nothing when the group is empty — an empty
570
+ * "活跃召回 · 0" line would ask the reader to explain a heading rather than read
571
+ * a fact.
572
+ * @param props - already-interpolated text, plus an optional DOM marker.
573
+ */
574
+ function GroupHeader(props) {
575
+ if (props.text.length === 0) return null;
576
+ return (0, react.createElement)("div", {
577
+ style: GROUP_HEADER_STYLE,
578
+ "data-dsh-brief-sidebar": props.marker ?? "group-header"
579
+ }, props.text);
580
+ }
581
+ /**
582
+ * The fold switch. `marker` is what tests (and the browser probe) click, so it
583
+ * belongs to the component rather than to either caller's markup.
584
+ * @param props - label, current state, DOM marker, click handler.
585
+ */
586
+ function FoldToggle(props) {
587
+ const { label, open, marker } = props;
588
+ return (0, react.createElement)("button", {
589
+ type: "button",
590
+ "aria-expanded": open,
591
+ style: TOGGLE_STYLE,
592
+ "data-dsh-brief-sidebar": marker,
593
+ onClick: () => {
594
+ props.onToggle();
595
+ }
596
+ }, label, (0, react.createElement)("svg", {
597
+ width: 10,
598
+ height: 10,
599
+ viewBox: "0 0 16 16",
600
+ "aria-hidden": true,
601
+ style: CHEVRON_STYLE$1(open)
602
+ }, (0, react.createElement)("path", {
603
+ d: "M4 6l4 4 4-4",
604
+ fill: "none",
605
+ stroke: "currentColor",
606
+ strokeWidth: 1.5,
607
+ strokeLinecap: "round",
608
+ strokeLinejoin: "round"
609
+ })));
610
+ }
611
+ /** A quiet caption under a group, used for the "the list is capped" note. */
612
+ function GroupCaption(props) {
613
+ return (0, react.createElement)("div", {
614
+ style: CAPTION_STYLE,
615
+ "data-dsh-brief-sidebar": props.marker
616
+ }, props.text);
617
+ }
618
+ //#endregion
519
619
  //#region src/client/locales.ts
520
620
  /**
521
621
  * Plugin-owned i18n dictionaries.
@@ -560,6 +660,8 @@ window.__ModuleLoader__.load({
560
660
  "deliverables.empty": "本回合暂无改动文件",
561
661
  "deliverables.emptyHint": "会话里成功写入或修改文件后,它们会实时出现在这里。",
562
662
  "deliverables.history": "更早改动的文件 · {count}",
663
+ "deliverables.currentTurn": "本回合改动 · {count}",
664
+ "deliverables.historyCapped": "(会话共 {total} 个文件,列表已截断)",
563
665
  "deliverable.codeplanTag": "规划",
564
666
  "section.memorySlots": "记忆",
565
667
  "slots.empty": "当前没有激活的记忆槽位",
@@ -581,13 +683,19 @@ window.__ModuleLoader__.load({
581
683
  "recall.obsoleteWhy": "声明过时后,该记忆退场(可恢复),下一轮会告知模型",
582
684
  "recall.strikeHint": ";判过时的条目会一直保留在列表里并划上删除线(清空会话才移除)",
583
685
  "recall.supersededHidden": "已隐藏 {count} 条被摘要取代的旧召回(正文已不在上下文)",
686
+ "recall.activeGroup": "活跃召回 · {count}",
687
+ "recall.historyGroup": "其余历史召回 · {count}",
688
+ "recall.supersededTag": "已被摘要取代",
584
689
  "recall.noBody": "(本帧没有这条记忆的全文)",
585
690
  "section.skillUsage": "技能引用",
586
691
  "skillUsage.empty": "本会话还没载入过技能",
587
- "skillUsage.emptyHint": "模型用 skill 工具载入技能后,技能名会实时出现在这里。",
692
+ "skillUsage.emptyHint": "模型用 skill 工具载入、或你直接点用某个技能后,技能名会实时出现在这里。",
588
693
  "skillUsage.uses": "{count} 次",
589
694
  "skillUsage.count": "载入 {count} 次 · {total} 个技能",
590
695
  "skillUsage.latestTag": "本轮",
696
+ "skillUsage.invokedGroup": "已引用 · {count}",
697
+ "skillUsage.availableGroup": "本会话可用 · {count}",
698
+ "skillUsage.availableCapped": "(可用清单共 {count} 条,列表已截断)",
591
699
  "settings.title": "概要侧栏",
592
700
  "settings.desc": "右侧栏概要 tab 的分区开关(只读展示)。",
593
701
  "settings.memorySlots": "记忆槽位分区",
@@ -612,6 +720,8 @@ window.__ModuleLoader__.load({
612
720
  "deliverables.empty": "No files changed in this turn",
613
721
  "deliverables.emptyHint": "Files written or edited successfully in the session appear here live.",
614
722
  "deliverables.history": "Earlier changes · {count}",
723
+ "deliverables.currentTurn": "This turn · {count}",
724
+ "deliverables.historyCapped": "(the session produced {total} files; the list is capped)",
615
725
  "deliverable.codeplanTag": "Plan",
616
726
  "section.memorySlots": "Memory",
617
727
  "slots.empty": "No active memory slots",
@@ -633,13 +743,19 @@ window.__ModuleLoader__.load({
633
743
  "recall.obsoleteWhy": "Declaring it obsolete retires the record (restorable) and tells the model next turn",
634
744
  "recall.strikeHint": "; an entry you mark obsolete stays listed, struck through (removed only when you clear the session)",
635
745
  "recall.supersededHidden": "{count} older recalls hidden — their text was replaced by a summary",
746
+ "recall.activeGroup": "Active recalls · {count}",
747
+ "recall.historyGroup": "Earlier recalls · {count}",
748
+ "recall.supersededTag": "replaced by summary",
636
749
  "recall.noBody": "(this frame carries no full body for this record)",
637
750
  "section.skillUsage": "Skill references",
638
751
  "skillUsage.empty": "No skills loaded in this session",
639
- "skillUsage.emptyHint": "Skills appear here as soon as the model loads one with the skill tool.",
752
+ "skillUsage.emptyHint": "Skills show up here once the model loads one with the `skill` tool, or you invoke one directly.",
640
753
  "skillUsage.uses": "{count}x",
641
754
  "skillUsage.count": "{count} loads - {total} skills",
642
755
  "skillUsage.latestTag": "this turn",
756
+ "skillUsage.invokedGroup": "Referenced · {count}",
757
+ "skillUsage.availableGroup": "Available this session · {count}",
758
+ "skillUsage.availableCapped": "({count} skills in the catalog; the list is capped)",
643
759
  "settings.title": "Brief sidebar",
644
760
  "settings.desc": "Section switches for the summary tab in the right sidebar (read-only views).",
645
761
  "settings.memorySlots": "Memory slots section",
@@ -664,6 +780,8 @@ window.__ModuleLoader__.load({
664
780
  "deliverables.empty": "このターンで変更されたファイルはありません",
665
781
  "deliverables.emptyHint": "セッションでファイルの書き込み・変更が成功すると、ここにリアルタイムで表示されます。",
666
782
  "deliverables.history": "以前の変更 · {count}",
783
+ "deliverables.currentTurn": "このターン · {count}",
784
+ "deliverables.historyCapped": "(セッション全体で {total} ファイル、一覧は上限で省略)",
667
785
  "deliverable.codeplanTag": "計画",
668
786
  "section.memorySlots": "メモリ",
669
787
  "slots.empty": "アクティブなメモリスロットはありません",
@@ -685,13 +803,19 @@ window.__ModuleLoader__.load({
685
803
  "recall.obsoleteWhy": "古いと宣言すると記録は退場(復元可)、次のターンでモデルに伝わります",
686
804
  "recall.strikeHint": ";古いと宣言した項目は取り消し線のまま一覧に保持されます(セッションをクリアすると消えます)",
687
805
  "recall.supersededHidden": "要約に置き換わった旧召回 {count} 件を非表示(本文はコンテキストにない)",
806
+ "recall.activeGroup": "アクティブな想起 · {count}",
807
+ "recall.historyGroup": "その他の履歴想起 · {count}",
808
+ "recall.supersededTag": "要約に置換済み",
688
809
  "recall.noBody": "このフレームには全文が含まれていない",
689
810
  "section.skillUsage": "スキル参照",
690
811
  "skillUsage.empty": "このセッションではスキルを読み込んでいません",
691
- "skillUsage.emptyHint": "モデルが skill ツールでスキルを読み込むと、ここにリアルタイムで表示されます。",
812
+ "skillUsage.emptyHint": "モデルが skill ツールで読み込むか、あなたがスキルを直接起動すると、ここにリアルタイムで表示されます。",
692
813
  "skillUsage.uses": "{count} 回",
693
814
  "skillUsage.count": "読み込み {count} 回 · スキル {total} 件",
694
815
  "skillUsage.latestTag": "このターン",
816
+ "skillUsage.invokedGroup": "参照済み · {count}",
817
+ "skillUsage.availableGroup": "このセッションで利用可能 · {count}",
818
+ "skillUsage.availableCapped": "(カタログは全 {count} 件、一覧は上限で省略)",
695
819
  "settings.title": "概要サイドバー",
696
820
  "settings.desc": "右サイドバー概要タブのセクション表示切り替え(読み取り専用)。",
697
821
  "settings.memorySlots": "メモリスロットセクション",
@@ -716,6 +840,8 @@ window.__ModuleLoader__.load({
716
840
  "deliverables.empty": "이번 턴에 변경된 파일이 없습니다",
717
841
  "deliverables.emptyHint": "세션에서 파일을 성공적으로 작성하거나 수정하면 여기에 실시간으로 표시됩니다.",
718
842
  "deliverables.history": "이전 변경 사항 · {count}",
843
+ "deliverables.currentTurn": "이번 턴 · {count}",
844
+ "deliverables.historyCapped": "(세션 전체 {total}개 파일, 목록은 잘림)",
719
845
  "deliverable.codeplanTag": "계획",
720
846
  "section.memorySlots": "메모리",
721
847
  "slots.empty": "활성화된 메모리 슬롯이 없습니다",
@@ -737,13 +863,19 @@ window.__ModuleLoader__.load({
737
863
  "recall.obsoleteWhy": "낡음으로 선언하면 기록이 퇴장하며(복원 가능), 다음 턴에서 모델에 알립니다",
738
864
  "recall.strikeHint": ";낡음으로 선언한 항목은 취소선 상태로 목록에 계속 표시됩니다(세션을 비우면 제거)",
739
865
  "recall.supersededHidden": "요약으로 대체된 이전 회수 {count}건 숨김(본문이 컨텍스트에 없음)",
866
+ "recall.activeGroup": "활성 회상 · {count}",
867
+ "recall.historyGroup": "나머지 이전 회상 · {count}",
868
+ "recall.supersededTag": "요약에 대체됨",
740
869
  "recall.noBody": "이 프레임에는 이 기록의 전문이 없습니다",
741
870
  "section.skillUsage": "스킬 참조",
742
871
  "skillUsage.empty": "이 세션에서 스킬을 불러오지 않았습니다",
743
- "skillUsage.emptyHint": "모델이 skill 도구로 스킬을 불러오면 여기에 즉시 표시됩니다.",
872
+ "skillUsage.emptyHint": "모델이 skill 도구로 불러오거나 당신이 스킬을 직접 실행하면 여기에 실시간으로 나타납니다.",
744
873
  "skillUsage.uses": "{count}회",
745
874
  "skillUsage.count": "불러오기 {count}회 · 스킬 {total}개",
746
875
  "skillUsage.latestTag": "이 턴",
876
+ "skillUsage.invokedGroup": "참조됨 · {count}",
877
+ "skillUsage.availableGroup": "이 세션에서 사용 가능 · {count}",
878
+ "skillUsage.availableCapped": "(카탈로그 전체 {count}개, 목록은 잘림)",
747
879
  "settings.title": "요약 사이드바",
748
880
  "settings.desc": "오른쪽 사이드바 요약 탭의 섹션 표시 전환(읽기 전용).",
749
881
  "settings.memorySlots": "메모리 슬롯 섹션",
@@ -768,6 +900,8 @@ window.__ModuleLoader__.load({
768
900
  "deliverables.empty": "Aucun fichier modifié à ce tour",
769
901
  "deliverables.emptyHint": "Les fichiers écrits ou modifiés dans la session apparaissent ici en direct.",
770
902
  "deliverables.history": "Modifications antérieures · {count}",
903
+ "deliverables.currentTurn": "Ce tour-ci · {count}",
904
+ "deliverables.historyCapped": "(la session a produit {total} fichiers ; la liste est tronquée)",
771
905
  "deliverable.codeplanTag": "Plan",
772
906
  "section.memorySlots": "Mémoire",
773
907
  "slots.empty": "Aucun emplacement mémoire actif",
@@ -789,13 +923,19 @@ window.__ModuleLoader__.load({
789
923
  "recall.obsoleteWhy": "Déclarer obsolète retire l’enregistrement (récupérable) et prévient le modèle au tour suivant",
790
924
  "recall.strikeHint": " ; une entrée déclarée obsolète reste listée, barrée (retirée uniquement quand vous videz la session)",
791
925
  "recall.supersededHidden": "{count} anciens rappels masqués — leur texte a été remplacé par un résumé",
926
+ "recall.activeGroup": "Rappels actifs · {count}",
927
+ "recall.historyGroup": "Rappels antérieurs · {count}",
928
+ "recall.supersededTag": "remplacé par le résumé",
792
929
  "recall.noBody": "(aucun texte complet pour cette entrée dans cette trame)",
793
930
  "section.skillUsage": "Références de compétences",
794
931
  "skillUsage.empty": "Aucune compétence chargée dans cette session",
795
- "skillUsage.emptyHint": "Les compétences apparaissent ici dès que le modèle en charge une avec l’outil skill.",
932
+ "skillUsage.emptyHint": "Les compétences apparaissent ici dès que le modèle en charge une via l’outil `skill`, ou quand vous en lancez une directement.",
796
933
  "skillUsage.uses": "{count}×",
797
934
  "skillUsage.count": "{count} chargements · {total} compétences",
798
935
  "skillUsage.latestTag": "ce tour",
936
+ "skillUsage.invokedGroup": "Référencées · {count}",
937
+ "skillUsage.availableGroup": "Disponibles dans cette session · {count}",
938
+ "skillUsage.availableCapped": "({count} compétences au catalogue ; la liste est tronquée)",
799
939
  "settings.title": "Barre latérale Résumé",
800
940
  "settings.desc": "Interrupteurs des sections de l’onglet Résumé de la barre latérale (lecture seule).",
801
941
  "settings.memorySlots": "Section des emplacements mémoire",
@@ -820,6 +960,8 @@ window.__ModuleLoader__.load({
820
960
  "deliverables.empty": "Keine Dateien in diesem Durchgang geändert",
821
961
  "deliverables.emptyHint": "In der Sitzung erfolgreich geschriebene oder geänderte Dateien erscheinen hier live.",
822
962
  "deliverables.history": "Frühere Änderungen · {count}",
963
+ "deliverables.currentTurn": "Dieser Durchlauf · {count}",
964
+ "deliverables.historyCapped": "(die Sitzung erzeugte {total} Dateien; die Liste ist gekürzt)",
823
965
  "deliverable.codeplanTag": "Plan",
824
966
  "section.memorySlots": "Gedächtnis",
825
967
  "slots.empty": "Keine aktiven Speicherplätze",
@@ -841,13 +983,19 @@ window.__ModuleLoader__.load({
841
983
  "recall.obsoleteWhy": "Als veraltet erklären versetzt den Eintrag in den Ruhestand (wiederherstellbar) und informiert das Modell in der nächsten Runde",
842
984
  "recall.strikeHint": "; ein als veraltet markierter Eintrag bleibt durchgestrichen in der Liste (erst beim Leeren der Sitzung entfernt)",
843
985
  "recall.supersededHidden": "{count} ältere Treffer ausgeblendet — ihr Text wurde durch eine Zusammenfassung ersetzt",
986
+ "recall.activeGroup": "Aktive Abrufe · {count}",
987
+ "recall.historyGroup": "Weitere Abrufe · {count}",
988
+ "recall.supersededTag": "durch Zusammenfassung ersetzt",
844
989
  "recall.noBody": "(dieser Rahmen enthält keinen vollständigen Text für diesen Eintrag)",
845
990
  "section.skillUsage": "Skill-Referenzen",
846
991
  "skillUsage.empty": "In dieser Sitzung wurden keine Skills geladen",
847
- "skillUsage.emptyHint": "Skills erscheinen hier, sobald das Modell einen über das skill-Werkzeug lädt.",
992
+ "skillUsage.emptyHint": "Skills erscheinen hier, sobald das Modell einen über das `skill`-Tool lädt oder du einen direkt aufrufst.",
848
993
  "skillUsage.uses": "{count}x",
849
994
  "skillUsage.count": "{count} Ladungen · {total} Skills",
850
995
  "skillUsage.latestTag": "diese Runde",
996
+ "skillUsage.invokedGroup": "Referenziert · {count}",
997
+ "skillUsage.availableGroup": "In dieser Sitzung verfügbar · {count}",
998
+ "skillUsage.availableCapped": "({count} Skills im Katalog; die Liste ist gekürzt)",
851
999
  "settings.title": "Übersicht-Seitenleiste",
852
1000
  "settings.desc": "Schalter für die Abschnitte des Übersicht-Tabs in der rechten Seitenleiste (schreibgeschützt).",
853
1001
  "settings.memorySlots": "Speicherplätze-Abschnitt",
@@ -872,6 +1020,8 @@ window.__ModuleLoader__.load({
872
1020
  "deliverables.empty": "Nessun file modificato in questo turno",
873
1021
  "deliverables.emptyHint": "I file scritti o modificati nella sessione appaiono qui in tempo reale.",
874
1022
  "deliverables.history": "Modifiche precedenti · {count}",
1023
+ "deliverables.currentTurn": "Questo turno · {count}",
1024
+ "deliverables.historyCapped": "(la sessione ha prodotto {total} file; l’elenco è troncato)",
875
1025
  "deliverable.codeplanTag": "Piano",
876
1026
  "section.memorySlots": "Memoria",
877
1027
  "slots.empty": "Nessuno slot di memoria attivo",
@@ -893,13 +1043,19 @@ window.__ModuleLoader__.load({
893
1043
  "recall.obsoleteWhy": "Dichiararlo obsoleto congeda il record (ripristinabile) e avvisa il modello al turno successivo",
894
1044
  "recall.strikeHint": "; una voce dichiarata obsoleta resta elencata, barrata (rimossa solo svuotando la sessione)",
895
1045
  "recall.supersededHidden": "{count} vecchi richiami nascosti — il testo è stato sostituito da un riassunto",
1046
+ "recall.activeGroup": "Richiami attivi · {count}",
1047
+ "recall.historyGroup": "Richiami precedenti · {count}",
1048
+ "recall.supersededTag": "sostituito dal riassunto",
896
1049
  "recall.noBody": "(questo frame non contiene il testo completo di questa voce)",
897
1050
  "section.skillUsage": "Riferimenti alle skill",
898
1051
  "skillUsage.empty": "Nessuna skill caricata in questa sessione",
899
- "skillUsage.emptyHint": "Le skill compaiono qui quando il modello ne carica una con il tool skill.",
1052
+ "skillUsage.emptyHint": "Le skill compaiono qui quando il modello ne carica una con il tool `skill` o quando ne avvii una direttamente.",
900
1053
  "skillUsage.uses": "{count}x",
901
1054
  "skillUsage.count": "{count} caricamenti · {total} skill",
902
1055
  "skillUsage.latestTag": "questo giro",
1056
+ "skillUsage.invokedGroup": "Referenziate · {count}",
1057
+ "skillUsage.availableGroup": "Disponibili in questa sessione · {count}",
1058
+ "skillUsage.availableCapped": "({count} skill nel catalogo; l’elenco è troncato)",
903
1059
  "settings.title": "Barra laterale Riepilogo",
904
1060
  "settings.desc": "Interruttori delle sezioni della scheda Riepilogo nella barra laterale destra (sola lettura).",
905
1061
  "settings.memorySlots": "Sezione slot di memoria",
@@ -924,6 +1080,8 @@ window.__ModuleLoader__.load({
924
1080
  "deliverables.empty": "За этот ход файлы не менялись",
925
1081
  "deliverables.emptyHint": "Успешно записанные или изменённые файлы появляются здесь в реальном времени.",
926
1082
  "deliverables.history": "Более ранние изменения · {count}",
1083
+ "deliverables.currentTurn": "Этот ход · {count}",
1084
+ "deliverables.historyCapped": "(в сессии всего {total} файлов; список усечён)",
927
1085
  "deliverable.codeplanTag": "План",
928
1086
  "section.memorySlots": "Память",
929
1087
  "slots.empty": "Активных слотов памяти нет",
@@ -945,13 +1103,19 @@ window.__ModuleLoader__.load({
945
1103
  "recall.obsoleteWhy": "Объявить устаревшим значит снимает запись восстанавлимо и сообщает модель на следующем ходе",
946
1104
  "recall.strikeHint": "; помеченная как устаревшая запись остаётся в списке, зачёркнутой (удаляется только при очистке сессии)",
947
1105
  "recall.supersededHidden": "Скрыто старых воспоминаний: {count} — их текст заменён кратким изложением",
1106
+ "recall.activeGroup": "Активные вызовы · {count}",
1107
+ "recall.historyGroup": "Прочие прежние вызовы · {count}",
1108
+ "recall.supersededTag": "заменено сводкой",
948
1109
  "recall.noBody": "В этом кадре нет полного текста этой записи",
949
1110
  "section.skillUsage": "Отсылки к скиллам",
950
1111
  "skillUsage.empty": "В этой сессии скиллы не загружались",
951
- "skillUsage.emptyHint": "Скиллы появятся здесь, как только модель загрузит их через инструмент skill.",
1112
+ "skillUsage.emptyHint": "Навыки появятся здесь, когда модель загрузит их через инструмент `skill` или вы вызовете навык напрямую.",
952
1113
  "skillUsage.uses": "{count} раз",
953
1114
  "skillUsage.count": "Загрузок: {count} · скиллов: {total}",
954
1115
  "skillUsage.latestTag": "этот ход",
1116
+ "skillUsage.invokedGroup": "Использованы · {count}",
1117
+ "skillUsage.availableGroup": "Доступны в этой сессии · {count}",
1118
+ "skillUsage.availableCapped": "({count} навыков в каталоге; список усечён)",
955
1119
  "settings.title": "Боковая панель «Сводка»",
956
1120
  "settings.desc": "Переключатели разделов вкладки «Сводка» на правой панели (только чтение).",
957
1121
  "settings.memorySlots": "Раздел слотов памяти",
@@ -976,6 +1140,8 @@ window.__ModuleLoader__.load({
976
1140
  "deliverables.empty": "Ningún archivo modificado en este turno",
977
1141
  "deliverables.emptyHint": "Los archivos escritos o editados en la sesión aparecen aquí en directo.",
978
1142
  "deliverables.history": "Cambios anteriores · {count}",
1143
+ "deliverables.currentTurn": "Este turno · {count}",
1144
+ "deliverables.historyCapped": "(la sesión produjo {total} archivos; la lista está truncada)",
979
1145
  "deliverable.codeplanTag": "Plan",
980
1146
  "section.memorySlots": "Memoria",
981
1147
  "slots.empty": "No hay ranuras de memoria activas",
@@ -997,13 +1163,19 @@ window.__ModuleLoader__.load({
997
1163
  "recall.obsoleteWhy": "Declararlo obsoleto retira el registro (recuperable) y avisa al modelo en el turno siguiente",
998
1164
  "recall.strikeHint": "; una entrada marcada como obsoleta sigue en la lista, tachada (se retira solo al vaciar la sesión)",
999
1165
  "recall.supersededHidden": "{count} recuerdos antiguos ocultos — su texto fue reemplazado por un resumen",
1166
+ "recall.activeGroup": "Recuerdos activos · {count}",
1167
+ "recall.historyGroup": "Recuerdos anteriores · {count}",
1168
+ "recall.supersededTag": "reemplazado por el resumen",
1000
1169
  "recall.noBody": "(este fotograma no trae el texto completo de este registro)",
1001
1170
  "section.skillUsage": "Referencias de skills",
1002
1171
  "skillUsage.empty": "Esta sesión no ha cargado ningún skill",
1003
- "skillUsage.emptyHint": "Los skills aparecerán aquí en cuanto el modelo cargue uno con la herramienta skill.",
1172
+ "skillUsage.emptyHint": "Las skills aparecen aquí cuando el modelo carga una con la herramienta `skill` o cuando invocas una directamente.",
1004
1173
  "skillUsage.uses": "{count}x",
1005
1174
  "skillUsage.count": "{count} cargas · {total} skills",
1006
1175
  "skillUsage.latestTag": "este turno",
1176
+ "skillUsage.invokedGroup": "Referenciadas · {count}",
1177
+ "skillUsage.availableGroup": "Disponibles en esta sesión · {count}",
1178
+ "skillUsage.availableCapped": "({count} skills en el catálogo; la lista está truncada)",
1007
1179
  "settings.title": "Barra lateral Resumen",
1008
1180
  "settings.desc": "Interruptores de las secciones de la pestaña Resumen en la barra lateral derecha (solo lectura).",
1009
1181
  "settings.memorySlots": "Sección de ranuras de memoria",
@@ -1022,6 +1194,13 @@ window.__ModuleLoader__.load({
1022
1194
  function expandCount(template, count) {
1023
1195
  return template.replace("{count}", String(count));
1024
1196
  }
1197
+ /**
1198
+ * Fill a `{total}` placeholder — the counter that says how many there really
1199
+ * are, as opposed to how many the (capped) list shows.
1200
+ */
1201
+ function expandTotal(template, total) {
1202
+ return template.replace("{total}", String(total));
1203
+ }
1025
1204
  //#endregion
1026
1205
  //#region src/client/summary/DeliverablesSection.tsx
1027
1206
  /**
@@ -1066,26 +1245,6 @@ window.__ModuleLoader__.load({
1066
1245
  gap: 8,
1067
1246
  padding: "6px 12px"
1068
1247
  };
1069
- /** 折叠区开关行:与文件行同宽,tertiary 强调,整行可点。 */
1070
- const HISTORY_TOGGLE_STYLE = {
1071
- background: "none",
1072
- border: "none",
1073
- font: "inherit",
1074
- fontSize: 12,
1075
- color: "var(--dsw-alias-label-tertiary)",
1076
- cursor: "pointer",
1077
- display: "flex",
1078
- alignItems: "center",
1079
- gap: 4,
1080
- padding: "6px 12px",
1081
- textAlign: "left",
1082
- width: "calc(100% - 24px)"
1083
- };
1084
- const CHEVRON_STYLE$1 = (open) => ({
1085
- flexShrink: 0,
1086
- transition: "transform 0.16s",
1087
- transform: open ? "rotate(180deg)" : "none"
1088
- });
1089
1248
  const PATH_STYLE = {
1090
1249
  minWidth: 0,
1091
1250
  overflowWrap: "anywhere",
@@ -1142,8 +1301,9 @@ window.__ModuleLoader__.load({
1142
1301
  * The deliverables section. The subscription is unconditional (a plain
1143
1302
  * listener, not IO).
1144
1303
  *
1145
- * 分层:活跃文件(本回合 latest)直接列表;全会话更早改动折叠在开关行后面
1146
- * (与活跃文件按归一化路径去重),展开后是与活跃区相同的可点击文件行。
1304
+ * 分层:本回合改动(latest)与全会话更早改动分成两组各自计数——前者直列,后者
1305
+ * 折叠在开关行后面(与活跃文件按归一化路径去重),展开后是与活跃区相同的可点击
1306
+ * 文件行。列表有上限时,开关行说折叠区条数、附注说会话真数,两个数不混为一谈。
1147
1307
  * @param props - translation, client context, session scope.
1148
1308
  */
1149
1309
  function DeliverablesSection(props) {
@@ -1172,32 +1332,25 @@ window.__ModuleLoader__.load({
1172
1332
  return (0, react.createElement)("div", {
1173
1333
  style: SECTION_STYLE$3,
1174
1334
  "data-dsh-brief-sidebar": "deliverables-section"
1175
- }, (0, react.createElement)("div", { style: HEADER_STYLE$4 }, t("section.deliverables")), (0, react.createElement)("ul", { style: LIST_STYLE$3 }, latestPaths.map((path) => (0, react.createElement)(PathRow, {
1335
+ }, (0, react.createElement)("div", { style: HEADER_STYLE$4 }, t("section.deliverables")), latestPaths.length > 0 && (0, react.createElement)(GroupHeader, {
1336
+ text: expandCount(t("deliverables.currentTurn"), latestPaths.length),
1337
+ marker: "deliverables-current-group"
1338
+ }), (0, react.createElement)("ul", { style: LIST_STYLE$3 }, latestPaths.map((path) => (0, react.createElement)(PathRow, {
1176
1339
  key: path,
1177
1340
  path,
1178
1341
  t,
1179
1342
  open
1180
- }))), history.length > 0 && (0, react.createElement)("button", {
1181
- type: "button",
1182
- "aria-expanded": historyOpen,
1183
- style: HISTORY_TOGGLE_STYLE,
1184
- onClick: () => {
1343
+ }))), history.length > 0 && (0, react.createElement)(FoldToggle, {
1344
+ label: expandCount(t("deliverables.history"), history.length),
1345
+ open: historyOpen,
1346
+ marker: "deliverables-history-toggle",
1347
+ onToggle: () => {
1185
1348
  setHistoryOpen((current) => !current);
1186
1349
  }
1187
- }, expandCount(t("deliverables.history"), history.length), (0, react.createElement)("svg", {
1188
- width: 10,
1189
- height: 10,
1190
- viewBox: "0 0 16 16",
1191
- "aria-hidden": true,
1192
- style: CHEVRON_STYLE$1(historyOpen)
1193
- }, (0, react.createElement)("path", {
1194
- d: "M4 6l4 4 4-4",
1195
- fill: "none",
1196
- stroke: "currentColor",
1197
- strokeWidth: 1.5,
1198
- strokeLinecap: "round",
1199
- strokeLinejoin: "round"
1200
- }))), historyOpen && (0, react.createElement)("ul", { style: LIST_STYLE$3 }, history.map((path) => (0, react.createElement)(PathRow, {
1350
+ }), history.length > 0 && view.sessionTotal > view.sessionPaths.length && (0, react.createElement)(GroupCaption, {
1351
+ text: expandTotal(t("deliverables.historyCapped"), view.sessionTotal),
1352
+ marker: "deliverables-history-capped"
1353
+ }), historyOpen && (0, react.createElement)("ul", { style: LIST_STYLE$3 }, history.map((path) => (0, react.createElement)(PathRow, {
1201
1354
  key: path,
1202
1355
  path,
1203
1356
  t,
@@ -1236,6 +1389,18 @@ window.__ModuleLoader__.load({
1236
1389
  };
1237
1390
  }
1238
1391
  /**
1392
+ * The available-skill list of a frame, or `[]` when the frame carries none.
1393
+ *
1394
+ * Absent-by-age is the important case: a host half older than this reader
1395
+ * publishes no `available` field at all, and that must NOT void the whole view
1396
+ * — the session's references are still true. Only a drifted (non-array) value
1397
+ * reads as "nothing known", never as "nothing available".
1398
+ */
1399
+ function readAvailable(value) {
1400
+ if (!Array.isArray(value)) return [];
1401
+ return value.filter((n) => typeof n === "string" && n.length > 0);
1402
+ }
1403
+ /**
1239
1404
  * Narrow a raw projection value into a skill-usage view.
1240
1405
  *
1241
1406
  * @param value - the raw `unknown` snapshot of the `dshSummarySkillUsage` face.
@@ -1251,14 +1416,33 @@ window.__ModuleLoader__.load({
1251
1416
  const narrowed = readEntry(entry);
1252
1417
  if (narrowed !== void 0) session.push(narrowed);
1253
1418
  }
1419
+ const available = readAvailable(raw["available"]);
1420
+ const availableCount = available.length === 0 ? 0 : isCounter$2(raw["availableCount"]) ? raw["availableCount"] : available.length;
1254
1421
  return {
1255
1422
  latest: readLatest(raw["latest"]),
1256
1423
  session,
1257
1424
  sessionTotal: raw["sessionTotal"],
1258
- callTotal: raw["callTotal"]
1425
+ callTotal: raw["callTotal"],
1426
+ available,
1427
+ availableCount
1259
1428
  };
1260
1429
  }
1261
1430
  /**
1431
+ * The available list minus the names already shown as referenced.
1432
+ *
1433
+ * One skill must not occupy a row in both groups: the reference row is the
1434
+ * stronger fact, and a duplicate under "available" would read as "the model
1435
+ * had a choice it didn't make".
1436
+ *
1437
+ * @param available - the session's current catalog names, in catalog order.
1438
+ * @param referenced - names the fold counted as loaded or invoked.
1439
+ * @returns the remaining catalog names, order preserved.
1440
+ */
1441
+ function availableExcept(available, referenced) {
1442
+ const seen = new Set(referenced);
1443
+ return available.filter((name) => !seen.has(name));
1444
+ }
1445
+ /**
1262
1446
  * Fill both placeholders of a template. `expandCount` only speaks `{count}`, and
1263
1447
  * this section's footer carries a second number on purpose: the capped list
1264
1448
  * needs the truthful distinct total next to the load count.
@@ -1278,15 +1462,23 @@ window.__ModuleLoader__.load({
1278
1462
  * part of the summary tab.
1279
1463
  *
1280
1464
  * Where `MemoryRecallSection` answers "what memories did the model see", this
1281
- * answers "which instruction packs did it pull" — the skills this session
1282
- * loaded through the host's `skill` tool, with how often and when.
1465
+ * answers "which instruction packs entered the context, and which ones were on
1466
+ * the menu". Two groups, deliberately not merged:
1467
+ *
1468
+ * - **已引用** — the skill's instructions reached the conversation, either
1469
+ * because the model called the `skill` tool or because the user invoked it
1470
+ * directly (the host then injects `<skill_content>` and tells the model not
1471
+ * to call the tool — reading only the tool would miss over half of those
1472
+ * sessions, measured on 250 real ones).
1473
+ * - **本会话可用** — the session's current catalog. Available is NOT used: the
1474
+ * model may never touch any of these, so it is collapsed behind a counted
1475
+ * toggle and never mixed into the reference rows.
1283
1476
  *
1284
1477
  * Like the deliverables section this is an OPTIONAL capability on both sides:
1285
1478
  * no projection registry (or a host half that never registered the unit) means
1286
1479
  * the client reads capability absence and the section hides. No settings switch
1287
1480
  * gates it either — the list is a read-only fact about the session, not a
1288
- * preference, and a section that only ever shows what already happened costs
1289
- * nothing to leave on.
1481
+ * preference.
1290
1482
  *
1291
1483
  * Two contracts this row honours, both learned on the recall section:
1292
1484
  * - **no native `title` attribute** — it paints an unskinable tooltip that
@@ -1361,24 +1553,40 @@ window.__ModuleLoader__.load({
1361
1553
  */
1362
1554
  function SkillUsageSection(props) {
1363
1555
  const { t, ctx, scope } = props;
1556
+ const [availableOpen, setAvailableOpen] = (0, react.useState)(false);
1364
1557
  const view = readSkillUsage(useProjectionValue(ctx, scope?.sessionId, SKILL_USAGE_KEY));
1365
1558
  if (view === void 0) return null;
1366
- if (view.session.length === 0) return (0, react.createElement)("div", {
1367
- style: SECTION_STYLE$2,
1368
- "data-dsh-brief-sidebar": "skill-usage-section"
1369
- }, (0, react.createElement)("div", { style: HEADER_STYLE$3 }, t("section.skillUsage")), (0, react.createElement)("div", { style: EMPTY_STYLE$2 }, (0, react.createElement)("div", { style: {
1370
- marginBottom: 6,
1371
- color: "var(--dsw-alias-label-secondary)"
1372
- } }, t("skillUsage.empty")), (0, react.createElement)("div", null, t("skillUsage.emptyHint"))));
1559
+ const referenced = view.session.map((entry) => entry.name);
1560
+ const rest = availableExcept(view.available, referenced);
1373
1561
  const latestNames = view.latest?.names ?? [];
1374
1562
  return (0, react.createElement)("div", {
1375
1563
  style: SECTION_STYLE$2,
1376
1564
  "data-dsh-brief-sidebar": "skill-usage-section"
1377
- }, (0, react.createElement)("div", { style: HEADER_STYLE$3 }, t("section.skillUsage")), (0, react.createElement)("ul", { style: LIST_STYLE$2 }, view.session.map((entry) => (0, react.createElement)("li", {
1565
+ }, (0, react.createElement)("div", { style: HEADER_STYLE$3 }, t("section.skillUsage")), view.session.length === 0 && (0, react.createElement)("div", { style: EMPTY_STYLE$2 }, (0, react.createElement)("div", { style: {
1566
+ marginBottom: 6,
1567
+ color: "var(--dsw-alias-label-secondary)"
1568
+ } }, t("skillUsage.empty")), (0, react.createElement)("div", null, t("skillUsage.emptyHint"))), view.session.length > 0 && (0, react.createElement)(GroupHeader, {
1569
+ text: expandCount(t("skillUsage.invokedGroup"), view.session.length),
1570
+ marker: "skill-usage-invoked-group"
1571
+ }), (0, react.createElement)("ul", { style: LIST_STYLE$2 }, view.session.map((entry) => (0, react.createElement)("li", {
1378
1572
  key: entry.name,
1379
1573
  style: ROW_STYLE$3,
1380
1574
  "data-dsh-brief-sidebar": "skill-usage-row"
1381
- }, (0, react.createElement)("span", { style: NAME_STYLE$1 }, entry.name), (0, react.createElement)("span", { style: COUNT_STYLE }, expandPair(t("skillUsage.uses"), entry.count, entry.count)), latestNames.includes(entry.name) && (0, react.createElement)("span", { style: TAG_STYLE }, t("skillUsage.latestTag"))))), (0, react.createElement)("div", { style: FOOTER_STYLE$2 }, expandPair(t("skillUsage.count"), view.callTotal, view.sessionTotal)));
1575
+ }, (0, react.createElement)("span", { style: NAME_STYLE$1 }, entry.name), (0, react.createElement)("span", { style: COUNT_STYLE }, expandPair(t("skillUsage.uses"), entry.count, entry.count)), latestNames.includes(entry.name) && (0, react.createElement)("span", { style: TAG_STYLE }, t("skillUsage.latestTag"))))), rest.length > 0 && (0, react.createElement)(FoldToggle, {
1576
+ label: expandCount(t("skillUsage.availableGroup"), rest.length),
1577
+ open: availableOpen,
1578
+ marker: "skill-usage-available-toggle",
1579
+ onToggle: () => {
1580
+ setAvailableOpen((current) => !current);
1581
+ }
1582
+ }), rest.length > 0 && view.availableCount > view.available.length && (0, react.createElement)(GroupCaption, {
1583
+ text: expandCount(t("skillUsage.availableCapped"), view.availableCount),
1584
+ marker: "skill-usage-available-capped"
1585
+ }), availableOpen && (0, react.createElement)("ul", { style: LIST_STYLE$2 }, rest.map((name) => (0, react.createElement)("li", {
1586
+ key: name,
1587
+ style: ROW_STYLE$3,
1588
+ "data-dsh-brief-sidebar": "skill-usage-available-row"
1589
+ }, (0, react.createElement)("span", { style: NAME_STYLE$1 }, name)))), view.session.length > 0 && (0, react.createElement)("div", { style: FOOTER_STYLE$2 }, expandPair(t("skillUsage.count"), view.callTotal, view.sessionTotal)));
1382
1590
  }
1383
1591
  //#endregion
1384
1592
  //#region src/client/summary/memory-slots.ts
@@ -2316,7 +2524,7 @@ window.__ModuleLoader__.load({
2316
2524
  * has already retired).
2317
2525
  */
2318
2526
  function RecallRow(props) {
2319
- const { item, selected, stale, mark, error, t } = props;
2527
+ const { item, selected, stale, wasSuperseded, mark, error, t } = props;
2320
2528
  const scenario = item.scenario === void 0 ? void 0 : item.scenario.join(" · ");
2321
2529
  const markText = mark === void 0 ? void 0 : mark === -1 ? t("recall.obsoleted") : expandCount(t("recall.rated"), mark);
2322
2530
  const staleText = stale && mark !== -1 ? t("recall.obsoleted") : void 0;
@@ -2344,7 +2552,10 @@ window.__ModuleLoader__.load({
2344
2552
  } }, (0, react.createElement)("span", { style: titleStyle }, item.title), scenario !== void 0 && (0, react.createElement)("p", { style: stale ? {
2345
2553
  ...SCENARIO_STYLE,
2346
2554
  ...STRIKE_STYLE
2347
- } : SCENARIO_STYLE }, scenario), staleText !== void 0 && (0, react.createElement)("span", { style: MARK_STYLE }, staleText), markText !== void 0 && (0, react.createElement)("span", { style: MARK_STYLE }, markText), error !== void 0 && (0, react.createElement)("span", { style: ERROR_STYLE }, `${t("recall.failed")}${error}`), selected && !stale && props.rating && (0, react.createElement)(RatingStrip, {
2555
+ } : SCENARIO_STYLE }, scenario), staleText !== void 0 && (0, react.createElement)("span", { style: MARK_STYLE }, staleText), wasSuperseded && (0, react.createElement)("span", {
2556
+ style: TYPE_STYLE,
2557
+ "data-dsh-brief-sidebar": "recall-superseded-tag"
2558
+ }, t("recall.supersededTag")), markText !== void 0 && (0, react.createElement)("span", { style: MARK_STYLE }, markText), error !== void 0 && (0, react.createElement)("span", { style: ERROR_STYLE }, `${t("recall.failed")}${error}`), selected && !stale && props.rating && (0, react.createElement)(RatingStrip, {
2348
2559
  current: mark,
2349
2560
  pending: props.pending,
2350
2561
  armed: props.armed,
@@ -2375,6 +2586,7 @@ window.__ModuleLoader__.load({
2375
2586
  const [errors, setErrors] = (0, react.useState)({});
2376
2587
  const [armed, setArmed] = (0, react.useState)(false);
2377
2588
  const [writeAbsent, setWriteAbsent] = (0, react.useState)(false);
2589
+ const [historyOpen, setHistoryOpen] = (0, react.useState)(false);
2378
2590
  const show = useConfigFlag(ctx, resolveShowMemoryRecall);
2379
2591
  const view = readRecall(useProjectionValue(ctx, scope?.sessionId, MEMORY_RECALL_KEY));
2380
2592
  const sessionId = scope?.sessionId ?? "";
@@ -2454,22 +2666,50 @@ window.__ModuleLoader__.load({
2454
2666
  if (view === void 0) return null;
2455
2667
  const isStale = (item) => item.retired === true || staleIds.includes(item.id);
2456
2668
  const rows = view.items.filter((item) => item.superseded !== true || item.retired === true);
2457
- const hidden = view.items.length - rows.length;
2669
+ const historyRows = view.items.filter((item) => item.superseded === true && item.retired !== true);
2670
+ const hidden = historyRows.length;
2458
2671
  if (rows.length === 0) return (0, react.createElement)("div", {
2459
2672
  style: SECTION_STYLE,
2460
2673
  "data-dsh-brief-sidebar": "memory-recall-section"
2461
2674
  }, (0, react.createElement)("div", { style: HEADER_STYLE$1 }, t("section.memoryRecall")), (0, react.createElement)("div", {
2462
2675
  style: EMPTY_STYLE,
2463
2676
  ...hidden > 0 ? { "data-dsh-brief-sidebar": "recall-superseded-note" } : {}
2464
- }, hidden > 0 ? expandCount(t("recall.supersededHidden"), hidden) : t("recall.empty")));
2677
+ }, hidden > 0 ? expandCount(t("recall.supersededHidden"), hidden) : t("recall.empty")), historyRows.length > 0 && (0, react.createElement)(FoldToggle, {
2678
+ label: expandCount(t("recall.historyGroup"), historyRows.length),
2679
+ open: historyOpen,
2680
+ marker: "recall-history-toggle",
2681
+ onToggle: () => {
2682
+ setHistoryOpen((current) => !current);
2683
+ }
2684
+ }), historyOpen && (0, react.createElement)("ul", { style: LIST_STYLE }, historyRows.map((item) => (0, react.createElement)(RecallRow, {
2685
+ key: item.id,
2686
+ item,
2687
+ selected: false,
2688
+ stale: isStale(item),
2689
+ wasSuperseded: true,
2690
+ pending: false,
2691
+ armed: false,
2692
+ mark: void 0,
2693
+ error: void 0,
2694
+ rating: false,
2695
+ t,
2696
+ onSelect: () => {},
2697
+ onScore: () => {},
2698
+ onEnter: () => {},
2699
+ onLeave: () => {}
2700
+ }))));
2465
2701
  return (0, react.createElement)("div", {
2466
2702
  style: SECTION_STYLE,
2467
2703
  "data-dsh-brief-sidebar": "memory-recall-section"
2468
- }, (0, react.createElement)("div", { style: HEADER_STYLE$1 }, t("section.memoryRecall")), rating && (0, react.createElement)("div", { style: HINT_STYLE$1 }, `${t("recall.rateHint")}${t("recall.strikeHint")}`), (0, react.createElement)("ul", { style: LIST_STYLE }, rows.map((item) => (0, react.createElement)(RecallRow, {
2704
+ }, (0, react.createElement)("div", { style: HEADER_STYLE$1 }, t("section.memoryRecall")), rating && (0, react.createElement)("div", { style: HINT_STYLE$1 }, `${t("recall.rateHint")}${t("recall.strikeHint")}`), rows.length > 0 && (0, react.createElement)(GroupHeader, {
2705
+ text: expandCount(t("recall.activeGroup"), rows.length),
2706
+ marker: "recall-active-group"
2707
+ }), (0, react.createElement)("ul", { style: LIST_STYLE }, rows.map((item) => (0, react.createElement)(RecallRow, {
2469
2708
  key: item.id,
2470
2709
  item,
2471
2710
  selected: selectedId === item.id,
2472
2711
  stale: isStale(item),
2712
+ wasSuperseded: item.superseded === true,
2473
2713
  pending: pendingId === item.id,
2474
2714
  armed: armed && selectedId === item.id,
2475
2715
  mark: marks[item.id] ?? item.rating,
@@ -2486,6 +2726,29 @@ window.__ModuleLoader__.load({
2486
2726
  onEnter(item.id, el);
2487
2727
  },
2488
2728
  onLeave
2729
+ }))), historyRows.length > 0 && (0, react.createElement)(FoldToggle, {
2730
+ label: expandCount(t("recall.historyGroup"), historyRows.length),
2731
+ open: historyOpen,
2732
+ marker: "recall-history-toggle",
2733
+ onToggle: () => {
2734
+ setHistoryOpen((current) => !current);
2735
+ }
2736
+ }), historyOpen && (0, react.createElement)("ul", { style: LIST_STYLE }, historyRows.map((item) => (0, react.createElement)(RecallRow, {
2737
+ key: item.id,
2738
+ item,
2739
+ selected: false,
2740
+ stale: isStale(item),
2741
+ wasSuperseded: true,
2742
+ pending: false,
2743
+ armed: false,
2744
+ mark: void 0,
2745
+ error: void 0,
2746
+ rating: false,
2747
+ t,
2748
+ onSelect: () => {},
2749
+ onScore: () => {},
2750
+ onEnter: () => {},
2751
+ onLeave: () => {}
2489
2752
  }))), (0, react.createElement)("div", { style: FOOTER_STYLE }, expandCount(t("recall.count"), view.count), hidden > 0 && (0, react.createElement)("div", { "data-dsh-brief-sidebar": "recall-superseded-note" }, expandCount(t("recall.supersededHidden"), hidden))), hover !== void 0 && typeof window !== "undefined" && (() => {
2490
2753
  const item = view.items.find((i) => i.id === hover.id);
2491
2754
  if (item === void 0) return null;