@max-null/dsh-memory 0.9.0 → 0.9.1

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/README.md CHANGED
@@ -86,7 +86,7 @@ memory_forget → 随时删除(删除始终是人的动作)
86
86
 
87
87
  自动规则对**低频但关键**的记忆(长期约定、判据、委托)够不着:它们不会被反复检索,够不到阈值;勉强够到也会被 30 天撤下。这类走显式路径——在 `memory_save` / `memory_update` 里给 `injected` 即钉住,写的是与面板开关同一套语义(`injectedAuto: false`),此后不受两条自动规则影响。未审核与已隔离的记录不接受注入。
88
88
 
89
- 注入有**字符预算**(默认 1500,config `injectionBudget`):装不下的条目**整条丢弃**(不截内容),按「最近更新优先」取舍——所以 `injected: true` 不等于「每轮真的在场」,它只保证有资格排队。0.9.0 起这种出局不再无声:注入末尾会追加一行 `(另有 N 条常驻因预算未注入:id1, id2, …)`,**清理干净即自行消失**;面板的注入预览里也能展开看明细。诊断行本身不占预算。
89
+ 注入有**字符预算**(默认 1500,config `injectionBudget`):装不下的条目**整条丢弃**(不截内容),按「最近更新优先」取舍——所以 `injected: true` 不等于「每轮真的在场」,它只保证有资格排队。0.9.0 起这种出局不再无声:注入末尾会追加一行 `(另有 N 条常驻因预算未注入:…)`,0.9.1 起列出的是**每条的短摘要**而不是 id——查 id 是什么的那一步最容易省略,省略了就等于没报;**清理干净即自行消失**。面板的注入预览里也能展开看明细。诊断行本身不占预算。
90
90
 
91
91
  记忆还可声明**有效性锚点**(环境变量 / 工具清单 / 插件版本):所绑的值变化后,这条记忆被标记 `stale` 并撤下常驻,检索结果里也带出失效提示——环境变了,旧结论就不再被当成仍然正确。
92
92
 
@@ -9,8 +9,10 @@ import type { MemoryRecord } from './engine.ts';
9
9
  export declare const DEFAULT_SUMMARY_CHARS = 80;
10
10
  /** 注入预算(字符):0.5.2 起默认开启,防常驻注入随记忆增长膨胀上下文。 */
11
11
  export declare const DEFAULT_INJECTION_BUDGET = 1500;
12
- /** 诊断行列出的 id 上限(2026-09-18):超出只列前 N 个,防这行本身失控。 */
13
- export declare const OMITTED_ID_LIMIT = 12;
12
+ /** 诊断行列出的条数上限(2026-09-18):超出只列前 N 个,防这行本身失控。 */
13
+ export declare const OMITTED_NOTICE_LIMIT = 12;
14
+ /** 诊断行里每条出局者的摘要长度(2026-09-18):够认出是哪条即可。 */
15
+ export declare const OMITTED_SUMMARY_CHARS = 24;
14
16
  /**
15
17
  * 确定性摘要:取首行,超过 maxChars 截断加省略号。
16
18
  * 空内容/空首行回退为去掉换行后的前 maxChars(保证 any 内容有摘要)。
@@ -26,13 +28,14 @@ export interface InjectionRender {
26
28
  /** 因预算被省略的候选条数(0 = 全部注入)。 */
27
29
  omitted: number;
28
30
  /**
29
- * 被省略条目的明细:`id` 供预算诊断行与后续清理定位,`line` 与 {@link lines}
30
- * 同格式,供面板明细直接渲染。诊断行**不占预算**——它由 `recallText` 追加在
31
- * 注入行之后,不参与这里的截断。
31
+ * 被省略条目的明细:`summary` 供预算诊断行报出「是哪条」,`line` 与
32
+ * {@link lines} 同格式、供面板明细直接渲染,`id` 备用。诊断行**不占预算**——
33
+ * 它由 `recallText` 追加在注入行之后,不参与这里的截断。
32
34
  */
33
35
  omittedRecords: Array<{
34
36
  id: string;
35
37
  line: string;
38
+ summary: string;
36
39
  }>;
37
40
  /** 实际注入的字符数(摘要 + 标记开销之和;不含 {@link omittedRecords})。 */
38
41
  chars: number;
