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/dsh.plugin.json +1 -1
- package/lib/client.js +333 -70
- package/lib/client.js.map +1 -1
- package/lib/index.mjs +78 -28
- package/lib/index.mjs.map +1 -1
- package/lib/types/client/locales.d.ts +13 -0
- package/lib/types/client/summary/DeliverablesSection.d.ts +3 -2
- package/lib/types/client/summary/FoldToggle.d.ts +27 -0
- package/lib/types/client/summary/skill-usage.d.ts +12 -0
- package/lib/types/projection/keys.d.ts +11 -4
- package/lib/types/projection/skill-usage-fold.d.ts +45 -19
- package/package.json +1 -1
- package/src/client/locales.ts +89 -9
- package/src/client/summary/DeliverablesSection.tsx +21 -47
- package/src/client/summary/FoldToggle.tsx +114 -0
- package/src/client/summary/MemoryRecallSection.tsx +79 -2
- package/src/client/summary/SkillUsageSection.tsx +51 -20
- package/src/client/summary/skill-usage.ts +40 -1
- package/src/projection/keys.ts +11 -4
- package/src/projection/register.ts +12 -2
- package/src/projection/skill-usage-fold.ts +108 -41
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
|
|
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
|
|
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
|
|
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": "
|
|
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": "
|
|
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
|
-
*
|
|
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")),
|
|
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)(
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
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
|
-
}
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
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
|
|
1282
|
-
*
|
|
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
|
|
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
|
-
|
|
1367
|
-
|
|
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)("
|
|
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)(
|
|
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),
|
|
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
|
|
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")}`),
|
|
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;
|