dsh-prime-memory 0.18.2 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/CHANGELOG.en.md +21 -0
  2. package/CHANGELOG.ja.md +21 -0
  3. package/CHANGELOG.ko.md +21 -0
  4. package/CHANGELOG.md +21 -0
  5. package/INSTALL.en.md +1 -1
  6. package/INSTALL.ja.md +1 -1
  7. package/INSTALL.ko.md +1 -1
  8. package/INSTALL.md +1 -1
  9. package/README.en.md +7 -2
  10. package/README.ja.md +7 -2
  11. package/README.ko.md +7 -2
  12. package/README.md +7 -2
  13. package/cordis.patch.yml +6 -0
  14. package/dist/client.js +36 -9
  15. package/dist/config.d.ts +37 -0
  16. package/dist/config.js +7 -0
  17. package/dist/contract.d.ts +46 -0
  18. package/dist/hooks/capture-recovery.d.ts +59 -0
  19. package/dist/hooks/capture-recovery.js +88 -0
  20. package/dist/hooks/capture.js +110 -1
  21. package/dist/hooks/recall-ack.d.ts +48 -0
  22. package/dist/hooks/recall-ack.js +79 -0
  23. package/dist/hooks/recall.d.ts +19 -0
  24. package/dist/hooks/recall.js +116 -7
  25. package/dist/index.d.ts +22 -0
  26. package/dist/index.js +4 -0
  27. package/dist/pipeline/l1.d.ts +4 -0
  28. package/dist/pipeline/l1.js +9 -2
  29. package/dist/pipeline/reconcile.js +4 -0
  30. package/dist/pipeline/runner.js +62 -0
  31. package/dist/prompts/boundary.d.ts +17 -0
  32. package/dist/prompts/boundary.js +20 -0
  33. package/dist/prompts/graph-projection.js +4 -1
  34. package/dist/prompts/l1-dedup.d.ts +3 -3
  35. package/dist/prompts/l1-dedup.js +9 -1
  36. package/dist/prompts/l1-extraction.d.ts +3 -3
  37. package/dist/prompts/l1-extraction.js +12 -0
  38. package/dist/prompts/persona.js +6 -0
  39. package/dist/prompts/scene.js +7 -1
  40. package/dist/stats.js +9 -0
  41. package/dist/store/l0.d.ts +4 -0
  42. package/dist/store/l0.js +8 -0
  43. package/dist/store/sqlite.d.ts +12 -0
  44. package/dist/store/sqlite.js +37 -0
  45. package/dist/store/trace.d.ts +39 -0
  46. package/dist/store/trace.js +149 -0
  47. package/dist/tools/index.js +25 -1
  48. package/dist/util/redact.d.ts +27 -0
  49. package/dist/util/redact.js +228 -0
  50. package/dsh.plugin.json +2 -2
  51. package/package.json +23 -22
package/CHANGELOG.en.md CHANGED
@@ -7,6 +7,13 @@
7
7
 
8
8
  This file covers the **0.12.0** release notes and the current **unreleased** changes in English. For the full history, see [CHANGELOG.md](./CHANGELOG.md) (Chinese).
9
9
 
10
+ ## [0.19.0] — 2026-09-29
11
+
12
+ ### Changed
13
+
14
+ - **DSH 0.2.0 adaptation (compat/0.2.0)**: peerDependencies and engines.dsh (package.json + dsh.plugin.json) moved wholesale to `>=0.2.0-rc.1 <0.2.1-0` (single-range replacement; the 0.1.7 line remains served by the compat/0.1.7 branch); the 9 dsh-* devDependencies re-pinned 0.1.1-rc.2 → 0.2.0-rc.1 and the type-only dependency `@deepseek-ai/dsh-compaction` added. Code-level adaptation to 0.2.0 host API drift: the `agent/session-start` event merged into `agent/created` (listeners made async to satisfy the serial contract); session event reads switched from `session.events` to `session.snapshotEvents()` (host deprecated synchronous full reads; degradation chain preserved); test stubs updated (projection cursor offset semantics).
15
+ - **Release metadata**: version 0.18.4 → 0.19.0; publishConfig.tag `dsh-0.1.7` → `dsh-0.2.0`; dsh.plugin.json version → `0.19.0-dsh0.2.0.1`.
16
+
10
17
  ## [0.17.0-dsh0.1.7.1] — 2026-09-25
11
18
 
12
19
  > First release of the **host 0.1.7** compatibility line (dist-tag `dsh-0.1.7`, based on main @ 85d9b05). **Requires host ≥0.1.7-rc.1**; hosts 0.1.5 / 0.1.6 should stay on the `dsh-0.1.5` tag. Contains everything from main plus the adaptation below.
@@ -22,6 +29,20 @@ This file covers the **0.12.0** release notes and the current **unreleased** cha
22
29
  - **Silent first-write loss regression**: lock files are created before the write; when the target's parent directory did not exist yet, `open('wx')` failed with ENOENT and stores swallowed it as a warn. `rmwJson` now `ensureDir`s before acquiring the lock (included from the main line).
23
30
  - Also includes everything from the main line: file-layer hardening (atomic writes / read-side classification / version fail-closed / file locking / path safety — see [Unreleased] entries).
24
31
 
32
+ ## [0.18.4] — 2026-09-28
33
+
34
+ ### Added
35
+
36
+ - **Crash recovery (§A)**: a turn interrupted by a host crash was previously lost forever with the in-memory capture buffer (the resume cold-start floor discarded all history). On `agent/session-start(resume)` the plugin now reconciles against the host's persisted event log: with the max L0-persisted turn as watermark it recovers complete trailing turns (cap 2; crash-orphaned turns are closed by the host with `turn/end{reason:'interrupted'}` — 98 instances found on this machine). Idempotency = watermark + per-turn existence check; when host read services are unavailable it degrades stepwise (`sessionQuery.readSession` → `sessionPersistence.readFrom` → current behavior + one-time notice), always fail-open and never blocking session startup.
37
+ - **Payload redaction (§C, `capture.redactSecrets`, default on)**: the capture boundary replaces 8 classes of secrets (PEM keys / Authorization headers / Bearer & JWT / Cookies / vendor API key shapes / emails / ≥9-digit numbers with dates excluded / high-entropy IDs) with typed `[REDACTED:<KIND>]` placeholders — a single choke point covering L0 JSONL, L0 SQLite, distill input and manual `memory_add`/`memory_import`. Safe values (`example` / `$VAR` / `${{…}}`) are kept; placeholders preserve the category so keyword search still matches. Note: once enabled the original L0 text is changed (rebuild cannot recover it); `false` restores plaintext.
38
+ - **Distill prompt anti-injection (§B)**: all six distill prompt files (L1 extract ×3 / L1 dedup ×3 / L2 scene ×2 / L3 persona ×2 / graph projection / reconcile) now carry a "content boundary (anti-injection)" declaration plus data-delimiter notes — conversation text, existing memory pools and scene contents embedded in prompts are data, not instructions, so instruction-like text in conversations can no longer hijack distillation, dedup or adjudication. Decision vocabularies and output contracts are unchanged.
39
+
40
+ ### Improved
41
+
42
+ - **Injection acknowledgment (§D)**: recall injection no longer marks the dedupe store on return; it is now a two-phase "pending → log receipt" — the mark happens only when the host actually writes the injected message into the session log (`user/message` with the `plugin:memory` signature and stable id). Injections overwritten or cancelled no longer suppress memories (they can be re-injected next turn); after 5 minutes without a receipt the mark is applied anyway (guards against an ack-chain failure disabling dedupe), unconfirmed-expired entries are dropped.
43
+ - **Compaction-aware re-injection (§E)**: after `compaction/end` (no error), the session's next turn performs one targeted enhanced recall — dedupe suppression is skipped (compaction evicted prior injections from context), the persona section is re-delivered immediately, and the occupancy ledger resets; consumed on use. The existing compact/clear full reset remains as a fallback; both paths are idempotent.
44
+ - **Structured trace (§F, `trace.*`)**: recall and distill events are persisted as daily JSONL under `<dataDir>/trace/` (14-day retention by default; 5 MB per-day cap with a marker). Recall events carry a query fingerprint (metadata-only by default: length + sha256; `trace.captureContent` stores the text ≤200 chars), hit/injected ids, scores, latency and four outcomes; distill events carry runId, the six-value decision aggregation (same source as `l1_receipts`, cross-auditable), latency and success. New `dsh-memory/trace-tail` endpoint; the Log tab gains a three-source switch (system log / recall trace / distill trace).
45
+
25
46
  ## [0.18.2] — 2026-09-27