@@ -44,8 +47,10 @@ export interface InjectionRender {
44
47
  */
45
48
  export declare function renderInjection(records: readonly MemoryRecord[], budget: number | null, summaryChars: number): InjectionRender;
46
49
  /**
47
- * 预算诊断行(2026-09-18):列 id 而非摘要——列全文要约 4000 字符,id 列表约
48
- * 100 字符。**不占注入预算**(调用方把它追加在注入行之后),清理干净后自行消失
49
- * (`omitted === 0` 返回空串);超出 {@link OMITTED_ID_LIMIT} 只列前 N 个。
50
+ * 预算诊断行(2026-09-18):列出被预算挡在外面的条目,**带短摘要而不是只有 id**——
51
+ * 「主动去查这个 id 是什么」正是最容易省略的那一步,而省略它就等于看不出来。
52
+ * 只报出局者、不报进场者(后者本来就在注入列表里)。**不占注入预算**(调用方把它
53
+ * 追加在注入行之后),清理干净后自行消失(`omitted === 0` 返回空串);超出
54
+ * {@link OMITTED_NOTICE_LIMIT} 只列前 N 个。
50
55
  */
51
56
  export declare function omittedNotice(rendered: InjectionRender): string;
package/dist/injection.js CHANGED
@@ -8,8 +8,10 @@
8
8
  export const DEFAULT_SUMMARY_CHARS = 80;
9
9
  /** 注入预算(字符):0.5.2 起默认开启,防常驻注入随记忆增长膨胀上下文。 */
10
10
  export const DEFAULT_INJECTION_BUDGET = 1500;
11
- /** 诊断行列出的 id 上限(2026-09-18):超出只列前 N 个,防这行本身失控。 */
12
- export const OMITTED_ID_LIMIT = 12;
11
+ /** 诊断行列出的条数上限(2026-09-18):超出只列前 N 个,防这行本身失控。 */
12
+ export const OMITTED_NOTICE_LIMIT = 12;
13
+ /** 诊断行里每条出局者的摘要长度(2026-09-18):够认出是哪条即可。 */
14
+ export const OMITTED_SUMMARY_CHARS = 24;
13
15
  /** 单条注入行的固定标记开销(不含摘要本体)。 */
14
16
  const LINE_OVERHEAD = 27;
15
17
  /**
@@ -46,7 +48,11 @@ export function renderInjection(records, budget, summaryChars) {
46
48
  const cost = text.length + LINE_OVERHEAD;
47
49
  if (budget !== null && budget > 0 && chars + cost > budget) {
48
50
  omitted++;
49
- omittedRecords.push({ id: String(record.id), line: text });
51
+ omittedRecords.push({
52
+ id: String(record.id),
53
+ line: text,
54
+ summary: deriveSummary(record.content, OMITTED_SUMMARY_CHARS),
55
+ });
50
56
  continue;
51
57
  }
52
58
  lines.push(text);
@@ -55,15 +61,17 @@ export function renderInjection(records, budget, summaryChars) {
55
61
  return { lines, budget: budget ?? null, omitted, omittedRecords, chars };
56
62
  }
57
63
  /**
58
- * 预算诊断行(2026-09-18):列 id 而非摘要——列全文要约 4000 字符,id 列表约
59
- * 100 字符。**不占注入预算**(调用方把它追加在注入行之后),清理干净后自行消失
60
- * (`omitted === 0` 返回空串);超出 {@link OMITTED_ID_LIMIT} 只列前 N 个。
64
+ * 预算诊断行(2026-09-18):列出被预算挡在外面的条目,**带短摘要而不是只有 id**——
65
+ * 「主动去查这个 id 是什么」正是最容易省略的那一步,而省略它就等于看不出来。
66
+ * 只报出局者、不报进场者(后者本来就在注入列表里)。**不占注入预算**(调用方把它
67
+ * 追加在注入行之后),清理干净后自行消失(`omitted === 0` 返回空串);超出
68
+ * {@link OMITTED_NOTICE_LIMIT} 只列前 N 个。
61
69
  */
62
70
  export function omittedNotice(rendered) {
63
71
  if (rendered.omitted === 0)
64
72
  return '';
65
- const ids = rendered.omittedRecords.map(record => String(record.id).slice(0, 8));
66
- const shown = ids.slice(0, OMITTED_ID_LIMIT);
67
- const truncated = ids.length > shown.length ? '…' : '';
68
- return `(另有 ${rendered.omitted} 条常驻因预算未注入:${shown.join(', ')}${truncated})`;
73
+ const shown = rendered.omittedRecords.slice(0, OMITTED_NOTICE_LIMIT);
74
+ const labels = shown.map(record => record.summary);
75
+ const truncated = rendered.omittedRecords.length > shown.length ? '…' : '';
76
+ return `(另有 ${rendered.omitted} 条常驻因预算未注入:${labels.join('、')}${truncated})`;
69
77
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@max-null/dsh-memory",
3
- "version": "0.9.0",
3
+ "version": "0.9.1",
4
4
  "description": "Cross-session plaintext memory plugin for the DeepSeek Harness — deterministic BM25 recall, writes take effect immediately, signal-driven injection, no embeddings",
5
5
  "license": "MIT",
6
6
  "publishConfig": {