@lmzhen/dsh-tool-memory 0.1.0-rc.4 → 0.1.0-rc.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js CHANGED
@@ -11,6 +11,33 @@ const inject = [
11
11
  "systemPrompt",
12
12
  "memory"
13
13
  ];
14
+ /**
15
+ * System-prompt memory guidance, aligned with Hermes `MEMORY_GUIDANCE`.
16
+ * Reached by the model every turn, so it is the place to steer behavior: what
17
+ * to save durably, what not to save, and how to phrase an entry. The tool
18
+ * schema description (`MEMORY_TOOL_DESCRIPTION`) carries the complementary
19
+ * operation-level guidance (add/replace/remove, batch, targets, when).
20
+ */
21
+ const MEMORY_GUIDANCE = "You have durable memory across sessions. Save stable user preferences, environment facts, conventions, and tool quirks with the `memory` tool. The most valuable memory is one that stops the user correcting or reminding you again, so user preferences and recurring corrections outrank procedural task details.\nWrite entries as declarative facts, not instructions to yourself: \"User prefers concise responses\" (good); \"Always respond concisely\" (bad). Imperative phrasing is re-read as a directive in later sessions and can override the user’s current request.\nDo NOT save task progress, session outcomes, completed-work logs, PR/issue numbers, commit SHAs, or anything stale within a week — use `session_search` to recall past sessions instead. Reusable procedures belong in a skill, not memory.";
22
+ /**
23
+ * Tool-schema description for `memory`, aligned with Hermes `MEMORY_SCHEMA`.
24
+ * Carries the operation-level guidance: how to batch, when to save, the
25
+ * priority order, the target semantics, and what to skip. Reached only when
26
+ * the model is choosing/using the tool, so it complements the always-on
27
+ * `MEMORY_GUIDANCE` system prompt.
28
+ */
29
+ const MEMORY_TOOL_DESCRIPTION = "Save durable facts to persistent memory that survive across sessions. Memory is injected into future turns, so keep entries compact and high-signal.\n\nHOW: make all changes in ONE call via an `operations` array (each item {action, content?, old_text?}). The batch applies atomically and the char limit is checked on the final result — so one call can remove/replace stale entries to free room AND add new ones. Use bare action/content/old_text only for a single lone change.\n\nWHEN: save proactively when the user states a preference, correction, or personal detail, or you learn a stable fact about their environment, conventions, or workflow. Priority: user preferences & corrections > environment facts > procedures. The best memory stops the user repeating themselves.\n\nTARGETS: \"user\" = who the user is (name, role, preferences, style). \"memory\" = your notes (environment, conventions, tool quirks, lessons).\n\nSKIP: trivial/obvious info, easily re-discovered facts, task progress, completed-work logs, temporary TODO state. To recall a past session use `session_search`, not memory. Reusable procedures belong in a skill, not memory.";
30
+ /**
31
+ * The requesting session's effective approval policy, mirroring
32
+ * `dsh-user-approval` (override ?? configured default). Returns undefined when
33
+ * the approval service is not mounted or no session is available — callers
34
+ * keep their previous behavior.
35
+ */
36
+ function effectiveSessionPolicy(ctx, session) {
37
+ const approval = ctx.get("approval");
38
+ if (!approval || session === void 0) return void 0;
39
+ return approval.overrideOf(session) ?? approval.config.policy ?? "ask";
40
+ }
14
41
  const Config = z.object({
15
42
  memoryEnabled: z.boolean().default(true),
16
43
  entryPreviewChars: z.number().default(200)
@@ -21,7 +48,7 @@ async function apply(ctx, rawConfig) {
21
48
  ctx.systemPrompt.section({
22
49
  name: "evolution:memory-guidance",
23
50
  order: 150,
24
- text: "You have durable memory. Save stable user preferences and environment facts with the `memory` tool. Prefer one atomic `operations` batch."
51
+ text: MEMORY_GUIDANCE
25
52
  });
26
53
  ctx.systemPrompt.context({
27
54
  name: "evolution:memory-snapshot",
@@ -45,7 +72,7 @@ async function apply(ctx, rawConfig) {
45
72
  }
46
73
  ctx.tools.register(defineTool({
47
74
  name: "memory",
48
- description: "Save durable facts to persistent memory. target \"user\" = who the user is; target \"memory\" = your notes. Use operations for atomic add/replace/remove. Save proactively; do not save task progress or one-off narratives.",
75
+ description: MEMORY_TOOL_DESCRIPTION,
49
76
  parameters: {
50
77
  target: {
51
78
  type: "string",
@@ -121,6 +148,25 @@ async function apply(ctx, rawConfig) {
121
148
  },
122
149
  isConcurrencySafe: () => false,
123
150
  async execute(args, exec) {
151
+ const conflict = (a) => {
152
+ if (a.facts === void 0 || a.content === void 0) return false;
153
+ return a.facts !== a.content;
154
+ };
155
+ if (Array.isArray(args.operations)) {
156
+ for (const op of args.operations) if (conflict(op)) return {
157
+ ok: false,
158
+ message: "Provide only one of facts or content per operation (same field); different values were given.",
159
+ entries: [],
160
+ chars: 0,
161
+ limit: 0
162
+ };
163
+ } else if (conflict(args)) return {
164
+ ok: false,
165
+ message: "Provide only one of facts or content (same field); different values were given.",
166
+ entries: [],
167
+ chars: 0,
168
+ limit: 0
169
+ };
124
170
  const target = args.target === "user" ? "user" : "memory";
125
171
  const normalized = Array.isArray(args.operations) ? {
126
172
  target,
@@ -132,13 +178,15 @@ async function apply(ctx, rawConfig) {
132
178
  old_text: args.old_text
133
179
  };
134
180
  const origin = exec.agent?.session.header.origin === "subagent" ? "background_review" : "foreground";
181
+ const sessionPolicy = effectiveSessionPolicy(ctx, exec.agent?.session);
135
182
  const approval = ctx.get("evolutionApproval");
136
183
  if (approval) {
137
184
  const decision = await approval.request({
138
185
  kind: "memory",
139
186
  summary: `memory ${target} ${Array.isArray(args.operations) ? `${args.operations.length} ops` : args.action ?? "add"}`,
140
187
  args: normalized,
141
- origin
188
+ origin,
189
+ ...sessionPolicy !== void 0 ? { sessionPolicy } : {}
142
190
  });
143
191
  if (decision.action === "staged") return {
144
192
  ok: true,
@@ -158,4 +206,4 @@ async function apply(ctx, rawConfig) {
158
206
  });
159
207
  }
160
208
  //#endregion
161
- export { Config, apply, inject, name };
209
+ export { Config, MEMORY_GUIDANCE, MEMORY_TOOL_DESCRIPTION, apply, inject, name };
@@ -6,6 +6,22 @@ import type { Context } from '@deepseek-ai/cordis';
6
6
  import z from '@deepseek-ai/schemastery';
7
7
  export declare const name = "tool-memory";
8
8
  export declare const inject: string[];
9
+ /**
10
+ * System-prompt memory guidance, aligned with Hermes `MEMORY_GUIDANCE`.
11
+ * Reached by the model every turn, so it is the place to steer behavior: what
12
+ * to save durably, what not to save, and how to phrase an entry. The tool
13
+ * schema description (`MEMORY_TOOL_DESCRIPTION`) carries the complementary
14
+ * operation-level guidance (add/replace/remove, batch, targets, when).
15
+ */
16
+ export declare const MEMORY_GUIDANCE: string;
17
+ /**
18
+ * Tool-schema description for `memory`, aligned with Hermes `MEMORY_SCHEMA`.
19
+ * Carries the operation-level guidance: how to batch, when to save, the
20
+ * priority order, the target semantics, and what to skip. Reached only when
21
+ * the model is choosing/using the tool, so it complements the always-on
22
+ * `MEMORY_GUIDANCE` system prompt.
23
+ */
24
+ export declare const MEMORY_TOOL_DESCRIPTION: string;
9
25
  export interface Config {
10
26
  memoryEnabled?: boolean;
11
27
  /** Maximum characters of each memory entry echoed back in tool results. */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lmzhen/dsh-tool-memory",
3
3
  "description": "Model-facing memory tool and prompt context (community build)",
4
- "version": "0.1.0-rc.4",
4
+ "version": "0.1.0-rc.41",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -39,15 +39,15 @@
39
39
  "@deepseek-ai/cordis": "^4.0.1",
40
40
  "@deepseek-ai/dsh-tools": "^0.1.0-rc.6",
41
41
  "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6",
42
- "@lmzhen/dsh-memory": "^0.1.0-rc.4",
43
- "@lmzhen/dsh-memory-files": "^0.1.0-rc.4"
42
+ "@lmzhen/dsh-memory": "^0.1.0-rc.41",
43
+ "@lmzhen/dsh-memory-files": "^0.1.0-rc.41"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6",
47
47
  "@deepseek-ai/dsh-tools": "^0.1.0-rc.6",
48
48
  "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6",
49
49
  "@deepseek-ai/dsh-agent-loop-testkit": "^0.1.0-rc.6",
50
- "@lmzhen/dsh-memory": "^0.1.0-rc.4",
51
- "@lmzhen/dsh-memory-files": "^0.1.0-rc.4"
50
+ "@lmzhen/dsh-memory": "^0.1.0-rc.41",
51
+ "@lmzhen/dsh-memory-files": "^0.1.0-rc.41"
52
52
  }
53
53
  }