26
47
 
27
48
  ### Fixed
package/CHANGELOG.ja.md CHANGED
@@ -9,6 +9,27 @@
9
9
 
10
10
  本ファイルは **0.12.0** リリースノートと現在の**未リリース**変更の日本語版です。全履歴は [CHANGELOG.md](./CHANGELOG.md)(中文)を参照してください。
11
11
 
12
+ ## [0.19.0] — 2026-09-29
13
+
14
+ ### 変更
15
+
16
+ - **DSH 0.2.0 適応(compat/0.2.0)**:peerDependencies と engines.dsh(package.json + dsh.plugin.json)を `>=0.2.0-rc.1 <0.2.1-0` へ一括更新(単一レンジ置換。0.1.7 系は compat/0.1.7 ブランチが継続サポート);dsh-* devDependencies 9 件を 0.1.1-rc.2 → 0.2.0-rc.1 に固定し直し、type-only 依存 `@deepseek-ai/dsh-compaction` を追加。コード面では 0.2.0 ホスト API の変化に対応:`agent/session-start` イベントを `agent/created` に統合(serial 契約に合わせリスナーを async 化);Session イベント読み取りを `session.events` → `session.snapshotEvents()` に変更(ホストが同期全量読み取りを非推奨化。フォールバックチェーンは維持);テストスタブ更新(projection カーソルの offset セマンティクス)。
17
+ - **リリースメタデータ**:バージョン 0.18.4 → 0.19.0;publishConfig.tag `dsh-0.1.7` → `dsh-0.2.0`;dsh.plugin.json version → `0.19.0-dsh0.2.0.1`。
18
+
19
+ ## [0.18.4] — 2026-09-28
20
+
21
+ ### 追加
22
+
23
+ - **クラッシュ復元(§A)**:ホストがターン途中でクラッシュすると、それまで当該ターンの会話はメモリバッファとともに永久失われていました(resume 時のコールドスタート保護が全履歴を破棄するため)。現在は resume 時にホストの永続化イベントログと突き合わせます:L0 記録済み最大 turn をウォーターマークとして、その後の完全なターンを最大 2 件まで補収(クラッシュ孤児ターンはホストが `turn/end{reason:'interrupted'}` で閉じます——実機で 98 件確認)。冪等性 = ウォーターマーク + ターン単位の存在チェック。ホストの読み取りサービスが利用不可の場合は段階的に縮退(`sessionQuery.readSession` → `sessionPersistence.readFrom` → 従来動作 + 一回限りの通知)し、常に fail-open でセッション起動を阻塞しません。
24
+ - **ペイロード赤字化(§C、`capture.redactSecrets`、デフォルト有効)**:捕获書き込み境界で 8 種の秘密(PEM 秘密鍵 / Authorization ヘッダー / Bearer・JWT / Cookie / ベンダー API キー形式 / メールアドレス / 9 桁以上の数値(日付は除外)/ 高エントロピー ID)を `[REDACTED:<KIND>]` 型付きプレースホルダーに置換——L0 JSONL・L0 SQLite・蒸留入力・手動 `memory_add`/`memory_import` を単一点でカバー。安全値(`example` / `$VAR` / `${{…}}` 等)は対象外。プレースホルダーはカテゴリ意味を保持し検索可能。注意:有効化後は L0 原文が変わります(再構築でも原文は取得不可)。`false` で平文に戻せます。
25
+ - **蒸留プロンプト耐注入(§B)**:6 つの蒸留プロンプトファイル(L1 抽出 ×3 / L1 重複排除 ×3 / L2 シーン ×2 / L3 ペルソナ ×2 / グラフ投影 / 突き合わせ器)すべてに「内容境界(耐注入)」宣言とデータスロット界定を追加——会話原文・既存記憶プール・シーン全文等の埋め込み内容はデータであり指令ではない。判定語彙と出力契約は不変。
26
+
27
+ ### 改善
28
+
29
+ - **注入確認(§D)**:リコール注入は返却時に即マークしなくなりました。「pending → ログ受領」の二段式——ホストが注入メッセージを実際にセッションログへ書き込んだ(`plugin:memory` 署名と安定 id を持つ `user/message`)時点で `dedupe.mark` します。上書き・取消された注入は記憶を誤抑制しなくなり(次ターンで再注入可能)、5 分受領なしで通常マークに縮退(確認経路故障による重複排除無効化を防ぐ)、未確認の期限切れは破棄。
30
+ - **圧縮後の精密再注入(§E)**:`compaction/end`(error なし)の後、当該セッションの次ターンで一回の拡張リコールを実施——重複排除抑制をスキップ(圧縮が旧注入をコンテキストから追い出したため)、ペルソナを即時再注入、占有台帳をリセット。使用時に消費。既存の compact/clear 全量リセットはフォールバックとして保持し、両経路は冪等。
31
+ - **構造化トレース(§F、`trace.*`)**:リコールと蒸留のイベントを日次 JSONL に永続化(`<dataDir>/trace/`、既定保持 14 日、日次 5MB 上限で停止 + マーカー)。リコールイベントは query 指紋(既定は metadata-only:長さ + sha256、`trace.captureContent` で原文 ≤200 文字)、ヒット/注入 id、スコア、所要時間と 4 結果を記録。蒸留イベントは runId・6 値の決定集計(`l1_receipts` と同源で交差監査可能)・所要時間と成否。新エンドポイント `dsh-memory/trace-tail`、設定ページの「ログ」Tab に 3 データソース切替(システムログ / リコールトレース / 蒸留トレース)。
32
+
12
33
  ## [0.18.2] — 2026-09-27
13
34
 
14
35
  ### 修正
package/CHANGELOG.ko.md CHANGED
@@ -9,6 +9,27 @@
9
9
 
10
10
  이 파일은 **0.12.0** 릴리스 노트와 현재 **미출시** 변경 사항의 한국어판입니다. 전체 이력은 [CHANGELOG.md](./CHANGELOG.md)(中文)를 참조하세요.
11
11
 
