@lmzhen/dsh-tool-memory 0.1.0-rc.4 → 0.1.0-rc.40
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 +52 -4
- package/lib/types/index.d.ts +16 -0
- package/package.json +5 -5
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:
|
|
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:
|
|
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 };
|
package/lib/types/index.d.ts
CHANGED
|
@@ -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
|
+
"version": "0.1.0-rc.40",
|
|
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.
|
|
43
|
-
"@lmzhen/dsh-memory-files": "^0.1.0-rc.
|
|
42
|
+
"@lmzhen/dsh-memory": "^0.1.0-rc.40",
|
|
43
|
+
"@lmzhen/dsh-memory-files": "^0.1.0-rc.40"
|
|
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.
|
|
51
|
-
"@lmzhen/dsh-memory-files": "^0.1.0-rc.
|
|
50
|
+
"@lmzhen/dsh-memory": "^0.1.0-rc.40",
|
|
51
|
+
"@lmzhen/dsh-memory-files": "^0.1.0-rc.40"
|
|
52
52
|
}
|
|
53
53
|
}
|