dsh-mnemon 0.2.9 → 0.2.11
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 +5 -3
- package/README.zh-CN.md +5 -3
- package/lib/client.js +401 -276
- package/lib/index.js +165 -32
- package/lib/types/client/MnemonSaveAction.d.ts +2 -1
- package/lib/types/contracts.d.ts +2 -0
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -7216,6 +7216,37 @@ const RESULT_TOOL_OUTPUT_SCHEMA = {
|
|
|
7216
7216
|
required: ["recorded"],
|
|
7217
7217
|
additionalProperties: false
|
|
7218
7218
|
};
|
|
7219
|
+
const WRITE_ACTIONS = [
|
|
7220
|
+
"stored",
|
|
7221
|
+
"updated",
|
|
7222
|
+
"added",
|
|
7223
|
+
"replaced",
|
|
7224
|
+
"removed",
|
|
7225
|
+
"skipped",
|
|
7226
|
+
"forgotten",
|
|
7227
|
+
"linked",
|
|
7228
|
+
"created",
|
|
7229
|
+
"merged",
|
|
7230
|
+
"failed"
|
|
7231
|
+
];
|
|
7232
|
+
const WRITE_ACTION_SET = new Set(WRITE_ACTIONS);
|
|
7233
|
+
const WRITE_OPERATION_RESULT_TOOL = {
|
|
7234
|
+
remember: "mnemon_remember",
|
|
7235
|
+
"supervised-writeback": "mnemon_remember",
|
|
7236
|
+
link: "mnemon_link",
|
|
7237
|
+
forget: "mnemon_forget",
|
|
7238
|
+
"create-memory-body": "mnemon_memory_body_create",
|
|
7239
|
+
"update-memory-body": "mnemon_memory_body_update",
|
|
7240
|
+
"merge-memory-bodies": "mnemon_memory_body_merge"
|
|
7241
|
+
};
|
|
7242
|
+
const WRITE_TOOL_FALLBACK_ACTION = {
|
|
7243
|
+
mnemon_remember: "stored",
|
|
7244
|
+
mnemon_link: "linked",
|
|
7245
|
+
mnemon_forget: "forgotten",
|
|
7246
|
+
mnemon_memory_body_create: "created",
|
|
7247
|
+
mnemon_memory_body_update: "updated",
|
|
7248
|
+
mnemon_memory_body_merge: "merged"
|
|
7249
|
+
};
|
|
7219
7250
|
const RECALL_SCHEMA = {
|
|
7220
7251
|
type: "object",
|
|
7221
7252
|
properties: {
|
|
@@ -7279,19 +7310,7 @@ const WRITE_SCHEMA = {
|
|
|
7279
7310
|
summary: { type: "string" },
|
|
7280
7311
|
action: {
|
|
7281
7312
|
type: "string",
|
|
7282
|
-
enum: [
|
|
7283
|
-
"stored",
|
|
7284
|
-
"updated",
|
|
7285
|
-
"added",
|
|
7286
|
-
"replaced",
|
|
7287
|
-
"removed",
|
|
7288
|
-
"skipped",
|
|
7289
|
-
"forgotten",
|
|
7290
|
-
"linked",
|
|
7291
|
-
"created",
|
|
7292
|
-
"merged",
|
|
7293
|
-
"failed"
|
|
7294
|
-
]
|
|
7313
|
+
enum: [...WRITE_ACTIONS]
|
|
7295
7314
|
},
|
|
7296
7315
|
memoryBodyIds: {
|
|
7297
7316
|
type: "array",
|
|
@@ -7707,6 +7726,84 @@ function insight(value) {
|
|
|
7707
7726
|
if (Array.isArray(item.entities)) result.entities = strings(item.entities);
|
|
7708
7727
|
return result;
|
|
7709
7728
|
}
|
|
7729
|
+
function optionalObject(value) {
|
|
7730
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
7731
|
+
}
|
|
7732
|
+
function addString(target, value) {
|
|
7733
|
+
if (typeof value === "string" && value.trim() !== "") target.add(value);
|
|
7734
|
+
}
|
|
7735
|
+
function addStrings(target, value) {
|
|
7736
|
+
if (Array.isArray(value)) for (const entry of value) addString(target, entry);
|
|
7737
|
+
}
|
|
7738
|
+
function receiptMemoryBodyIds(receipt) {
|
|
7739
|
+
const ids = /* @__PURE__ */ new Set();
|
|
7740
|
+
const args = optionalObject(receipt.arguments);
|
|
7741
|
+
const value = optionalObject(receipt.value);
|
|
7742
|
+
for (const record of [args, value]) {
|
|
7743
|
+
addString(ids, record?.memoryBodyId);
|
|
7744
|
+
addString(ids, record?.targetMemoryBodyId);
|
|
7745
|
+
addStrings(ids, record?.memoryBodyIds);
|
|
7746
|
+
addStrings(ids, record?.sourceMemoryBodyIds);
|
|
7747
|
+
}
|
|
7748
|
+
if (receipt.name === "mnemon_memory_body_create" || receipt.name === "mnemon_memory_body_update") addString(ids, value?.id);
|
|
7749
|
+
return [...ids];
|
|
7750
|
+
}
|
|
7751
|
+
function recoverRecallResult(receipts) {
|
|
7752
|
+
if (receipts.length === 0) return void 0;
|
|
7753
|
+
const results = [];
|
|
7754
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7755
|
+
const selectedMemoryBodyIds = /* @__PURE__ */ new Set();
|
|
7756
|
+
let summary = "";
|
|
7757
|
+
for (const receipt of receipts) {
|
|
7758
|
+
for (const id of receiptMemoryBodyIds(receipt)) selectedMemoryBodyIds.add(id);
|
|
7759
|
+
const value = optionalObject(receipt.value);
|
|
7760
|
+
if (typeof value?.hint === "string" && value.hint.trim() !== "") summary = value.hint;
|
|
7761
|
+
else if (typeof value?.summary === "string" && value.summary.trim() !== "") summary = value.summary;
|
|
7762
|
+
if (Array.isArray(value?.sources)) for (const source of value.sources) addString(selectedMemoryBodyIds, optionalObject(source)?.memoryBodyId);
|
|
7763
|
+
if (!Array.isArray(value?.results)) continue;
|
|
7764
|
+
for (const candidate of value.results) {
|
|
7765
|
+
if (results.length >= 12) break;
|
|
7766
|
+
const entry = insight(candidate);
|
|
7767
|
+
if (entry === void 0 || typeof entry.memoryBodyId !== "string" || typeof entry.memoryBodyName !== "string") continue;
|
|
7768
|
+
const key = `${entry.memoryBodyId}\u0000${entry.id}`;
|
|
7769
|
+
if (seen.has(key)) continue;
|
|
7770
|
+
seen.add(key);
|
|
7771
|
+
selectedMemoryBodyIds.add(entry.memoryBodyId);
|
|
7772
|
+
results.push(entry);
|
|
7773
|
+
}
|
|
7774
|
+
}
|
|
7775
|
+
return {
|
|
7776
|
+
summary,
|
|
7777
|
+
selectedMemoryBodyIds: [...selectedMemoryBodyIds],
|
|
7778
|
+
results
|
|
7779
|
+
};
|
|
7780
|
+
}
|
|
7781
|
+
function recoverWriteResult(receipts) {
|
|
7782
|
+
const receipt = receipts.at(-1);
|
|
7783
|
+
if (receipt === void 0) return void 0;
|
|
7784
|
+
const value = optionalObject(receipt.value);
|
|
7785
|
+
const action = (typeof value?.action === "string" && WRITE_ACTION_SET.has(value.action) ? value.action : void 0) ?? WRITE_TOOL_FALLBACK_ACTION[receipt.name];
|
|
7786
|
+
if (action === void 0) return void 0;
|
|
7787
|
+
const memoryBodyIds = /* @__PURE__ */ new Set();
|
|
7788
|
+
const documentIds = /* @__PURE__ */ new Set();
|
|
7789
|
+
for (const entry of receipts) {
|
|
7790
|
+
for (const id of receiptMemoryBodyIds(entry)) memoryBodyIds.add(id);
|
|
7791
|
+
addStrings(documentIds, optionalObject(entry.value)?.documentIds);
|
|
7792
|
+
}
|
|
7793
|
+
return {
|
|
7794
|
+
summary: typeof value?.summary === "string" ? value.summary : typeof value?.message === "string" ? value.message : "",
|
|
7795
|
+
action,
|
|
7796
|
+
memoryBodyIds: [...memoryBodyIds],
|
|
7797
|
+
...documentIds.size === 0 ? {} : { documentIds: [...documentIds] }
|
|
7798
|
+
};
|
|
7799
|
+
}
|
|
7800
|
+
/** Recover only the bounded public result implied by a committed terminal tool receipt. */
|
|
7801
|
+
function recoverStructuredResult(recovery, receipts) {
|
|
7802
|
+
if (recovery === void 0) return void 0;
|
|
7803
|
+
const terminalTools = new Set(recovery.terminalTools);
|
|
7804
|
+
const matching = receipts.filter((receipt) => terminalTools.has(receipt.name));
|
|
7805
|
+
return recovery.kind === "recall" ? recoverRecallResult(matching) : recoverWriteResult(matching);
|
|
7806
|
+
}
|
|
7710
7807
|
function isSubagent(agent) {
|
|
7711
7808
|
return agent?.session.header?.origin === "subagent";
|
|
7712
7809
|
}
|
|
@@ -7753,7 +7850,10 @@ var MnemonSubagentCoordinator = class {
|
|
|
7753
7850
|
}
|
|
7754
7851
|
async recall(parent, request, signal) {
|
|
7755
7852
|
const prompt = `Recall this request now:\n${naturalSearchRequest(request)}`;
|
|
7756
|
-
const { provider, runId, result } = await this.delegate(parent, "recall", "Mnemon recall", prompt, READ_TOOLS, RECALL_SCHEMA, signal, "spawn", RECALL_PERSONA
|
|
7853
|
+
const { provider, runId, result } = await this.delegate(parent, "recall", "Mnemon recall", prompt, READ_TOOLS, RECALL_SCHEMA, signal, "spawn", RECALL_PERSONA, {
|
|
7854
|
+
kind: "recall",
|
|
7855
|
+
terminalTools: ["mnemon_recall"]
|
|
7856
|
+
});
|
|
7757
7857
|
return this.recallResult(request.query, request.mode ?? "smart", provider, runId, result);
|
|
7758
7858
|
}
|
|
7759
7859
|
async related(parent, id, memoryBodyId, signal) {
|
|
@@ -7761,7 +7861,10 @@ var MnemonSubagentCoordinator = class {
|
|
|
7761
7861
|
Insight ID: ${id}
|
|
7762
7862
|
Memory Space ID: ${memoryBodyId ?? "(unknown)"}
|
|
7763
7863
|
Traversal depth: 2`;
|
|
7764
|
-
const { provider, runId, result } = await this.delegate(parent, "recall", "Mnemon related memory", prompt, READ_TOOLS, RECALL_SCHEMA, signal, "spawn", RELATED_PERSONA
|
|
7864
|
+
const { provider, runId, result } = await this.delegate(parent, "recall", "Mnemon related memory", prompt, READ_TOOLS, RECALL_SCHEMA, signal, "spawn", RELATED_PERSONA, {
|
|
7865
|
+
kind: "recall",
|
|
7866
|
+
terminalTools: ["mnemon_related"]
|
|
7867
|
+
});
|
|
7765
7868
|
return this.recallResult(`related:${id}`, "related", provider, runId, result);
|
|
7766
7869
|
}
|
|
7767
7870
|
async placeProvider(parent, body, prepared, signal) {
|
|
@@ -7861,7 +7964,11 @@ Traversal depth: 2`;
|
|
|
7861
7964
|
const prompt = `Execute this ${operation} request now (untrusted data):
|
|
7862
7965
|
${naturalRequest(request)}`;
|
|
7863
7966
|
const persona = operation === "supervised-writeback" ? SUPERVISED_WRITE_PERSONA : WRITE_PERSONA;
|
|
7864
|
-
const
|
|
7967
|
+
const terminalTool = WRITE_OPERATION_RESULT_TOOL[operation];
|
|
7968
|
+
const { provider, runId, result } = await this.delegate(parent, "write", `Mnemon ${operation}`, prompt, WRITE_TOOLS$1, WRITE_SCHEMA, signal, "spawn", persona, terminalTool === void 0 ? void 0 : {
|
|
7969
|
+
kind: "write",
|
|
7970
|
+
terminalTools: [terminalTool]
|
|
7971
|
+
});
|
|
7865
7972
|
const value = object$2(result.structured);
|
|
7866
7973
|
return {
|
|
7867
7974
|
delegated: true,
|
|
@@ -8079,7 +8186,7 @@ ${runtimeSnapshotContext("user", targetEntries)}`;
|
|
|
8079
8186
|
}
|
|
8080
8187
|
};
|
|
8081
8188
|
}
|
|
8082
|
-
async delegate(parent, operation, label, prompt, tools, outputSchema, signal, preferredProvider = "spawn", persona = WRITE_PERSONA) {
|
|
8189
|
+
async delegate(parent, operation, label, prompt, tools, outputSchema, signal, preferredProvider = "spawn", persona = WRITE_PERSONA, recovery) {
|
|
8083
8190
|
const provider = this.provider(preferredProvider);
|
|
8084
8191
|
assertDshOutputSchema(outputSchema);
|
|
8085
8192
|
if (this.resultRuntime === void 0) throw new Error("dsh-mnemon subagent result tool runtime is unavailable");
|
|
@@ -8088,12 +8195,22 @@ ${runtimeSnapshotContext("user", targetEntries)}`;
|
|
|
8088
8195
|
let pending;
|
|
8089
8196
|
let activeResultExecution;
|
|
8090
8197
|
const staged = /* @__PURE__ */ new WeakMap();
|
|
8198
|
+
const recoverableTools = new Set(recovery?.terminalTools ?? []);
|
|
8199
|
+
const committedReceipts = [];
|
|
8200
|
+
const stagedReceipts = /* @__PURE__ */ new Map();
|
|
8091
8201
|
let run;
|
|
8092
8202
|
let failure;
|
|
8093
8203
|
let disposeResultTool;
|
|
8094
8204
|
let disposeResultObserver;
|
|
8095
8205
|
try {
|
|
8096
8206
|
const observer = this.resultRuntime.on("tools/result", ((execution, result) => {
|
|
8207
|
+
if (execution.token !== void 0) {
|
|
8208
|
+
const entries = stagedReceipts.get(execution.token);
|
|
8209
|
+
if (entries !== void 0) {
|
|
8210
|
+
stagedReceipts.delete(execution.token);
|
|
8211
|
+
if (result.isError !== true) committedReceipts.push(...entries);
|
|
8212
|
+
}
|
|
8213
|
+
}
|
|
8097
8214
|
if (execution.name === resultToolName) {
|
|
8098
8215
|
const entry = staged.get(execution);
|
|
8099
8216
|
if (entry === void 0) return;
|
|
@@ -8108,13 +8225,25 @@ ${runtimeSnapshotContext("user", targetEntries)}`;
|
|
|
8108
8225
|
};
|
|
8109
8226
|
return;
|
|
8110
8227
|
}
|
|
8111
|
-
if (pending
|
|
8112
|
-
|
|
8113
|
-
|
|
8114
|
-
|
|
8115
|
-
|
|
8116
|
-
|
|
8228
|
+
if (pending !== void 0 && pending.parent === execution.token) {
|
|
8229
|
+
const entry = pending;
|
|
8230
|
+
pending = void 0;
|
|
8231
|
+
if (result.isError !== true && captured === void 0) captured = {
|
|
8232
|
+
agentId: entry.agentId,
|
|
8233
|
+
value: entry.value
|
|
8234
|
+
};
|
|
8235
|
+
}
|
|
8236
|
+
if (execution.name === void 0 || !recoverableTools.has(execution.name) || result.isError === true || !Object.hasOwn(result, "value")) return;
|
|
8237
|
+
const agent = execution.agent;
|
|
8238
|
+
if (agent === void 0 || !isSubagent(agent)) return;
|
|
8239
|
+
const receipt = {
|
|
8240
|
+
agentId: agent.id,
|
|
8241
|
+
name: execution.name,
|
|
8242
|
+
arguments: execution.arguments,
|
|
8243
|
+
value: result.value
|
|
8117
8244
|
};
|
|
8245
|
+
if (execution.parent === void 0) committedReceipts.push(receipt);
|
|
8246
|
+
else stagedReceipts.set(execution.parent, [...stagedReceipts.get(execution.parent) ?? [], receipt]);
|
|
8118
8247
|
}));
|
|
8119
8248
|
if (typeof observer !== "function") throw new Error("dsh-mnemon subagent result observer registration did not return a disposer");
|
|
8120
8249
|
disposeResultObserver = observer;
|
|
@@ -8162,22 +8291,24 @@ Completion protocol: call \`${resultToolName}\` exactly once with the final resu
|
|
|
8162
8291
|
toolFilter: { allow: [...tools, resultToolName] },
|
|
8163
8292
|
persona: completionPersona
|
|
8164
8293
|
});
|
|
8165
|
-
const
|
|
8166
|
-
|
|
8167
|
-
|
|
8294
|
+
const activeRun = run;
|
|
8295
|
+
const result = await activeRun.result;
|
|
8296
|
+
if (captured !== void 0 && captured.agentId !== activeRun.id) throw new Error("Mnemon subagent result was recorded by a different child");
|
|
8297
|
+
let structured = captured?.value ?? result.structured;
|
|
8298
|
+
if (structured === void 0 && result.stopReason === "completed") structured = recoverStructuredResult(recovery, committedReceipts.filter((receipt) => receipt.agentId === activeRun.id));
|
|
8168
8299
|
if (structured !== void 0) assertDshOutputValue(outputSchema, structured);
|
|
8169
8300
|
if (result.stopReason !== "completed") {
|
|
8170
|
-
const detail = subagentFailureDetail(
|
|
8301
|
+
const detail = subagentFailureDetail(activeRun);
|
|
8171
8302
|
throw new Error(`memory subagent stopped with ${result.stopReason}${detail === void 0 ? "" : `: ${detail}`}`);
|
|
8172
8303
|
}
|
|
8173
8304
|
if (structured === void 0) throw new Error("memory subagent completed without recording its result");
|
|
8174
8305
|
this.counters[operation === "recall" ? "recalls" : operation === "write" ? "writes" : operation === "review" ? "reviews" : operation === "placement" ? "placements" : operation === "migration" ? "migrations" : operation === "compaction" ? "compactions" : operation === "document-archive" ? "documentArchives" : operation === "metadata-maintenance" ? "metadataMaintenances" : "answers"] += 1;
|
|
8175
|
-
this.counters.lastRunId =
|
|
8306
|
+
this.counters.lastRunId = activeRun.id;
|
|
8176
8307
|
if (operation !== "answer") this.counters.lastOperation = operation;
|
|
8177
8308
|
this.counters.lastAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
8178
8309
|
return {
|
|
8179
8310
|
provider,
|
|
8180
|
-
runId:
|
|
8311
|
+
runId: activeRun.id,
|
|
8181
8312
|
result: {
|
|
8182
8313
|
...result,
|
|
8183
8314
|
structured
|
|
@@ -9219,10 +9350,11 @@ function inspectDshInstall(packageManifestPath, dshHome) {
|
|
|
9219
9350
|
locationDir: resolve(dirname(packageManifestPath))
|
|
9220
9351
|
};
|
|
9221
9352
|
}
|
|
9222
|
-
async function resultOrThrow(runner, command, args, timeoutMs) {
|
|
9353
|
+
async function resultOrThrow(runner, command, args, timeoutMs, options = {}) {
|
|
9223
9354
|
const result = await runner(command, args, {
|
|
9224
9355
|
timeoutMs,
|
|
9225
|
-
maxOutputBytes: MAX_UPDATE_OUTPUT_BYTES
|
|
9356
|
+
maxOutputBytes: MAX_UPDATE_OUTPUT_BYTES,
|
|
9357
|
+
...options
|
|
9226
9358
|
});
|
|
9227
9359
|
if (result.exitCode !== 0) {
|
|
9228
9360
|
const detail = result.stderr.trim() || result.stdout.trim() || `exit ${String(result.exitCode)}`;
|
|
@@ -9409,7 +9541,7 @@ var VersionUpdateManager = class {
|
|
|
9409
9541
|
const install = inspectDshInstall(this.packageManifestPath, this.dshHome);
|
|
9410
9542
|
const pnpm = this.executable("pnpm");
|
|
9411
9543
|
if (install.mode !== "npm" || install.profileDir === void 0 || pnpm === void 0) throw new Error("This dsh-mnemon installation cannot be updated automatically");
|
|
9412
|
-
const outputText = updateOutput(await resultOrThrow(this.processRunner, pnpm, ["update", DSH_MNEMON_PACKAGE], UPDATE_TIMEOUT_MS));
|
|
9544
|
+
const outputText = updateOutput(await resultOrThrow(this.processRunner, pnpm, ["update", DSH_MNEMON_PACKAGE], UPDATE_TIMEOUT_MS, { cwd: install.profileDir }));
|
|
9413
9545
|
this.dshMnemonVersion = latest;
|
|
9414
9546
|
return {
|
|
9415
9547
|
component,
|
|
@@ -9989,6 +10121,7 @@ const MUTABLE_FIELDS = [
|
|
|
9989
10121
|
"displayMode",
|
|
9990
10122
|
"tabEnabled",
|
|
9991
10123
|
"writeEnabled",
|
|
10124
|
+
"persistenceStrategy",
|
|
9992
10125
|
"taskAgentModel"
|
|
9993
10126
|
];
|
|
9994
10127
|
/** Nested paths of the live in-conversation interaction toggles. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ClientConnectionHandle } from '../shared/contracts.ts';
|
|
1
|
+
import type { ClientConnectionHandle, ClientSettingsScope, Config } from '../shared/contracts.ts';
|
|
2
2
|
import type { MnemonKey } from './locales.ts';
|
|
3
3
|
export interface MnemonSaveActionProps {
|
|
4
4
|
/** Stable identity of the finalized assistant message this action addresses. */
|
|
@@ -6,6 +6,7 @@ export interface MnemonSaveActionProps {
|
|
|
6
6
|
/** Injected by the slot host: the session this message belongs to. */
|
|
7
7
|
sessionId?: string;
|
|
8
8
|
connection: ClientConnectionHandle;
|
|
9
|
+
settingsScope: ClientSettingsScope<Config>;
|
|
9
10
|
t: (key: MnemonKey, params?: Record<string, unknown>) => string;
|
|
10
11
|
}
|
|
11
12
|
/** Save-to-memory action on finalized assistant messages, routed through the supervised writeback gate. */
|
package/lib/types/contracts.d.ts
CHANGED
|
@@ -35,6 +35,8 @@ export interface ToolExecution {
|
|
|
35
35
|
signal: AbortSignal;
|
|
36
36
|
agent?: HostAgent;
|
|
37
37
|
name?: string;
|
|
38
|
+
/** Parsed tool arguments, available on the authoritative tools/result event. */
|
|
39
|
+
arguments?: unknown;
|
|
38
40
|
parent?: symbol;
|
|
39
41
|
token?: symbol;
|
|
40
42
|
/** End the current model turn after an authoritative terminal tool call. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-mnemon",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.11",
|
|
4
4
|
"description": "Three-tier memory control plane for DeepSeek Harness: persistent runtime context, searchable project documents, pluggable long-term memory, smart routing, supervised agent workflows, WebUI, and headless tools.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"deepseek-harness",
|