12
+ ## [0.19.0] — 2026-09-29
13
+
14
+ ### 변경
15
+
16
+ - **DSH 0.2.0 대응(compat/0.2.0)**:peerDependencies와 engines.dsh(package.json + dsh.plugin.json)를 `>=0.2.0-rc.1 <0.2.1-0`로 일괄 갱신(단일 범위 치환. 0.1.7 라인은 compat/0.1.7 브랜치가 계속 지원);dsh-* devDependencies 9건을 0.1.1-rc.2 → 0.2.0-rc.1로 재고정하고 type-only 의존성 `@deepseek-ai/dsh-compaction` 추가. 코드 측면에서 0.2.0 호스트 API 변화 대응:`agent/session-start` 이벤트를 `agent/created`로 통합(serial 계약에 맞춰 리스너를 async화);Session 이벤트 읽기를 `session.events` → `session.snapshotEvents()`로 변경(호스트가 동기 전량 읽기를 폐기 예정. 폴백 체인 유지);테스트 스텁 갱신(projection 커서 offset 시맨틱스).
17
+ - **릴리스 메타데이터**:버전 0.18.4 → 0.19.0;publishConfig.tag `dsh-0.1.7` → `dsh-0.2.0`;dsh.plugin.json version → `0.19.0-dsh0.2.0.1`.
18
+
19
+ ## [0.18.4] — 2026-09-28
20
+
21
+ ### 추가
22
+
23
+ - **크래시 복구(§A)**: 호스트가 턴 도중 크래시하면 해당 턴 대화는 메모리 버퍼와 함께 영구 유실되었습니다(resume 시 콜드스타트 보호가 전체 이력을 폐기). 이제 resume 시 호스트의 영속 이벤트 로그와 대조합니다: L0 기록 최대 turn을 워터마크로, 그 이후의 완전한 턴을 최대 2개까지 보수(크래시 고아 턴은 호스트가 `turn/end{reason:'interrupted'}`로 닫습니다 — 실기에서 98건 확인). 멱등성 = 워터마크 + 턴 단위 존재 검사. 호스트 읽기 서비스를 사용할 수 없으면 단계적 축소(`sessionQuery.readSession` → `sessionPersistence.readFrom` → 기존 동작 + 일회성 안내), 항상 fail-open으로 세션 시작을 막지 않습니다.
24
+ - **페이로드 마스킹(§C, `capture.redactSecrets`, 기본 활성)**: 캡처 쓰기 경계에서 8종의 시크릿(PEM 개인키 / Authorization 헤더 / Bearer·JWT / Cookie / 벤더 API 키 형태 / 이메일 / 9자리 이상 숫자(날짜 제외) / 고엔트로피 ID)을 `[REDACTED:<KIND>]` 타입 플레이스홀더로 치환 — L0 JSONL·L0 SQLite·증류 입력·수동 `memory_add`/`memory_import`를 단일 지점에서 커버. 안전값(`example` / `$VAR` / `${{…}}` 등)은 제외. 플레이스홀더는 카테고리 의미를 유지해 검색 가능. 주의: 활성화 후 L0 원문은 변경됩니다(재구축으로도 원문 복원 불가). `false`로 평문 복귀.
25
+ - **증류 프롬프트 내성 주입(§B)**: 6개 증류 프롬프트 파일(L1 추출 ×3 / L1 중복제거 ×3 / L2 씬 ×2 / L3 페르소나 ×2 / 그래프 투영 / 대조기) 모두에 "콘텐츠 경계(내성 주입)" 선언과 데이터 슬롯 경계를 추가 — 대화 원문·기존 기억 풀·씬 전문 등 임베디드 콘텐츠는 데이터이지 지시가 아닙니다. 판정 어휘와 출력 계약은 불변.
26
+
27
+ ### 개선
28
+
29
+ - **주입 확인(§D)**: 리콜 주입은 반환 즉시 마크하지 않습니다. "pending → 로그 수신" 2단 방식 — 호스트가 주입 메시지를 실제로 세션 로그에 기록했을 때(`plugin:memory` 서명과 안정 id를 가진 `user/message`) `dedupe.mark` 합니다. 덮어쓰기·취소된 주입은 더 이상 기억을 오억제하지 않고(다음 턴 재주입 가능), 5분 수신 없으면 일반 마크로 축소(확인 경로 장애로 인한 중복제거 무효화 방지), 미확인 만료는 폐기.
30
+ - **압축 후 정밀 재주입(§E)**: `compaction/end`(error 없음) 후 해당 세션의 다음 턴에 한 번의 확장 리콜 실행 — 중복제거 억제를 건너뛰고(압축이 기존 주입을 컨텍스트에서 축출), 페르소나 즉시 재주입, 점유 원장 리셋. 사용 시 소비. 기존 compact/clear 전량 리셋은 폴백으로 유지되며 양 경로는 멱등.
31
+ - **구조화 트레이스(§F, `trace.*`)**: 리콜과 증류 이벤트를 일별 JSONL로 영속화(`<dataDir>/trace/`, 기본 보존 14일, 일별 5MB 상한에서 정지 + 마커). 리콜 이벤트는 query 지문(기본 metadata-only: 길이 + sha256, `trace.captureContent` 시 원문 ≤200자), 히트/주입 id, 스코어, 소요시간과 4가지 결과를 기록. 증류 이벤트는 runId·6값 결정 집계(`l1_receipts`와 동원으로 교차 감사 가능)·소요시간과 성패. 신규 엔드포인트 `dsh-memory/trace-tail`, 설정 페이지 "로그" 탭에 3개 데이터 소스 전환(시스템 로그 / 리콜 트레이스 / 증류 트레이스).
32
+
12
33
  ## [0.18.2] — 2026-09-27
13
34
 
14
35
  ### 수정
package/CHANGELOG.md CHANGED
@@ -6,6 +6,27 @@
6
6
  > **UI 截图约定**:带界面变化的条目在 `assets/changelog/<版本号>/<两位编号>-<简述>.png`
7
7
  > 存真机截图,并在条目内以相对路径引用,读者可在更新日志里直接看到新版本 UI 的样子。
8
8
 
