@lmzhen/dsh-tool-memory 0.1.0-rc.5 → 0.1.0-rc.50
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 +212 -7
- package/lib/types/index.d.ts +16 -0
- package/package.json +5 -5
package/lib/index.js
CHANGED
|
@@ -1,19 +1,203 @@
|
|
|
1
1
|
import z from "@deepseek-ai/schemastery";
|
|
2
2
|
import { defineTool } from "@deepseek-ai/dsh-tools";
|
|
3
|
+
import { createHash } from "node:crypto";
|
|
4
|
+
//#region ../evolution-core/src/prompts.ts
|
|
5
|
+
/**
|
|
6
|
+
* Review and curation prompts adapted from Hermes Agent
|
|
7
|
+
* `agent/background_review.py`, `agent/curator.py`, and
|
|
8
|
+
* `agent/learn_prompt.py`, with tool names translated to the DSH-native
|
|
9
|
+
* catalog (`memory`, `skill_manage`, `skill`, `bash`, `str_replace_editor`).
|
|
10
|
+
*
|
|
11
|
+
* Every prompt is pinned in a versioned bundle. Review workers verify the
|
|
12
|
+
* bundle digest before spending a model call, so a partially-patched
|
|
13
|
+
* deployment fails closed instead of silently running a truncated prompt.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Prompt bundle identity. Bump both id and version whenever a prompt's text
|
|
17
|
+
* changes semantically: the bundle digest is the fail-closed signal for
|
|
18
|
+
* review workers, so a stale id across deployments must be distinguishable.
|
|
19
|
+
*/
|
|
20
|
+
const PROMPT_BUNDLE_ID = "dsh-evolution@3";
|
|
21
|
+
const MEMORY_REVIEW_PROMPT = `[Auto-review — Memory]
|
|
22
|
+
Review the conversation above and consider saving to memory if appropriate.
|
|
23
|
+
|
|
24
|
+
Focus on:
|
|
25
|
+
1. Has the user revealed things about themselves — persona, desires, preferences, or personal details worth remembering?
|
|
26
|
+
2. Has the user expressed expectations about how you should behave, their work style, or ways they want you to operate?
|
|
27
|
+
|
|
28
|
+
If something stands out, save it using the memory tool.
|
|
29
|
+
If nothing is worth saving, just say "Nothing to save." and stop.`;
|
|
30
|
+
const SKILL_REVIEW_PROMPT = `[Auto-review — Skills]
|
|
31
|
+
Review the conversation above and update the skill library. Be ACTIVE — most sessions produce at least one skill update, even if small.
|
|
32
|
+
|
|
33
|
+
Target shape: CLASS-LEVEL skills with a rich SKILL.md and a references/ directory for session-specific detail. Not a flat list of narrow one-session skills.
|
|
34
|
+
|
|
35
|
+
Signals that warrant action:
|
|
36
|
+
- The user corrected your style, tone, format, verbosity, workflow, or approach.
|
|
37
|
+
- A non-trivial technique, fix, workaround, or debugging path emerged.
|
|
38
|
+
- A loaded skill turned out wrong, missing, or outdated — patch it now.
|
|
39
|
+
|
|
40
|
+
Only update skills you loaded or read in THIS session; never touch skills you have not read.
|
|
41
|
+
|
|
42
|
+
Preference order:
|
|
43
|
+
1. Patch a skill that was loaded or read this session.
|
|
44
|
+
2. Patch an existing umbrella skill.
|
|
45
|
+
3. Add references/, templates/, or scripts/ support under an existing skill.
|
|
46
|
+
4. Create a new class-level umbrella skill only when nothing fits.
|
|
47
|
+
|
|
48
|
+
Protected skills (bundled/hub-installed) must not be edited. Pinned skills are read-only to the background review: the pinned write guard refuses background changes, so only the foreground may update or archive them.
|
|
49
|
+
|
|
50
|
+
Do NOT capture:
|
|
51
|
+
- Environment-dependent failures (missing binaries, unconfigured credentials).
|
|
52
|
+
- Negative claims about tools ("browser tools do not work").
|
|
53
|
+
- Transient errors that resolved during the session.
|
|
54
|
+
- One-off task narratives.
|
|
55
|
+
|
|
56
|
+
If a tool failed because of setup state, capture the FIX under an existing setup skill — never "this tool does not work" as a standalone constraint.
|
|
57
|
+
|
|
58
|
+
"Nothing to save." is a real option but should NOT be the default.`;
|
|
59
|
+
const COMBINED_REVIEW_PROMPT = `[Auto-review]
|
|
60
|
+
Review the conversation above and update two things.
|
|
61
|
+
|
|
62
|
+
**Memory**: who the user is. Save durable user preferences, personal details, and expectations with the memory tool.
|
|
63
|
+
|
|
64
|
+
**Skills**: how to do this class of task. Be ACTIVE. Only update skills you loaded or read in THIS session. Follow the same class-level umbrella policy, preference order, protected-skill rules, and do-not-capture list as a skill review.
|
|
65
|
+
|
|
66
|
+
Act on whichever dimension has real signal. If genuinely nothing stands out on either, say "Nothing to save." and stop — but don't reach for that conclusion as a default.`;
|
|
67
|
+
const CURATOR_PROMPT = `You are the skill curator. Maintain a healthy, class-level skill library, not a flat pile of narrow one-session skills.
|
|
68
|
+
|
|
69
|
+
The goal is a LIBRARY OF CLASS-LEVEL INSTRUCTIONS. A skill collection of many narrow skills where each captures one session's specific bug is a FAILURE of the library. An agent searching skills matches on descriptions, not exact names; one broad umbrella with labeled subsections beats five narrow siblings for discoverability.
|
|
70
|
+
|
|
71
|
+
Right target shape: class-level skills with rich SKILL.md + references/, templates/, scripts/ support files for session-specific detail.
|
|
72
|
+
|
|
73
|
+
Hard rules:
|
|
74
|
+
1. NEVER hard-delete a skill. Archive (moving to .archive/) is the maximum destructive action; archives are recoverable, deletion is not.
|
|
75
|
+
2. Do not touch bundled, hub-installed, pinned, or scheduled-task-referenced (\`referenced\`) skills. Referenced skills MAY be consolidated into an umbrella, but never simply pruned.
|
|
76
|
+
3. Do not archive recently-created or never-used skills without strong evidence. "use=0" is NOT evidence either way — it only means the trigger has not come up yet.
|
|
77
|
+
4. Do NOT reject consolidation on the grounds that "each skill has a distinct trigger". The right bar is: would a human maintainer write this as N separate skills, or one skill with N labeled subsections? When the answer is the latter, merge.
|
|
78
|
+
5. Judge overlap on CONTENT, not on usage counters.
|
|
79
|
+
6. Before archiving a merged skill, ensure its unique content was preserved in the umbrella.
|
|
80
|
+
|
|
81
|
+
How to work:
|
|
82
|
+
1. Scan the candidate list. Identify PREFIX CLUSTERS — skills sharing a first word or domain keyword (expect 10-25 clusters).
|
|
83
|
+
2. For each cluster with 2+ members, ask "what is the UMBRELLA CLASS these skills serve?" and consolidate:
|
|
84
|
+
a. MERGE INTO AN EXISTING UMBRELLA (patch a labeled section for each sibling's unique insight, then archive the siblings).
|
|
85
|
+
b. CREATE A NEW UMBRELLA SKILL.md covering the shared workflow with short labeled subsections, then archive the absorbed siblings.
|
|
86
|
+
c. DEMOTE session-specific detail to references/, templates/, or scripts/ under the umbrella.
|
|
87
|
+
3. Keep the umbrella body tight and scannable: exact commands, verbatim paths, ~100-200 lines; never invent flags or APIs.
|
|
88
|
+
|
|
89
|
+
Produce a YAML summary with exactly this shape:
|
|
90
|
+
consolidations:
|
|
91
|
+
- from: <old-skill-name>
|
|
92
|
+
into: <umbrella-skill-name>
|
|
93
|
+
reason: <one short sentence>
|
|
94
|
+
prunings:
|
|
95
|
+
- name: <skill-name>
|
|
96
|
+
reason: <one short sentence>
|
|
97
|
+
Nominate a pruning only when archival is clearly safe (stale AND genuinely obsolete or fully absorbed elsewhere).`;
|
|
98
|
+
const COMPLETION_SKILL_REVIEW_PROMPT = `[Auto-review — Skills · task complete]
|
|
99
|
+
Your current task now appears complete. Before wrapping up, review the approach and update the skill library via skill_manage.
|
|
100
|
+
|
|
101
|
+
Follow the skills review policy: be ACTIVE, prefer class-level umbrellas, patch ONLY skills loaded or read this session, and capture non-trivial techniques and user corrections. Do NOT capture environment-dependent failures, negative claims about tools, or one-off task narratives.
|
|
102
|
+
|
|
103
|
+
Do NOT modify output files or re-run the task. If you are still mid-task, ignore this.`;
|
|
104
|
+
function sha256(text) {
|
|
105
|
+
return createHash("sha256").update(text).digest("hex");
|
|
106
|
+
}
|
|
107
|
+
function createPromptBundle(prompts) {
|
|
108
|
+
const canonical = JSON.stringify({
|
|
109
|
+
id: PROMPT_BUNDLE_ID,
|
|
110
|
+
version: 3,
|
|
111
|
+
prompts: Object.fromEntries(Object.entries(prompts).sort())
|
|
112
|
+
});
|
|
113
|
+
return Object.freeze({
|
|
114
|
+
id: PROMPT_BUNDLE_ID,
|
|
115
|
+
version: 3,
|
|
116
|
+
prompts: Object.freeze({ ...prompts }),
|
|
117
|
+
sha256: sha256(canonical)
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
createPromptBundle({
|
|
121
|
+
memory: MEMORY_REVIEW_PROMPT,
|
|
122
|
+
skill: SKILL_REVIEW_PROMPT,
|
|
123
|
+
combined: COMBINED_REVIEW_PROMPT,
|
|
124
|
+
curator: CURATOR_PROMPT,
|
|
125
|
+
completion: COMPLETION_SKILL_REVIEW_PROMPT
|
|
126
|
+
});
|
|
127
|
+
//#endregion
|
|
128
|
+
//#region ../evolution-core/src/threats.ts
|
|
129
|
+
const FILLER = String.raw`(?:\w+\s+){0,8}`;
|
|
130
|
+
new RegExp(String.raw`ignore\s+${FILLER}(?:previous|above|prior|all)\s+${FILLER}instructions`, "i"), new RegExp(String.raw`new\s+${FILLER}system\s+${FILLER}prompt`, "i"), new RegExp(String.raw`forget\s+${FILLER}(?:everything|all)\s+${FILLER}(?:discussed|you\s+know)`, "i"), new RegExp(String.raw`you\s+have\s+been\s+${FILLER}(?:updated|upgraded|patched)\s+to`, "i"), new RegExp(String.raw`do\s+not\s+${FILLER}tell\s+${FILLER}the\s+user`, "i"), new RegExp(String.raw`output\s+${FILLER}(?:system|initial)\s+prompt`, "i");
|
|
131
|
+
//#endregion
|
|
132
|
+
//#region ../evolution-core/src/skill-store.ts
|
|
133
|
+
/**
|
|
134
|
+
* Map a requesting session onto the two origin surfaces (rc.44 plan M2-2.3):
|
|
135
|
+
* the APPROVAL surface treats every delegated subagent as the autonomous
|
|
136
|
+
* review channel, while the LIBRARY surface keeps the Hermes distinction -
|
|
137
|
+
* the review fork is 'background_review' (the pinned guard blocks its
|
|
138
|
+
* writes) and any other subagent is 'subagent' (agent-authored, not
|
|
139
|
+
* review-channel). `isReview` marks the caller as the background review
|
|
140
|
+
* pipeline itself. Single source: the two tools and the review executor all
|
|
141
|
+
* read this table instead of re-deriving it.
|
|
142
|
+
*/
|
|
143
|
+
function resolveOrigins(headerOrigin, isReview = false) {
|
|
144
|
+
if (isReview) return {
|
|
145
|
+
approval: "background_review",
|
|
146
|
+
library: "background_review"
|
|
147
|
+
};
|
|
148
|
+
if (headerOrigin === "subagent") return {
|
|
149
|
+
approval: "background_review",
|
|
150
|
+
library: "subagent"
|
|
151
|
+
};
|
|
152
|
+
return {
|
|
153
|
+
approval: "foreground",
|
|
154
|
+
library: "foreground"
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
//#endregion
|
|
3
158
|
//#region lib/types/index.js
|
|
4
159
|
/**
|
|
5
160
|
* Model-facing memory tool and runtime-context memory snapshot.
|
|
6
161
|
* @module @lmzhen/dsh-tool-memory
|
|
7
162
|
*/
|
|
8
163
|
const name = "tool-memory";
|
|
164
|
+
/** Max characters of each echoed memory entry (single source for the Config default and the runtime slice). */
|
|
165
|
+
const DEFAULT_ENTRY_PREVIEW_CHARS = 200;
|
|
9
166
|
const inject = [
|
|
10
167
|
"tools",
|
|
11
168
|
"systemPrompt",
|
|
12
169
|
"memory"
|
|
13
170
|
];
|
|
171
|
+
/**
|
|
172
|
+
* System-prompt memory guidance, aligned with Hermes `MEMORY_GUIDANCE`.
|
|
173
|
+
* Reached by the model every turn, so it is the place to steer behavior: what
|
|
174
|
+
* to save durably, what not to save, and how to phrase an entry. The tool
|
|
175
|
+
* schema description (`MEMORY_TOOL_DESCRIPTION`) carries the complementary
|
|
176
|
+
* operation-level guidance (add/replace/remove, batch, targets, when).
|
|
177
|
+
*/
|
|
178
|
+
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.";
|
|
179
|
+
/**
|
|
180
|
+
* Tool-schema description for `memory`, aligned with Hermes `MEMORY_SCHEMA`.
|
|
181
|
+
* Carries the operation-level guidance: how to batch, when to save, the
|
|
182
|
+
* priority order, the target semantics, and what to skip. Reached only when
|
|
183
|
+
* the model is choosing/using the tool, so it complements the always-on
|
|
184
|
+
* `MEMORY_GUIDANCE` system prompt.
|
|
185
|
+
*/
|
|
186
|
+
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.";
|
|
187
|
+
/**
|
|
188
|
+
* The requesting session's effective approval policy, mirroring
|
|
189
|
+
* `dsh-user-approval` (override ?? configured default). Returns undefined when
|
|
190
|
+
* the approval service is not mounted or no session is available — callers
|
|
191
|
+
* keep their previous behavior.
|
|
192
|
+
*/
|
|
193
|
+
function effectiveSessionPolicy(ctx, session) {
|
|
194
|
+
const approval = ctx.get("approval");
|
|
195
|
+
if (!approval || session === void 0) return void 0;
|
|
196
|
+
return approval.overrideOf(session) ?? approval.config.policy ?? "ask";
|
|
197
|
+
}
|
|
14
198
|
const Config = z.object({
|
|
15
199
|
memoryEnabled: z.boolean().default(true),
|
|
16
|
-
entryPreviewChars: z.number().default(
|
|
200
|
+
entryPreviewChars: z.number().default(DEFAULT_ENTRY_PREVIEW_CHARS)
|
|
17
201
|
});
|
|
18
202
|
async function apply(ctx, rawConfig) {
|
|
19
203
|
if (!rawConfig.memoryEnabled) return;
|
|
@@ -21,7 +205,7 @@ async function apply(ctx, rawConfig) {
|
|
|
21
205
|
ctx.systemPrompt.section({
|
|
22
206
|
name: "evolution:memory-guidance",
|
|
23
207
|
order: 150,
|
|
24
|
-
text:
|
|
208
|
+
text: MEMORY_GUIDANCE
|
|
25
209
|
});
|
|
26
210
|
ctx.systemPrompt.context({
|
|
27
211
|
name: "evolution:memory-snapshot",
|
|
@@ -38,14 +222,14 @@ async function apply(ctx, rawConfig) {
|
|
|
38
222
|
return {
|
|
39
223
|
ok: result.ok,
|
|
40
224
|
message: result.message,
|
|
41
|
-
entries: result.entries.map((entry) => entry.slice(0, rawConfig.entryPreviewChars ??
|
|
225
|
+
entries: result.entries.map((entry) => entry.slice(0, rawConfig.entryPreviewChars ?? DEFAULT_ENTRY_PREVIEW_CHARS)),
|
|
42
226
|
chars: result.chars,
|
|
43
227
|
limit: result.limit
|
|
44
228
|
};
|
|
45
229
|
}
|
|
46
230
|
ctx.tools.register(defineTool({
|
|
47
231
|
name: "memory",
|
|
48
|
-
description:
|
|
232
|
+
description: MEMORY_TOOL_DESCRIPTION,
|
|
49
233
|
parameters: {
|
|
50
234
|
target: {
|
|
51
235
|
type: "string",
|
|
@@ -121,6 +305,25 @@ async function apply(ctx, rawConfig) {
|
|
|
121
305
|
},
|
|
122
306
|
isConcurrencySafe: () => false,
|
|
123
307
|
async execute(args, exec) {
|
|
308
|
+
const conflict = (a) => {
|
|
309
|
+
if (a.facts === void 0 || a.content === void 0) return false;
|
|
310
|
+
return a.facts !== a.content;
|
|
311
|
+
};
|
|
312
|
+
if (Array.isArray(args.operations)) {
|
|
313
|
+
for (const op of args.operations) if (conflict(op)) return {
|
|
314
|
+
ok: false,
|
|
315
|
+
message: "Provide only one of facts or content per operation (same field); different values were given.",
|
|
316
|
+
entries: [],
|
|
317
|
+
chars: 0,
|
|
318
|
+
limit: 0
|
|
319
|
+
};
|
|
320
|
+
} else if (conflict(args)) return {
|
|
321
|
+
ok: false,
|
|
322
|
+
message: "Provide only one of facts or content (same field); different values were given.",
|
|
323
|
+
entries: [],
|
|
324
|
+
chars: 0,
|
|
325
|
+
limit: 0
|
|
326
|
+
};
|
|
124
327
|
const target = args.target === "user" ? "user" : "memory";
|
|
125
328
|
const normalized = Array.isArray(args.operations) ? {
|
|
126
329
|
target,
|
|
@@ -131,14 +334,16 @@ async function apply(ctx, rawConfig) {
|
|
|
131
334
|
facts: args.facts ?? args.content,
|
|
132
335
|
old_text: args.old_text
|
|
133
336
|
};
|
|
134
|
-
const origin = exec.agent?.session.header.origin
|
|
337
|
+
const origin = resolveOrigins(exec.agent?.session.header.origin).approval;
|
|
338
|
+
const sessionPolicy = effectiveSessionPolicy(ctx, exec.agent?.session);
|
|
135
339
|
const approval = ctx.get("evolutionApproval");
|
|
136
340
|
if (approval) {
|
|
137
341
|
const decision = await approval.request({
|
|
138
342
|
kind: "memory",
|
|
139
343
|
summary: `memory ${target} ${Array.isArray(args.operations) ? `${args.operations.length} ops` : args.action ?? "add"}`,
|
|
140
344
|
args: normalized,
|
|
141
|
-
origin
|
|
345
|
+
origin,
|
|
346
|
+
...sessionPolicy !== void 0 ? { sessionPolicy } : {}
|
|
142
347
|
});
|
|
143
348
|
if (decision.action === "staged") return {
|
|
144
349
|
ok: true,
|
|
@@ -158,4 +363,4 @@ async function apply(ctx, rawConfig) {
|
|
|
158
363
|
});
|
|
159
364
|
}
|
|
160
365
|
//#endregion
|
|
161
|
-
export { Config, apply, inject, name };
|
|
366
|
+
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.50",
|
|
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.50",
|
|
43
|
+
"@lmzhen/dsh-memory-files": "^0.1.0-rc.50"
|
|
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.50",
|
|
51
|
+
"@lmzhen/dsh-memory-files": "^0.1.0-rc.50"
|
|
52
52
|
}
|
|
53
53
|
}
|