9
+ ## [0.19.0] — 2026-09-29
10
+
11
+ ### 变更
12
+
13
+ - **DSH 0.2.0 适配(compat/0.2.0)**:peerDependencies 与 engines.dsh(package.json + dsh.plugin.json)整体换代到 `>=0.2.0-rc.1 <0.2.1-0`(单段替换,0.1.7 线由 compat/0.1.7 分支继续服务);devDependencies 9 个 dsh-* 精确钉 0.1.1-rc.2 → 0.2.0-rc.1 并新增 type-only 依赖 `@deepseek-ai/dsh-compaction`。代码层适配 0.2.0 宿主 API 漂移:`agent/session-start` 事件并入 `agent/created`(监听器改为 async 以满足 serial 契约);Session 事件读取 `session.events` → `session.snapshotEvents()`(宿主已弃用同步全量读取,保留降级链);测试桩同步更新(projection 游标 offset 语义)。
14
+ - **发布元数据**:版本 0.18.4 → 0.19.0;publishConfig.tag `dsh-0.1.7` → `dsh-0.2.0`;dsh.plugin.json version → `0.19.0-dsh0.2.0.1`。
15
+
16
+ ## [0.18.4] — 2026-09-28
17
+
18
+ ### 新增
19
+
20
+ - **崩溃恢复(§A)**:宿主在轮次中途崩溃时,该轮对话此前会随内存缓冲永久丢失(resume 的冷启动地板丢弃全部历史)。现在 resume 时从宿主持久化事件日志对账:以 L0 已落盘的最大 turn 为水位线,补收其后的完整轮次(上限 2 轮;崩溃孤儿轮由宿主补写 `turn/end{reason:'interrupted'}` 闭合,本机实测 98 处)。幂等 = 水位线 + 逐轮存在性检查;宿主读日志服务不可用时逐级降级(`sessionQuery.readSession` → `sessionPersistence.readFrom` → 维持现状 + 一次性提示),全程 fail-open 不阻塞会话启动。
21
+ - **载荷脱敏(§C,`capture.redactSecrets`,默认开启)**:捕获写入边界把 8 类密钥(PEM 私钥 / Authorization 头 / Bearer 与 JWT / Cookie / 厂商 API key 形态 / 邮箱 / ≥9 位长号(排除日期)/ 高熵 ID)替换为 `[REDACTED:<KIND>]` 类型化占位符——单点覆盖 L0 JSONL、L0 SQLite、蒸馏输入与手动 `memory_add`/`memory_import`(两条 L1 写入边界同词表)。安全值(`example` / `$VAR` / `${{…}}` 等)不脱;占位符保留类别语义、可被检索命中。注意:开启后 L0 原文自此改变(重建不可得原文),`false` 一键回明文。
22
+ - **蒸馏提示词防注入(§B)**:六处蒸馏 prompt(L1 抽取 ×3 / L1 去重 ×3 / L2 场景 ×2 / L3 画像 ×2 / 图谱投影 / 核对器)全部加入"内容边界(防注入)"总声明与数据插槽界定——对话原文、既有记忆池、场景全文等嵌入内容一律是数据不是指令,防止对话携带的指令性文字劫持蒸馏、去重与裁决。判定词表与输出契约零变化。
23
+
24
+ ### 改进
25
+
26
+ - **注入确认(§D)**:召回注入不再在返回瞬间标记去重,改为"pending → 日志回执"两段式——宿主把注入消息真实写入会话日志(`user/message` 带 `plugin:memory` 署名与稳定 id)时才 `dedupe.mark`。被覆盖/取消的注入不再误压制记忆(下轮可重注);5 分钟未回执降级为照常标记(防确认链路故障导致去重失效),未确认即弃。
27
+ - **压缩精确再注入(§E)**:`compaction/end`(无 error)后,该会话下一轮做一次定向增强召回——跳过去重压制(压缩已把旧注入逐出上下文)、画像立即重注入、占用账本归零;消费即清。原有 compact/clear 会话级全量重置保留为回退路径,双路径幂等。
28
+ - **结构化追踪(§F,`trace.*`)**:召回与蒸馏事件按天 JSONL 落盘(`<dataDir>/trace/`,保留期默认 14 天,单日 5MB 停写 + marker)。召回事件含 query 指纹(默认 metadata-only:长度 + sha256,`trace.captureContent` 才存原文 ≤200 字符)、命中/注入 id、分数、耗时与四种结局(injected/suppressed/timeout/off);蒸馏事件含 runId、六值决策聚合(与 `l1_receipts` 同源可交叉审计)、耗时与成败。新增 `dsh-memory/trace-tail` 端点;设置页"日志"Tab 新增 系统日志 / 召回追踪 / 蒸馏追踪 三数据源切换。
29
+
9
30
  ## [0.18.2] — 2026-09-27
10
31
 
11
32
  ### 修复
package/INSTALL.en.md CHANGED
@@ -4,7 +4,7 @@ This plugin ships as a **DSH official bundle package**: after install, the `dsh.
4
4
 
5
5
  ## Requirements
6
6
 
7
- - Node.js ≥ 22.16 (DSH 0.1.1-rc.2 and above)
7
+ - Node.js ≥ 22.16 (DSH 0.2.0-rc.1 and above)
8
8
  - DeepSeek Harness (DSH) installed, with `--profile web` available
9
9
 
10
10
  ## Install
package/INSTALL.ja.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  ## 環境要件
6
6
 
7
- - Node.js ≥ 22.16(DSH 0.1.1-rc.2 以上)
7
+ - Node.js ≥ 22.16(DSH 0.2.0-rc.1 以上)
8
8
  - DeepSeek Harness(以下 DSH)が導入済みで、`--profile web` が利用可能
9
9
 
10
10
  ## インストール
package/INSTALL.ko.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  ## 환경 요구
6
6
 
7
- - Node.js ≥ 22.16(DSH 0.1.1-rc.2 이상)
7
+ - Node.js ≥ 22.16(DSH 0.2.0-rc.1 이상)
8
8
  - DeepSeek Harness(이하 DSH)설치 완료, `--profile web` 사용 가능
9
9
 
10
10
  ## 설치
package/INSTALL.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  ## 环境要求
6
6
 
7
- - Node.js ≥ 22.16(DSH 0.1.1-rc.2 及以上)
7
+ - Node.js ≥ 22.16(DSH 0.2.0-rc.1 及以上)
8
8
  - 已安装 DeepSeek Harness(以下简称 DSH),且 `--profile web` 可用
9
9
 
10
10
  ## 安装
package/README.en.md CHANGED
@@ -10,7 +10,7 @@
10
10
  [简体中文](README.md) · [Latest release](https://github.com/drscrewdriver/dsh-prime-memory/releases/latest) · [Report issues](https://github.com/drscrewdriver/dsh-prime-memory/issues)
11
11
 
12
12
  [![npm version](https://img.shields.io/npm/v/dsh-prime-memory?color=6f83ff&style=flat-square&label=npm)](https://www.npmjs.com/package/dsh-prime-memory)
13
- [![DSH 0.1.1-rc.2](https://img.shields.io/badge/DSH-0.1.1--rc.2-8b5cf6?style=flat-square)](https://github.com/deepseek-ai/deepseek-harness)
13
+ [![DSH 0.2.0-rc.1](https://img.shields.io/badge/DSH-0.2.0--rc.1-8b5cf6?style=flat-square)](https://github.com/deepseek-ai/deepseek-harness)
14
14
  [![MIT License](https://img.shields.io/badge/license-MIT-536990?style=flat-square)](LICENSE)
15
15
 
16
16
  </div>
@@ -41,11 +41,12 @@
41
41
  | 0.1.2-rc.1 | `settings.register()` (fallback available) | ⚠️ Inferred from framework docs, not field-tested |
42
42
  | 0.1.3-rc.1 | `settings.register()` (fallback available) | ⚠️ Not field-tested (0.1.3+ namespaces became plain strings; this plugin is compatible) |
43
43
  | 0.1.5-rc.2 | `settings.register()` (fallback available) | ⚠️ Not field-tested; Session V3 surface semantics and input-bar/settings slots pending regression |
44
+ | 0.2.0-rc.1 | `settings.register()` (live scope) | ✅ Current adaptation line (event wiring agent/session-start → agent/created) |
44
45
 
45
46
  > Compatibility mechanism: settings registration uses a three-way runtime branch
46
47
  > (`register` → `installSection` bridge → always-on degradation); see the 0.11.0 entry
47
48
  > in [CHANGELOG.md](./CHANGELOG.md). `dsh.plugin.json` declares
48
- > `engines.dsh: ">=0.1.1-rc.2 <0.2.0-0"`.
49
+ > `engines.dsh: ">=0.2.0-rc.1 <0.2.1-0"`.
49
50
 
50
51
  ## Getting Started
51
52
 
@@ -283,6 +284,10 @@ the bundle layer appends and causes `duplicate loader entry id` startup failure)
283
284
  | `capture.enabled` | `true` | L0 capture |
284
285
  | `capture.stripCodeBlocks` | `true` | Strip code blocks from assistant messages |
285
286
  | `capture.maxMessageChars` | `4000` | Max characters per message |
287
+ | `capture.redactSecrets` | `true` | Payload redaction: 8 secret classes (PEM/Bearer/JWT/Cookie/vendor API keys/emails/long numbers/high-entropy IDs) become `[REDACTED:<KIND>]` placeholders at capture time — covers L0, distill input and manual writes; `false` restores plaintext (irreversible once enabled) |
288
+ | `trace.enabled` | `true` | Structured trace: recall/distill events as daily JSONL under `<dataDir>/trace/`; switch sources in the Log tab |
289
+ | `trace.retentionDays` | `14` | Trace retention in days (`0` = forever) |
290
+ | `trace.captureContent` | `false` | `true` stores recall query text (default: length + sha256 only) |
286
291
  | `extract.enabled` | `true` | L1 extraction |
287
292
  | `extract.minMessages` | `6` | Steady-state trigger threshold: run L1 extraction once a session accumulates N new messages. The effective threshold ramps up 1→2→4→…→N (first turn yields memories immediately, then batches to save calls) |
288
293
  | `extract.idleSeconds` | `300` | Idle flush: distill a session's pending slice after N seconds of silence (catches "user left before reaching the threshold"); `0` disables |
package/README.ja.md CHANGED
@@ -10,7 +10,7 @@ alt="DeepSeek Harness ヒーロー画像:会話がバックグラウンドで
10
10
  [中文 README](./README.md) · [English README](./README.en.md) · [日本語 README](./README.ja.md) · [한국어 README](./README.ko.md) · [最新リリース](https://github.com/drscrewdriver/dsh-prime-memory/releases/latest) · [問題を報告](https://github.com/drscrewdriver/dsh-prime-memory/issues)
11
11
 
12
12
  [![npm version](https://img.shields.io/npm/v/dsh-prime-memory?color=6f83ff&style=flat-square&label=npm)](https://www.npmjs.com/package/dsh-prime-memory)
13
- [![DSH 0.1.1-rc.2](https://img.shields.io/badge/DSH-0.1.1--rc.2-8b5cf6?style=flat-square)](https://github.com/deepseek-ai/deepseek-harness)
13
+ [![DSH 0.2.0-rc.1](https://img.shields.io/badge/DSH-0.2.0--rc.1-8b5cf6?style=flat-square)](https://github.com/deepseek-ai/deepseek-harness)
14
14
  [![MIT License](https://img.shields.io/badge/license-MIT-536990?style=flat-square)](LICENSE)
15
15
 
16
16
  </div>
@@ -43,10 +43,11 @@ alt="DeepSeek Harness ヒーロー画像:会話がバックグラウンドで
43
43
  | 0.1.2-rc.1 | `settings.register()`(フォールバック可) | ⚠️ フレームワークドキュメントから推定、未実測 |
44
44
  | 0.1.3-rc.1 | `settings.register()`(フォールバック可) | ⚠️ 未実測(0.1.3+ で名前空間が文字列化、本プラグインは対応済み) |
45
45
  | 0.1.5-rc.2 | `settings.register()`(フォールバック可) | ⚠️ 未実測。Session V3 の surface セマンティクスと入力バー/設定スロットは回帰待ち |
46
+ | 0.2.0-rc.1 | `settings.register()`(ライブスコープ) | ✅ 今回の適用ライン(イベント配線 agent/session-start → agent/created) |
46
47
 
47
48
  > 互換メカニズム:settings 登録は 3 分岐のランタイム判定(`register` → `installSection` ブリッジ → 常時オン縮退)。
48
49
  > 詳細は [CHANGELOG.md](./CHANGELOG.md) の 0.11.0 エントリ参照。`dsh.plugin.json` は
49
- > `engines.dsh: ">=0.1.1-rc.2 <0.2.0-0"` を宣言。
50
+ > `engines.dsh: ">=0.2.0-rc.1 <0.2.1-0"` を宣言。
50
51
 
51
52
  ## クイックスタート
52
53
 
@@ -227,6 +228,10 @@ node bench/harness/retrieval-metrics.mjs <runDir> --flood 200,600
227
228
  | `capture.enabled` | `true` | L0 捕捉 |
228
229
  | `capture.stripCodeBlocks` | `true` | アシスタントメッセージからコードブロックを除去 |
229
230
  | `capture.maxMessageChars` | `4000` | 単メッセージ最大文字数 |
231
+ | `capture.redactSecrets` | `true` | ペイロード赤字化:捕获書き込み時に 8 種の秘密(PEM/Bearer/JWT/Cookie/ベンダー API キー/メール/長数字/高エントロピー ID)を `[REDACTED:<KIND>]` に置換——L0・蒸留入力・手動書き込みをカバー。`false` で平文に戻す(有効化後は原文不可逆) |
232
+ | `trace.enabled` | `true` | 構造化トレース:リコール/蒸留イベントを日次 JSONL で保存(`<dataDir>/trace/`)、設定ページの「ログ」Tab で切替表示 |
233
+ | `trace.retentionDays` | `14` | トレース保持日数(`0` = 無期限) |
234
+ | `trace.captureContent` | `false` | `true` でリコール query 原文を保存(既定は長さ + sha256 のみ) |
230
235
  | `extract.enabled` | `true` | L1 抽出 |
231
236
  | `extract.minMessages` | `6` | 定常トリガ閾値:単セッションが N 件新メッセージを溜めて L1 抽出を1回実行。立ち上がりは 1→2→4→…→N と倍増 |
232
237
  | `extract.idleSeconds` | `300` | アイドル兜底:セッションが N 秒無言で未蒸留スライスを落とす。`0` で無効 |
package/README.ko.md CHANGED
@@ -10,7 +10,7 @@ alt="DeepSeek Harness 히어로 이미지: 대화가 백그라운드에서 계
10
10
  [中文 README](./README.md) · [English README](./README.en.md) · [日本語 README](./README.ja.md) · [한국어 README](./README.ko.md) · [최신 릴리스](https://github.com/drscrewdriver/dsh-prime-memory/releases/latest) · [문제 제보](https://github.com/drscrewdriver/dsh-prime-memory/issues)
11
11
 
12
12
  [![npm version](https://img.shields.io/npm/v/dsh-prime-memory?color=6f83ff&style=flat-square&label=npm)](https://www.npmjs.com/package/dsh-prime-memory)
13
- [![DSH 0.1.1-rc.2](https://img.shields.io/badge/DSH-0.1.1--rc.2-8b5cf6?style=flat-square)](https://github.com/deepseek-ai/deepseek-harness)
13
+ [![DSH 0.2.0-rc.1](https://img.shields.io/badge/DSH-0.2.0--rc.1-8b5cf6?style=flat-square)](https://github.com/deepseek-ai/deepseek-harness)
14
14
  [![MIT License](https://img.shields.io/badge/license-MIT-536990?style=flat-square)](LICENSE)
15
15
 
16
16
  </div>
@@ -43,10 +43,11 @@ alt="DeepSeek Harness 히어로 이미지: 대화가 백그라운드에서 계
43
43
  | 0.1.2-rc.1 | `settings.register()`(폴백 가능) | ⚠️ 프레임워크 문서 기반 추정, 미실측 |
44
44
  | 0.1.3-rc.1 | `settings.register()`(폴백 가능) | ⚠️ 미실측(0.1.3+에서 네임스페이스가 문자열화, 본 플러그인은 대응 완료) |
45
45
  | 0.1.5-rc.2 | `settings.register()`(폴백 가능) | ⚠️ 미실측. Session V3 surface 시맨틱스와 입력바/설정 슬롯 회귀 대기 |
46
+ | 0.2.0-rc.1 | `settings.register()`(라이브 스코프) | ✅ 이번 적용 라인(이벤트 배선 agent/session-start → agent/created) |
46
47
 
47
48
  > 호환 메커니즘: settings 등록은 3분기 런타임 분기(`register` → `installSection` 브리지 → 상시 온 강등).
48
49
  > 자세한 내용은 [CHANGELOG.md](./CHANGELOG.md)의 0.11.0 항목 참조. `dsh.plugin.json`은
49
- > `engines.dsh: ">=0.1.1-rc.2 <0.2.0-0"` 선언.
50
+ > `engines.dsh: ">=0.2.0-rc.1 <0.2.1-0"` 선언.
50
51
 
51
52
  ## 빠른 시작
52
53
 
@@ -227,6 +228,10 @@ node bench/harness/retrieval-metrics.mjs <runDir> --flood 200,600
227
228
  | `capture.enabled` | `true` | L0 포착 |
228
229
  | `capture.stripCodeBlocks` | `true` | 어시스턴트 메시지에서 코드 블록 제거 |
229
230
  | `capture.maxMessageChars` | `4000` | 단메시지 최대 문자 수 |
231
+ | `capture.redactSecrets` | `true` | 페이로드 마스킹:캡처 쓰기 시 8종 시크릿(PEM/Bearer/JWT/Cookie/벤더 API 키/이메일/긴 숫자/고엔트로피 ID)을 `[REDACTED:<KIND>]`로 치환 — L0·증류 입력·수동 쓰기 커버. `false`로 평문 복귀(활성화 후 원문 비가역) |
232
+ | `trace.enabled` | `true` | 구조화 트레이스:리콜/증류 이벤트를 일별 JSONL로 저장(`<dataDir>/trace/`), 설정 페이지 "로그" 탭에서 전환 조회 |
233
+ | `trace.retentionDays` | `14` | 트레이스 보존 일수(`0` = 무기한) |
234
+ | `trace.captureContent` | `false` | `true` 시 리콜 query 원문 저장(기본은 길이 + sha256만) |
230
235
  | `extract.enabled` | `true` | L1 추출 |
231
236
  | `extract.minMessages` | `6` | 정상 트리거 임계값:단세션이 N건 새 메시지 누적 시 L1 추출 1회. 시작 단계는 1→2→4→…→N 배증 |
232
237
  | `extract.idleSeconds` | `300` | 유휴兜底:세션이 N초 무음이면 미증류 슬라이스 투하. `0` 비활성 |
package/README.md CHANGED
@@ -10,7 +10,7 @@ alt="DeepSeek Harness hero 横幅:对话自动分层蒸馏成记忆,模型
10
10
  [English](README.en.md) · [最新发行版](https://github.com/drscrewdriver/dsh-prime-memory/releases/latest) · [反馈问题](https://github.com/drscrewdriver/dsh-prime-memory/issues)
11
11
 
12
12
  [![npm version](https://img.shields.io/npm/v/dsh-prime-memory?color=6f83ff\&style=flat-square\&label=npm)](https://www.npmjs.com/package/dsh-prime-memory)
13
- [![DSH 0.1.1-rc.2](https://img.shields.io/badge/DSH-0.1.1--rc.2-8b5cf6?style=flat-square)](https://github.com/deepseek-ai/deepseek-harness)
13
+ [![DSH 0.2.0-rc.1](https://img.shields.io/badge/DSH-0.2.0--rc.1-8b5cf6?style=flat-square)](https://github.com/deepseek-ai/deepseek-harness)
14
14
  [![MIT License](https://img.shields.io/badge/license-MIT-536990?style=flat-square)](LICENSE)
15
15
 
16
16
  </div>
@@ -41,10 +41,11 @@ alt="DeepSeek Harness hero 横幅:对话自动分层蒸馏成记忆,模型
41
41
  | 0.1.2-rc.1 | `settings.register()`(回退可用) | ⚠️ 按框架文档推断,未实测 |
42
42
  | 0.1.3-rc.1 | `settings.register()`(回退可用) | ⚠️ 未实测(0.1.3+ 命名空间已改字符串,本插件已兼容) |
43
43
  | 0.1.5-rc.2 | `settings.register()`(回退可用) | ⚠️ 未实测;Session V3 surface 语义与输入栏/设置槽位待回归 |
44
+ | 0.2.0-rc.1 | `settings.register()`(live scope) | ✅ 本次适配线(事件接线 agent/session-start → agent/created) |
44
45
 
45
46
  > 兼容机制:settings 注册走运行时三分支(`register` → `installSection` 桥接 → 恒开降级),
46
47
  > 详见 [CHANGELOG.md](./CHANGELOG.md) 的 0.11.0 条目。`dsh.plugin.json` 声明
47
- > `engines.dsh: ">=0.1.1-rc.2 <0.2.0-0"`。
48
+ > `engines.dsh: ">=0.2.0-rc.1 <0.2.1-0"`。
48
49
 
49
50
  ## 快速开始
50
51
 
@@ -295,6 +296,10 @@ ONNX 量化 **CPU 推理**——无需 API Key,数据不出本机)。本地
295
296
  | `capture.enabled` | `true` | L0 捕获 |
296
297
  | `capture.stripCodeBlocks` | `true` | 助手消息剥离代码块 |
297
298
  | `capture.maxMessageChars` | `4000` | 单条消息最大字符数 |
299
+ | `capture.redactSecrets` | `true` | 载荷脱敏:捕获写入即把 8 类密钥(PEM/Bearer/JWT/Cookie/厂商 API key/邮箱/长号/高熵 ID)替换为 `[REDACTED:<KIND>]` 占位符,覆盖 L0、蒸馏输入与手动写入;`false` 回明文(开启后 L0 原文不再可逆) |
300
+ | `trace.enabled` | `true` | 结构化追踪:召回/蒸馏事件按天 JSONL(`<dataDir>/trace/`),设置页"日志"Tab 可切换查看 |
301
+ | `trace.retentionDays` | `14` | 追踪事件保留天数(`0` 永久) |
302
+ | `trace.captureContent` | `false` | `true` 才存召回 query 原文(默认只存长度 + sha256) |
298
303
  | `extract.enabled` | `true` | L1 抽取 |
299
304
  | `extract.minMessages` | `6` | 稳态触发阈值:单会话攒够 N 条新消息跑一次 L1 抽取。起步阶段生效阈值从 1 翻倍爬坡到此值(首轮即出记忆,随后自动攒批省调用) |
300
305
  | `extract.idleSeconds` | `300` | 闲置兜底:会话静默 N 秒后把未蒸馏切片落袋(接住"没攒够阈值用户就离开");`0` 关闭 |
package/cordis.patch.yml CHANGED
@@ -11,6 +11,12 @@
11
11
  # config: # 全部字段有默认值,按需覆盖:
12
12
  # family: auto # 新会话默认档:auto | chat | work
13
13
  # dataDir: '' # 默认 $DSH_HOME/memory
14
+ # capture:
15
+ # redactSecrets: true # §C 脱敏:8 类密钥→[REDACTED:KIND] 占位符(false 回明文)
16
+ # trace:
17
+ # enabled: true # §F 追踪:recall/distill 事件按天 JSONL
18
+ # retentionDays: 14 # 事件保留天数(0 = 永久)
19
+ # captureContent: false # true 才存 query 原文(默认只存 chars+sha)
14
20
  # llm:
15
21
  # provider: '' # 蒸馏模型路由(默认跟随当前默认模型)
16
22
  # model: ''
package/dist/client.js CHANGED
@@ -1178,20 +1178,46 @@ var __defProp = Object.defineProperty;
1178
1178
  // client/src/tabs/LogTab.tsx
1179
1179
  var import_react4 = require("react");
1180
1180
  var import_jsx_runtime4 = require("react/jsx-runtime");
1181
+ var SOURCES = [
1182
+ { id: "", label: "系统日志" },
1183
+ { id: "recall_turn", label: "召回追踪" },
1184
+ { id: "distill_run", label: "蒸馏追踪" }
1185
+ ];
1186
+ function fmtEvent(ev) {
1187
+ if (ev.kind === "recall_turn") {
1188
+ const outcome = String(ev.outcome ?? "?");
1189
+ const hits = ev.hitIds?.length ?? 0;
1190
+ const injected = ev.injectedIds?.length ?? 0;
1191
+ const q = ev.queryText ? ` query="${String(ev.queryText).slice(0, 40)}"` : ` sha=${String(ev.querySha ?? "")}`;
1192
+ return `[${new Date(Number(ev.ts)).toLocaleTimeString()}] recall ${outcome}${q} hits=${hits} injected=${injected} suppressed=${String(ev.suppressedCount ?? 0)} ${String(ev.durationMs ?? 0)}ms`;
1193
+ }
1194
+ if (ev.kind === "distill_run") {
1195
+ const by = ev.byKind ? " byKind=" + JSON.stringify(ev.byKind) : "";
1196
+ const err = ev.errorKind ? " error=" + String(ev.errorKind) : "";
1197
+ return `[${new Date(Number(ev.ts)).toLocaleTimeString()}] distill ${String(ev.layer)}${ev.runId ? " run=" + String(ev.runId) : ""} ok=${String(ev.ok)} in=${String(ev.inputChars ?? 0)}ch new=${String(ev.newRecords ?? 0)} ${String(ev.durationMs ?? 0)}ms${by}${err}`;
1198
+ }
1199
+ return JSON.stringify(ev);
1200
+ }
1181
1201
  function LogTab(props) {
1182
1202
  const rpc = props.rpc;
1203
+ const [source, setSource] = (0, import_react4.useState)("");
1183
1204
  const [lines, setLines] = (0, import_react4.useState)(null);
1184
1205
  const [error, setError] = (0, import_react4.useState)(null);
1185
1206
  const preRef = (0, import_react4.useRef)(null);
1186
1207
  const load = (0, import_react4.useCallback)(() => {
1187
1208
  setError(null);
1188
- rpc("dsh-memory/log-tail", { lines: 200 }).then((r) => {
1189
- if (r && r.ok) setLines(r.value.lines);
1209
+ if (source === "") {
1210
+ rpc("dsh-memory/log-tail", { lines: 200 }).then((r) => {
1211
+ if (r && r.ok) setLines(r.value.lines);
1212
+ else setError(r && r.error ? r.error.message : "RPC error");
1213
+ }).catch((e) => setError(String(e && e.message || e)));
1214
+ return;
1215
+ }
1216
+ rpc("dsh-memory/trace-tail", { lines: 200, kind: source }).then((r) => {
1217
+ if (r && r.ok) setLines(r.value.events.map(fmtEvent));
1190
1218
  else setError(r && r.error ? r.error.message : "RPC error");
1191
- }).catch((e) => {
1192
- setError(String(e && e.message || e));
1193
- });
1194
- }, [rpc]);
1219
+ }).catch((e) => setError(String(e && e.message || e)));
1220
+ }, [rpc, source]);
1195
1221
  (0, import_react4.useEffect)(() => {
1196
1222
  load();
1197
1223
  }, [load]);
@@ -1199,12 +1225,13 @@ var __defProp = Object.defineProperty;
1199
1225
  if (lines && preRef.current) preRef.current.scrollTop = preRef.current.scrollHeight;
1200
1226
  }, [lines]);
1201
1227
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
1202
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { ...S.flexRow, marginBottom: 10 }, children: [
1203
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: S.muted, children: error ? "加载失败" : lines === null ? "加载中…" : "最近 " + lines.length + " 行(memory.log)" }),
1228
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { ...S.flexRow, marginBottom: 10, gap: 8 }, children: [
1229
+ SOURCES.map((s) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(NButton, { onClick: () => setSource(s.id), children: source === s.id ? "● " + s.label : s.label }, s.id)),
1204
1230
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: S.grow }),
1205
1231
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(NButton, { onClick: load, children: "刷新" })
1206
1232
  ] }),
1207
- error ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { ...S.error, marginBottom: 10 }, children: "日志读取失败:" + error + "(点右上“刷新”重试)" }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("pre", { style: S.pre, ref: preRef, children: (lines || []).join("\n") || "(暂无日志)" })
1233
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { ...S.muted, marginBottom: 10 }, children: error ? "加载失败" : lines === null ? "加载中…" : `最近 ${lines.length} 条(${SOURCES.find((s) => s.id === source)?.label})` }),
1234
+ error ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { ...S.error, marginBottom: 10 }, children: "读取失败:" + error + "(点右上“刷新”重试)" }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("pre", { style: S.pre, ref: preRef, children: (lines || []).join("\n") || "(暂无记录)" })
1208
1235
  ] });
1209
1236
  }
1210
1237
 
package/dist/config.d.ts CHANGED
@@ -29,6 +29,21 @@ export interface MemoryConfig {
29
29
  stripCodeBlocks: boolean;
30
30
  /** 单条消息内容最大字符数。 */
31
31
  maxMessageChars: number;
32
+ /**
33
+ * §C 载荷脱敏(memorax-absorb):捕获单点把 8 类密钥(PEM/Bearer/JWT/Cookie/
34
+ * 厂商 API key/邮箱/长号/高熵 ID)替换为 `[REDACTED:<KIND>]` 占位符,覆盖
35
+ * L0 JSONL/SQLite/蒸馏输入与手动 memory_add/import。**默认开启**——密钥被
36
+ * 逐轮召回注入的危害大于偶发误脱敏;注意开启后 L0 原文自此改变(重建不可得原文)。
37
+ * 决策记录见计划 spec §C;`false` 一键回到明文行为。 */
38
+ redactSecrets?: boolean;
39
+ };
40
+ /** §F 结构化追踪(memorax-absorb):recall/distill 事件按天 JSONL。 */
41
+ trace: {
42
+ enabled: boolean;
43
+ /** 事件文件保留天数(写入时切日清理;0 = 永久)。 */
44
+ retentionDays: number;
45
+ /** 默认 metadata-only(chars+sha);true 才存 query 原文(≤200 字符)。 */
46
+ captureContent: boolean;
32
47
  };
33
48
  extract: {
34
49
  enabled: boolean;
@@ -407,10 +422,21 @@ export declare const memorySchema: Schema<Schemastery.ObjectS<NoInfer<{
407
422
  enabled: Schema<boolean, boolean, "defined">;
408
423
  stripCodeBlocks: Schema<boolean, boolean, "defined">;
409
424
  maxMessageChars: Schema<number, number, "defined">;
425
+ redactSecrets: Schema<boolean, boolean, "defined">;
410
426
  }>>, Schemastery.ObjectT<NoInfer<{
411
427
  enabled: Schema<boolean, boolean, "defined">;
412
428
  stripCodeBlocks: Schema<boolean, boolean, "defined">;
413
429
  maxMessageChars: Schema<number, number, "defined">;
430
+ redactSecrets: Schema<boolean, boolean, "defined">;
431
+ }>>, "plain">;
432
+ trace: Schema<Schemastery.ObjectS<NoInfer<{
433
+ enabled: Schema<boolean, boolean, "defined">;
434
+ retentionDays: Schema<number, number, "defined">;
435
+ captureContent: Schema<boolean, boolean, "defined">;
436
+ }>>, Schemastery.ObjectT<NoInfer<{
437
+ enabled: Schema<boolean, boolean, "defined">;
438
+ retentionDays: Schema<number, number, "defined">;
439
+ captureContent: Schema<boolean, boolean, "defined">;
414
440
  }>>, "plain">;
415
441
  extract: Schema<Schemastery.ObjectS<NoInfer<{
416
442
  enabled: Schema<boolean, boolean, "defined">;
@@ -886,10 +912,21 @@ export declare const memorySchema: Schema<Schemastery.ObjectS<NoInfer<{
886
912
  enabled: Schema<boolean, boolean, "defined">;
887
913
  stripCodeBlocks: Schema<boolean, boolean, "defined">;
888
914
  maxMessageChars: Schema<number, number, "defined">;
915
+ redactSecrets: Schema<boolean, boolean, "defined">;
889
916
  }>>, Schemastery.ObjectT<NoInfer<{
890
917
  enabled: Schema<boolean, boolean, "defined">;
891
918
  stripCodeBlocks: Schema<boolean, boolean, "defined">;
892
919
  maxMessageChars: Schema<number, number, "defined">;
920
+ redactSecrets: Schema<boolean, boolean, "defined">;
921
+ }>>, "plain">;
922
+ trace: Schema<Schemastery.ObjectS<NoInfer<{
923
+ enabled: Schema<boolean, boolean, "defined">;
924
+ retentionDays: Schema<number, number, "defined">;
925
+ captureContent: Schema<boolean, boolean, "defined">;
926
+ }>>, Schemastery.ObjectT<NoInfer<{
927
+ enabled: Schema<boolean, boolean, "defined">;
928
+ retentionDays: Schema<number, number, "defined">;
929
+ captureContent: Schema<boolean, boolean, "defined">;
893
930
  }>>, "plain">;
894
931
  extract: Schema<Schemastery.ObjectS<NoInfer<{
895
932
  enabled: Schema<boolean, boolean, "defined">;
package/dist/config.js CHANGED
@@ -84,6 +84,13 @@ export const memorySchema = Schema.object({
84
84
  enabled: Schema.boolean().default(true),
85
85
  stripCodeBlocks: Schema.boolean().default(true),
86
86
  maxMessageChars: Schema.number().min(200).max(200_000).default(4000),
87
+ // §C 默认开启:本地存储也不落明文密钥(决策记录见计划 spec §C)
88
+ redactSecrets: Schema.boolean().default(true),
89
+ }),
90
+ trace: Schema.object({
91
+ enabled: Schema.boolean().default(true),
92
+ retentionDays: Schema.number().min(0).max(365).default(14),
93
+ captureContent: Schema.boolean().default(false),
87
94
  }),
88
95
  extract: Schema.object({
89
96
  enabled: Schema.boolean().default(true),
@@ -913,6 +913,50 @@ export interface LogTailRequest {
913
913
  export interface LogTailResponse {
914
914
  lines: string[];
915
915
  }
916
+ /** dsh-memory/trace-tail(§F 追踪事件流,memorax-absorb Wave 4) */
917
+ export interface RecallTraceEvent {
918
+ kind: 'recall_turn';
919
+ ts: number;
920
+ sessionId: string;
921
+ turn?: number;
922
+ /** metadata-only 默认:query 长度 + sha256 前 16 位;captureContent 才存原文(≤200)。 */
923
+ queryChars: number;
924
+ querySha?: string;
925
+ queryText?: string;
926
+ hitIds: string[];
927
+ hitScores: number[];
928
+ injectedIds: string[];
929
+ suppressedCount: number;
930
+ durationMs: number;
931
+ outcome: 'injected' | 'suppressed' | 'timeout' | 'off';
932
+ }
933
+ export interface DistillTraceEvent {
934
+ kind: 'distill_run';
935
+ ts: number;
936
+ layer: 'l1' | 'l2' | 'l3';
937
+ sessionId: string;
938
+ /** 仅 l1 有(与 l1_receipts 同一 runId,可交叉审计)。 */
939
+ runId?: string;
940
+ inputChars: number;
941
+ /** 仅 l1:决策六值词表聚合(store/update/merge/skip/conflict/skip_missing)。 */
942
+ byKind?: Record<string, number>;
943
+ newRecords?: number;
944
+ durationMs: number;
945
+ provider?: string;
946
+ model?: string;
947
+ ok: boolean;
948
+ errorKind?: string;
949
+ }
950
+ export type TraceEvent = RecallTraceEvent | DistillTraceEvent;
951
+ export interface TraceTailRequest {
952
+ /** 1~500,默认 100。 */
953
+ lines?: number;
954
+ /** 缺省 = 两类都取(按时间混合)。 */
955
+ kind?: 'recall_turn' | 'distill_run';
956
+ }
957
+ export interface TraceTailResponse {
958
+ events: TraceEvent[];
959
+ }
916
960
  /** dsh-memory/rebuild-* */
917
961
  export type RebuildStatusResponse = {
918
962
  supported: false;
@@ -1172,6 +1216,7 @@ export interface DshMemoryRequestMap {
1172
1216
  'dsh-memory/scenes': Record<string, never>;
1173
1217
  'dsh-memory/persona': Record<string, never>;
1174
1218
  'dsh-memory/log-tail': LogTailRequest;
1219
+ 'dsh-memory/trace-tail': TraceTailRequest;
1175
1220
  'dsh-memory/rebuild-status': Record<string, never>;
1176
1221
  'dsh-memory/rebuild-start': Record<string, never>;
1177
1222
  'dsh-memory/rebuild-cancel': Record<string, never>;
@@ -1216,6 +1261,7 @@ export interface DshMemoryResponseMap {
1216
1261
  'dsh-memory/scenes': ScenesResponse;
1217
1262
  'dsh-memory/persona': PersonaResponse;
1218
1263
  'dsh-memory/log-tail': LogTailResponse;
1264
+ 'dsh-memory/trace-tail': TraceTailResponse;
1219
1265
  'dsh-memory/rebuild-status': RebuildStatusResponse;
1220
1266
  'dsh-memory/rebuild-start': RebuildStatus;
1221
1267
  'dsh-memory/rebuild-cancel': RebuildStatus;