dsh-mnemon 0.5.23 → 0.5.25
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 +1 -1
- package/README.zh-CN.md +1 -1
- package/lib/bundle.js +1 -1
- package/lib/client.js +381 -48
- package/lib/index.js +213 -37
- package/lib/{starter-resolution-B0Wj3X3R.js → starter-resolution-UcTGyjgm.js} +5 -5
- package/lib/starter.js +1 -1
- package/lib/types/src/client/locales.d.ts +41 -0
- package/lib/types/src/client/page-controls.d.ts +1 -0
- package/package.json +6 -6
package/lib/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import z from "@deepseek-ai/schemastery";
|
|
|
7
7
|
import { basename, delimiter, dirname, isAbsolute, join, normalize, resolve } from "node:path";
|
|
8
8
|
import { resolveEmbedding, resolvePersistenceStrategy, resolveRecallQuality } from "dsh-mnemon-source-memory-spaces";
|
|
9
9
|
import { createHash, randomUUID } from "node:crypto";
|
|
10
|
-
import { accessSync, closeSync, constants, existsSync, fstatSync, lstatSync, mkdirSync, openSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
10
|
+
import { accessSync, chmodSync, closeSync, constants, copyFileSync, existsSync, fstatSync, lstatSync, mkdirSync, openSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
11
11
|
import { homedir } from "node:os";
|
|
12
12
|
import { strToU8, unzipSync, zipSync } from "fflate";
|
|
13
13
|
import { DOCUMENTS_ACTIVE_LIMIT_BYTES, DOCUMENTS_VERSION } from "dsh-mnemon-source-documents/contracts";
|
|
@@ -862,6 +862,33 @@ function readCurrentRuntime(root, limits = RUNTIME_MEMORY_LIMITS) {
|
|
|
862
862
|
const path = join(root, "runtime", "memories.json");
|
|
863
863
|
return existsSync(path) ? parseRuntime(JSON.parse(readFileSync(path, "utf8")), limits) : emptyRuntime();
|
|
864
864
|
}
|
|
865
|
+
/**
|
|
866
|
+
* A Pack carries no local archive: the one MEMORY.md wrote while no Memory Space
|
|
867
|
+
* could take its entries holds their only copy, so an import keeps it (#336).
|
|
868
|
+
* Its files and folders are carried; a link is neither carried nor followed.
|
|
869
|
+
*/
|
|
870
|
+
function keepRuntimeArchive(root, stagedRuntime) {
|
|
871
|
+
const copy = (from, to) => {
|
|
872
|
+
let stat;
|
|
873
|
+
try {
|
|
874
|
+
stat = lstatSync(from);
|
|
875
|
+
} catch {
|
|
876
|
+
return;
|
|
877
|
+
}
|
|
878
|
+
if (stat.isSymbolicLink()) return;
|
|
879
|
+
if (stat.isFile()) {
|
|
880
|
+
copyFileSync(from, to);
|
|
881
|
+
chmodSync(to, 384);
|
|
882
|
+
} else if (stat.isDirectory()) {
|
|
883
|
+
mkdirSync(to, {
|
|
884
|
+
recursive: true,
|
|
885
|
+
mode: 448
|
|
886
|
+
});
|
|
887
|
+
for (const name of readdirSync(from)) copy(join(from, name), join(to, name));
|
|
888
|
+
}
|
|
889
|
+
};
|
|
890
|
+
copy(join(root, "runtime", "archived"), join(stagedRuntime, "archived"));
|
|
891
|
+
}
|
|
865
892
|
function writeRuntime(directory, file) {
|
|
866
893
|
mkdirSync(directory, {
|
|
867
894
|
recursive: true,
|
|
@@ -1120,6 +1147,7 @@ function stageImport(root, pack, components, mode, runtimeLimits) {
|
|
|
1120
1147
|
if (components.includes("runtime")) {
|
|
1121
1148
|
const runtime = mode === "merge" ? mergeRuntime(root, pack, runtimeLimits) : parseRuntime(json$1(pack.files["payload/runtime/memories.json"], "payload/runtime/memories.json"), runtimeLimits);
|
|
1122
1149
|
writeRuntime(join(staging, "runtime"), runtime);
|
|
1150
|
+
keepRuntimeArchive(root, join(staging, "runtime"));
|
|
1123
1151
|
}
|
|
1124
1152
|
if (components.includes("documents")) {
|
|
1125
1153
|
const documents = mode === "merge" ? mergeDocuments(root, pack) : archiveDocuments(pack);
|
|
@@ -3437,6 +3465,14 @@ function pendingMutationContext(plan) {
|
|
|
3437
3465
|
...plan.excluded === void 0 ? [] : [`- Matched committed entry: excluded by the host because it will be ${plan.action === "replace" ? "replaced" : "removed"}`]
|
|
3438
3466
|
].join("\n");
|
|
3439
3467
|
}
|
|
3468
|
+
/**
|
|
3469
|
+
* A space that can take a MEMORY.md archive or a Document's index: active, its
|
|
3470
|
+
* Provider enabled and ready, with exact writes and safe forget. A Mnemon Native
|
|
3471
|
+
* space stays listed, and active, while its CLI is missing; it takes no writes then.
|
|
3472
|
+
*/
|
|
3473
|
+
function archivableSpace(directory, body) {
|
|
3474
|
+
return body.active && body.providerEnabled !== false && body.provider.capabilities.remember === true && body.provider.capabilities.writeMode === "exact" && body.provider.capabilities.forget === true && directory.providers?.find((provider) => provider.id === body.provider.id)?.serviceConfigured !== false;
|
|
3475
|
+
}
|
|
3440
3476
|
function compactedBudget(plan) {
|
|
3441
3477
|
const pendingBytes = plan.pending === void 0 ? 0 : Buffer.byteLength(plan.pending.content, "utf8");
|
|
3442
3478
|
const separatorBytes = plan.pending === void 0 || plan.entries.length === 0 ? 0 : Buffer.byteLength(RUNTIME_ENTRY_DELIMITER, "utf8");
|
|
@@ -3595,6 +3631,22 @@ function destinationFromCommittedMutation(result, memoryBodyId, content) {
|
|
|
3595
3631
|
digest
|
|
3596
3632
|
};
|
|
3597
3633
|
}
|
|
3634
|
+
/**
|
|
3635
|
+
* The memory a skipped write names as already holding exactly this text, when
|
|
3636
|
+
* its receipt carries that memory's id and stored text. Anything less proves
|
|
3637
|
+
* nothing, and the caller verifies by search instead.
|
|
3638
|
+
*/
|
|
3639
|
+
function skippedExactDestination(result, memoryBodyId, content) {
|
|
3640
|
+
const value = optionalObject(result);
|
|
3641
|
+
const id = typeof value?.id === "string" ? value.id.trim() : "";
|
|
3642
|
+
if (id === "" || value?.content !== content) return void 0;
|
|
3643
|
+
if (value.memoryBodyId !== void 0 && value.memoryBodyId !== memoryBodyId) return void 0;
|
|
3644
|
+
return {
|
|
3645
|
+
layerId: "memory-spaces",
|
|
3646
|
+
reference: `memory-space:${encodeURIComponent(memoryBodyId)}/item:${encodeURIComponent(id)}`,
|
|
3647
|
+
digest: sha256(content)
|
|
3648
|
+
};
|
|
3649
|
+
}
|
|
3598
3650
|
function mutationStates(result) {
|
|
3599
3651
|
const value = optionalObject(result);
|
|
3600
3652
|
return [value?.action, value?.status].filter((entry) => typeof entry === "string").map((entry) => entry.trim().toLocaleLowerCase());
|
|
@@ -3892,11 +3944,13 @@ var MnemonSubagentCoordinator = class {
|
|
|
3892
3944
|
commit: () => runtime.mutate("mutate", request, signal),
|
|
3893
3945
|
memorySpaces: async () => {
|
|
3894
3946
|
if (!graph.config.writeEnabled || !this.runtimeSource.config.writeEnabled) throw new Error("dsh-mnemon is configured read-only");
|
|
3895
|
-
|
|
3947
|
+
if (!allowsParticipation(graph.config, "memory-spaces", "write", "automatic") || !lease.generation.sourceInstances().some((source) => source.sourceTypeId === "memory-spaces")) return void 0;
|
|
3896
3948
|
const source = graph.source("memory-spaces", scope).forGeneration(lease.generation);
|
|
3949
|
+
const { sourceInstanceKey } = await source.identity();
|
|
3897
3950
|
return {
|
|
3898
3951
|
source,
|
|
3899
|
-
cleanup: source
|
|
3952
|
+
cleanup: source,
|
|
3953
|
+
elsewhere: await this.archivableElsewhere(graph, scope, lease.generation, sourceInstanceKey, signal)
|
|
3900
3954
|
};
|
|
3901
3955
|
},
|
|
3902
3956
|
model: (...args) => this.runtimeModel(scope, parent, signal, ...args)
|
|
@@ -3946,7 +4000,7 @@ var MnemonSubagentCoordinator = class {
|
|
|
3946
4000
|
},
|
|
3947
4001
|
memorySpaces: async () => {
|
|
3948
4002
|
if (!authorize()) throw new Error("Runtime capacity maintenance is no longer authorized");
|
|
3949
|
-
return this.runtimeArchiveSource(graph, turn.scope, turn.view, lease.generation, turn);
|
|
4003
|
+
return this.runtimeArchiveSource(graph, turn.scope, turn.view, lease.generation, turn, signal);
|
|
3950
4004
|
},
|
|
3951
4005
|
model: (...args) => this.runtimeModel(turn.scope, parent, signal, ...args)
|
|
3952
4006
|
}, input, signal);
|
|
@@ -3992,7 +4046,7 @@ var MnemonSubagentCoordinator = class {
|
|
|
3992
4046
|
scenario: "management.runtime-capacity",
|
|
3993
4047
|
budget: DEFAULT_MEMORY_VIEW_BUDGET
|
|
3994
4048
|
}, signal);
|
|
3995
|
-
return this.runtimeArchiveSource(graph, request.scope, view, generation);
|
|
4049
|
+
return this.runtimeArchiveSource(graph, request.scope, view, generation, void 0, signal);
|
|
3996
4050
|
},
|
|
3997
4051
|
model: (...args) => this.runtimeModel(request.scope, void 0, signal, ...args)
|
|
3998
4052
|
}, request.input, signal);
|
|
@@ -4006,11 +4060,14 @@ var MnemonSubagentCoordinator = class {
|
|
|
4006
4060
|
lease.release();
|
|
4007
4061
|
}
|
|
4008
4062
|
}
|
|
4009
|
-
async runtimeArchiveSource(graph, scope, view, generation, turn) {
|
|
4063
|
+
async runtimeArchiveSource(graph, scope, view, generation, turn, signal) {
|
|
4010
4064
|
if (!graph.config.writeEnabled || !this.runtimeSource.config.writeEnabled) throw new Error("dsh-mnemon is configured read-only");
|
|
4011
|
-
|
|
4065
|
+
if (!allowsParticipation(graph.config, "memory-spaces", "write", "automatic")) return void 0;
|
|
4012
4066
|
const candidates = generation.sourceInstances().filter((source) => source.sourceTypeId === "memory-spaces" && view.actionOffers.some((offer) => offer.sourceInstanceKey === source.sourceInstanceKey && offer.sourceActionId === "remember" && offer.authority === void 0));
|
|
4013
|
-
if (candidates.length === 0)
|
|
4067
|
+
if (candidates.length === 0) {
|
|
4068
|
+
if (await this.noArchivableMemorySpace(graph, scope, generation, signal)) return void 0;
|
|
4069
|
+
throw new Error("Source Action is not offered by the current View: memory-spaces/remember");
|
|
4070
|
+
}
|
|
4014
4071
|
if (candidates.length !== 1) throw new Error("Runtime archival requires one unambiguous writable Memory Spaces Source");
|
|
4015
4072
|
const cleanup = graph.source("memory-spaces", scope).forInstance(candidates[0].sourceInstanceKey).forGeneration(generation);
|
|
4016
4073
|
let source = cleanup;
|
|
@@ -4024,6 +4081,46 @@ var MnemonSubagentCoordinator = class {
|
|
|
4024
4081
|
writeScope: {
|
|
4025
4082
|
viewId: view.id,
|
|
4026
4083
|
grant
|
|
4084
|
+
},
|
|
4085
|
+
elsewhere: await this.archivableElsewhere(graph, scope, generation, candidates[0].sourceInstanceKey, signal)
|
|
4086
|
+
};
|
|
4087
|
+
}
|
|
4088
|
+
/**
|
|
4089
|
+
* MEMORY.md keeps working without a Memory Space to archive into: the Runtime
|
|
4090
|
+
* Source moves the entries compaction leaves out to its local archive, as exact
|
|
4091
|
+
* text, in the same commit as the compaction and the pending write (#336).
|
|
4092
|
+
*/
|
|
4093
|
+
async archiveRuntimeLocally(context, request, plan, reason, signal) {
|
|
4094
|
+
signal.throwIfAborted();
|
|
4095
|
+
if (plan.localArchive !== true) throw new Error(`runtime memory archival found no Memory Space that can take the archive (${reason}), and this Runtime Source cannot archive locally; pending write was not committed and existing runtime entries are unchanged; update dsh-mnemon-source-runtime, activate a supported Memory Space, or increase runtimeMemory.memoryLimitBytes`);
|
|
4096
|
+
context.assertWritable?.();
|
|
4097
|
+
const runId = `host-${randomUUID()}`;
|
|
4098
|
+
const compacted = plan.entries.map(({ content, importance, branches }) => ({
|
|
4099
|
+
content,
|
|
4100
|
+
importance,
|
|
4101
|
+
...branches === void 0 ? {} : { branches }
|
|
4102
|
+
}));
|
|
4103
|
+
const mutation = await context.runtime.mutateResult("compact-and-mutate", {
|
|
4104
|
+
revision: plan.revision,
|
|
4105
|
+
mutation: request,
|
|
4106
|
+
compacted,
|
|
4107
|
+
maxBytes: compactedBudget(plan),
|
|
4108
|
+
archive: "local"
|
|
4109
|
+
}, signal);
|
|
4110
|
+
const archived = mutation.value.archived?.entries ?? 0;
|
|
4111
|
+
this.counters.migrations += 1;
|
|
4112
|
+
this.counters.lastRunId = runId;
|
|
4113
|
+
this.counters.lastOperation = "migration";
|
|
4114
|
+
this.counters.lastAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
4115
|
+
return {
|
|
4116
|
+
...mutation.value,
|
|
4117
|
+
revision: mutation.revision,
|
|
4118
|
+
maintenance: {
|
|
4119
|
+
kind: "local-archive",
|
|
4120
|
+
runId,
|
|
4121
|
+
provider: "host",
|
|
4122
|
+
summary: `Moved ${archived} MEMORY.md ${archived === 1 ? "entry" : "entries"} to the local archive${mutation.value.archived === void 0 ? "" : ` ${mutation.value.archived.path}`}, since ${reason}.`,
|
|
4123
|
+
memoryBodyIds: []
|
|
4027
4124
|
}
|
|
4028
4125
|
};
|
|
4029
4126
|
}
|
|
@@ -4160,15 +4257,22 @@ ${naturalRequest(request)}`;
|
|
|
4160
4257
|
const document = await controller.read("document", { id }, signal);
|
|
4161
4258
|
if (document.status !== "active") throw new Error("only active documents can be archived");
|
|
4162
4259
|
const source = documentMigrationSource(document);
|
|
4163
|
-
const
|
|
4260
|
+
const indexSpaces = await this.documentIndexSpaces(parent, lease.generation, signal);
|
|
4261
|
+
if (indexSpaces === void 0) return this.archiveDocumentLocally(controller, document, "no Memory Spaces layer takes writes here", signal);
|
|
4262
|
+
const memoryService = indexSpaces.forGeneration(lease.generation);
|
|
4164
4263
|
const identity = await memoryService.identity();
|
|
4165
4264
|
const cleanup = graph.source("memory-spaces", agentScope(parent, graph.config)).forInstance(identity.sourceInstanceKey).forGeneration(lease.generation);
|
|
4166
4265
|
const grant = authority?.context.view.readGrants.find((grant) => grant.sourceInstanceKey === identity.sourceInstanceKey && grant.schema === "dsh-mnemon.memory-spaces/v1");
|
|
4167
4266
|
if (authority !== void 0 && grant === void 0) throw new Error("document archive requires a Memory Space namespace grant");
|
|
4168
4267
|
const allowed = grant === void 0 ? void 0 : new Set(strings(object$6(grant.value).memoryBodyIds));
|
|
4169
|
-
const
|
|
4170
|
-
const
|
|
4171
|
-
|
|
4268
|
+
const directory = await memoryService.read("body-directory", null, signal);
|
|
4269
|
+
const indexable = (body) => archivableSpace(directory, body);
|
|
4270
|
+
const eligible = (body) => indexable(body) && (allowed === void 0 || allowed.has(body.id));
|
|
4271
|
+
const bodies = directory.items.filter(eligible);
|
|
4272
|
+
if (bodies.length === 0) {
|
|
4273
|
+
if (!directory.items.some(indexable) && !await this.archivableElsewhere(graph, agentScope(parent, graph.config), lease.generation, identity.sourceInstanceKey, signal)) return this.archiveDocumentLocally(controller, document, "no Memory Space can take its index", signal);
|
|
4274
|
+
throw new Error("document archive requires an existing active Memory Space with exact writes and safe forget");
|
|
4275
|
+
}
|
|
4172
4276
|
const { provider, runId, result } = await this.delegate(parent, "document-archive", "Plan managed document archive", documentArchivePrompt(document, source, bodies), [], DOCUMENT_ARCHIVE_SCHEMA, signal, "spawn", DOCUMENT_ARCHIVE_PERSONA);
|
|
4173
4277
|
const value = object$6(result.structured);
|
|
4174
4278
|
const summary = typeof value.summary === "string" ? value.summary.trim() : "";
|
|
@@ -4220,18 +4324,22 @@ ${naturalRequest(request)}`;
|
|
|
4220
4324
|
if (written.length !== 1) throw new Error("document archive requires exactly one index receipt");
|
|
4221
4325
|
if (isNew && receiptId !== void 0) destination = destinationFromCommittedMutation(receipt, memoryBodyId, content);
|
|
4222
4326
|
else if (states.includes("skipped")) {
|
|
4223
|
-
const
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4327
|
+
const named = skippedExactDestination(receipt, memoryBodyId, content);
|
|
4328
|
+
if (named !== void 0) destination = named;
|
|
4329
|
+
else {
|
|
4330
|
+
const exact = (await memoryService.read("search", {
|
|
4331
|
+
query: document.contentHash,
|
|
4332
|
+
mode: "keyword",
|
|
4333
|
+
limit: 50,
|
|
4334
|
+
memoryBodyIds: [memoryBodyId]
|
|
4335
|
+
}, signal)).results.find((item) => item.memoryBodyId === memoryBodyId && item.id === receiptId && item.content === content);
|
|
4336
|
+
if (exact === void 0) throw new Error(`document archive skipped index lacks exact durable evidence in Memory Space ${memoryBodyId}`);
|
|
4337
|
+
destination = {
|
|
4338
|
+
layerId: "memory-spaces",
|
|
4339
|
+
reference: `memory-space:${encodeURIComponent(memoryBodyId)}/item:${encodeURIComponent(exact.id)}`,
|
|
4340
|
+
digest: sha256(exact.content)
|
|
4341
|
+
};
|
|
4342
|
+
}
|
|
4235
4343
|
} else throw new Error(`document archive received no reversible committed index receipt in Memory Space ${memoryBodyId}`);
|
|
4236
4344
|
}
|
|
4237
4345
|
signal.throwIfAborted();
|
|
@@ -4293,6 +4401,7 @@ ${naturalRequest(request)}`;
|
|
|
4293
4401
|
if (plan.entries.length === 0) throw new Error("runtime memory capacity was exceeded without entries available for maintenance");
|
|
4294
4402
|
if (request.target === "user") return this.compactUserAndCommit(context, request, plan, signal);
|
|
4295
4403
|
const archive = await context.memorySpaces();
|
|
4404
|
+
if (archive === void 0) return this.archiveRuntimeLocally(context, request, plan, "no Memory Space takes automatic writes here", signal);
|
|
4296
4405
|
const memoryService = archive.source;
|
|
4297
4406
|
let allowed = archive.memoryBodyIds;
|
|
4298
4407
|
const readDirectory = async () => {
|
|
@@ -4306,13 +4415,16 @@ ${naturalRequest(request)}`;
|
|
|
4306
4415
|
return catalog;
|
|
4307
4416
|
};
|
|
4308
4417
|
const catalog = await readDirectory();
|
|
4309
|
-
const
|
|
4310
|
-
const
|
|
4418
|
+
const ready = (body) => catalog.providers?.find((provider) => provider.id === body.provider.id)?.serviceConfigured !== false;
|
|
4419
|
+
const writable = (body) => body.active && body.providerEnabled !== false && body.provider.capabilities.remember === true && ready(body) && (allowed === void 0 || allowed.has(body.id));
|
|
4420
|
+
const exact = (body) => body.provider.capabilities.writeMode === "exact" && body.provider.capabilities.forget === true;
|
|
4421
|
+
const eligible = (body) => writable(body) && exact(body);
|
|
4311
4422
|
const eligibleBodies = catalog.items.filter(eligible);
|
|
4312
4423
|
if (eligibleBodies.length === 0) {
|
|
4313
4424
|
const writableBodies = catalog.items.filter(writable);
|
|
4314
4425
|
const unsupported = writableBodies.map((body) => `${body.id} (provider=${body.provider.id}, writeMode=${body.provider.capabilities.writeMode}, forget=${body.provider.capabilities.forget})`).join(", ");
|
|
4315
4426
|
const reason = catalog.items.length === 0 ? "Memory Space body-directory is empty" : allowed?.size === 0 ? "current View write scope is empty" : allowed !== void 0 && catalog.items.some((body) => body.active && body.providerEnabled !== false && body.provider.capabilities.remember && !allowed?.has(body.id)) && writableBodies.length === 0 ? "current View write scope excludes the active writable Memory Spaces" : writableBodies.length === 0 ? "no active writable Memory Space in the authorized scope" : "authorized destinations lack exact writes or safe forget";
|
|
4427
|
+
if (!catalog.items.some((body) => archivableSpace(catalog, body)) && archive.elsewhere !== true) return this.archiveRuntimeLocally(context, request, plan, `${reason}${unsupported === "" ? "" : ` (${unsupported})`}`, signal);
|
|
4316
4428
|
const scope = archive.writeScope === void 0 ? "management" : `${archive.writeScope.grant.sourceInstanceKey}/${catalog.writeScope === void 0 ? "pinned-read" : "source-write"}`;
|
|
4317
4429
|
throw new Error(`runtime memory archival requires an existing active writable Memory Space with exact writes and safe forget; ${reason}; scope=${scope}, catalog=${catalog.items.length}, authorized=${allowed?.size ?? "management"}, writable=${writableBodies.length}; pending write was not committed and existing runtime entries are unchanged; retry the same request in a new turn after activating a supported authorized Memory Space, or increase runtimeMemory.memoryLimitBytes${unsupported === "" ? "" : `; unsupported destinations: ${unsupported}`}`);
|
|
4318
4430
|
}
|
|
@@ -4563,12 +4675,18 @@ ${runtimeSnapshotContext("user", plan.entries)}`;
|
|
|
4563
4675
|
const committed = destinationFromCommittedMutation(result, memoryBodyId, entry.content);
|
|
4564
4676
|
if (committed !== void 0) return committed;
|
|
4565
4677
|
if (!mutationStates(result).includes("skipped")) throw new Error(`runtime archive write did not commit synchronously for Memory Space ${memoryBodyId}`);
|
|
4566
|
-
const
|
|
4678
|
+
const named = skippedExactDestination(result, memoryBodyId, entry.content);
|
|
4679
|
+
if (named !== void 0) return named;
|
|
4680
|
+
const recalled = await service.read("search", {
|
|
4567
4681
|
query: entry.content.slice(0, 500),
|
|
4568
4682
|
limit: 20,
|
|
4569
4683
|
memoryBodyIds: [memoryBodyId]
|
|
4570
|
-
}, signal)
|
|
4571
|
-
|
|
4684
|
+
}, signal);
|
|
4685
|
+
const exact = recalled.results.find((candidate) => candidate.memoryBodyId === memoryBodyId && candidate.content.trim() === entry.content);
|
|
4686
|
+
if (exact === void 0) {
|
|
4687
|
+
const unavailable = recalled.sources?.find((source) => source.status === "unavailable");
|
|
4688
|
+
throw new Error(`runtime archive skipped an entry without exact durable recall evidence in Memory Space ${memoryBodyId}: ${unavailable === void 0 ? `its search returned ${recalled.results.length} results, none with that exact text` : `its search was unavailable (${safeFailureDetail(unavailable.hint ?? "no detail")})`}`);
|
|
4689
|
+
}
|
|
4572
4690
|
return {
|
|
4573
4691
|
layerId: "memory-spaces",
|
|
4574
4692
|
reference: `memory-space:${encodeURIComponent(memoryBodyId)}/item:${encodeURIComponent(exact.id)}`,
|
|
@@ -4832,6 +4950,68 @@ This is the only completion channel for this run. Do not finish with a plain-tex
|
|
|
4832
4950
|
await source.assertActionOffered(actionId, (offer) => authority.graph.config.writeEnabled && offer.authority === void 0);
|
|
4833
4951
|
return source;
|
|
4834
4952
|
}
|
|
4953
|
+
/**
|
|
4954
|
+
* The Memory Spaces Source a Document archive indexes into, or undefined when
|
|
4955
|
+
* that layer is off, not installed, takes no automatic writes, or has no space
|
|
4956
|
+
* anywhere that could take the index (#336). A space this View does not offer
|
|
4957
|
+
* keeps the refusal, as before.
|
|
4958
|
+
*/
|
|
4959
|
+
async documentIndexSpaces(parent, generation, signal) {
|
|
4960
|
+
const graph = this.runtimeSource.forAgent(parent);
|
|
4961
|
+
if (!graph.config.writeEnabled || !this.runtimeSource.config.writeEnabled) throw new Error("dsh-mnemon is configured read-only");
|
|
4962
|
+
if (!allowsParticipation(graph.config, "memory-spaces", "write", "automatic")) return void 0;
|
|
4963
|
+
const installed = generation.sourceInstances().filter((source) => source.sourceTypeId === "memory-spaces");
|
|
4964
|
+
if (installed.length === 0) return void 0;
|
|
4965
|
+
const authority = this.turnAuthority(parent, false);
|
|
4966
|
+
if (authority !== void 0 && !authority.context.view.actionOffers.some((offer) => offer.sourceActionId === "remember" && offer.authority === void 0 && installed.some((source) => source.sourceInstanceKey === offer.sourceInstanceKey)) && await this.noArchivableMemorySpace(graph, agentScope(parent, graph.config), generation, signal)) return void 0;
|
|
4967
|
+
return this.writableSourceFor(parent, "memory-spaces", "remember");
|
|
4968
|
+
}
|
|
4969
|
+
/** Whether a Memory Spaces Source other than the one in use lists a space that could take the archive. */
|
|
4970
|
+
async archivableElsewhere(graph, scope, generation, sourceInstanceKey, signal) {
|
|
4971
|
+
if (!generation.sourceInstances().some((source) => source.sourceTypeId === "memory-spaces" && source.sourceInstanceKey !== sourceInstanceKey)) return false;
|
|
4972
|
+
return !await this.noArchivableMemorySpace(graph, scope, generation, signal, sourceInstanceKey);
|
|
4973
|
+
}
|
|
4974
|
+
/**
|
|
4975
|
+
* True only when no installed Memory Spaces Source lists a space that could take
|
|
4976
|
+
* an archive (#336). A directory that cannot be read counts as one that could:
|
|
4977
|
+
* the caller then refuses as before, and nothing leaves working memory.
|
|
4978
|
+
*/
|
|
4979
|
+
async noArchivableMemorySpace(graph, scope, generation, signal, except) {
|
|
4980
|
+
for (const instance of generation.sourceInstances().filter((source) => source.sourceTypeId === "memory-spaces" && source.sourceInstanceKey !== except)) try {
|
|
4981
|
+
const directory = await graph.source("memory-spaces", scope).forInstance(instance.sourceInstanceKey).forGeneration(generation).read("body-directory", null, signal);
|
|
4982
|
+
if (directory.items.some((body) => archivableSpace(directory, body))) return false;
|
|
4983
|
+
} catch {
|
|
4984
|
+
signal?.throwIfAborted();
|
|
4985
|
+
return false;
|
|
4986
|
+
}
|
|
4987
|
+
return true;
|
|
4988
|
+
}
|
|
4989
|
+
/** A Project Document archived without a Mnemon index keeps its original under .mnemon/documents/archived. */
|
|
4990
|
+
async archiveDocumentLocally(controller, document, reason, signal) {
|
|
4991
|
+
signal.throwIfAborted();
|
|
4992
|
+
const summary = `Archived locally without a Mnemon index, since ${reason}.`;
|
|
4993
|
+
const archived = await controller.mutate("archive", {
|
|
4994
|
+
id: document.id,
|
|
4995
|
+
documentRevision: document.revision,
|
|
4996
|
+
summary,
|
|
4997
|
+
memoryBodyIds: []
|
|
4998
|
+
}, signal);
|
|
4999
|
+
const runId = `host-${randomUUID()}`;
|
|
5000
|
+
this.counters.documentArchives += 1;
|
|
5001
|
+
this.counters.lastRunId = runId;
|
|
5002
|
+
this.counters.lastOperation = "document-archive";
|
|
5003
|
+
this.counters.lastAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
5004
|
+
return {
|
|
5005
|
+
...archived,
|
|
5006
|
+
maintenance: {
|
|
5007
|
+
runId,
|
|
5008
|
+
provider: "host",
|
|
5009
|
+
summary,
|
|
5010
|
+
memoryBodyIds: [],
|
|
5011
|
+
archivedDocumentIds: [document.id]
|
|
5012
|
+
}
|
|
5013
|
+
};
|
|
5014
|
+
}
|
|
4835
5015
|
async assertAutomaticMemoryWrite(parent) {
|
|
4836
5016
|
const graph = this.runtimeSource.forAgent(parent);
|
|
4837
5017
|
if (!graph.config.writeEnabled || !this.runtimeSource.config.writeEnabled) throw new Error("dsh-mnemon is configured read-only");
|
|
@@ -5789,7 +5969,7 @@ var MnemonLifecycle = class {
|
|
|
5789
5969
|
};
|
|
5790
5970
|
/** Creation ids reserved before DSH publishes clean task-root Agents. */
|
|
5791
5971
|
taskAgentIds = /* @__PURE__ */ new Set();
|
|
5792
|
-
/** Bounded process-local replay fence for finalized-message write actions. */
|
|
5972
|
+
/** Bounded process-local replay fence for finalized-message write actions: the latest text per message. */
|
|
5793
5973
|
supervisedWritebacks = /* @__PURE__ */ new Map();
|
|
5794
5974
|
constructor(ctx, coordinator, config, runtimeSource) {
|
|
5795
5975
|
this.ctx = ctx;
|
|
@@ -6055,15 +6235,13 @@ var MnemonLifecycle = class {
|
|
|
6055
6235
|
if (normalizedKey === void 0 || normalizedKey === "") return execute();
|
|
6056
6236
|
const replayKey = `${replayScope}\u0000${normalizedKey}`;
|
|
6057
6237
|
const existing = this.supervisedWritebacks.get(replayKey);
|
|
6058
|
-
if (existing
|
|
6059
|
-
|
|
6060
|
-
return existing.result;
|
|
6061
|
-
}
|
|
6062
|
-
if (this.supervisedWritebacks.size >= 256) {
|
|
6238
|
+
if (existing?.content === normalizedContent) return existing.result;
|
|
6239
|
+
if (existing === void 0 && this.supervisedWritebacks.size >= 256) {
|
|
6063
6240
|
const oldest = this.supervisedWritebacks.keys().next().value;
|
|
6064
6241
|
if (oldest !== void 0) this.supervisedWritebacks.delete(oldest);
|
|
6065
6242
|
}
|
|
6066
6243
|
const result = execute();
|
|
6244
|
+
this.supervisedWritebacks.delete(replayKey);
|
|
6067
6245
|
this.supervisedWritebacks.set(replayKey, {
|
|
6068
6246
|
content: normalizedContent,
|
|
6069
6247
|
result
|
|
@@ -7212,7 +7390,6 @@ async function assisted(runtime, lifecycle, typeId, operation, input, signal, ta
|
|
|
7212
7390
|
if (typeId === "documents") {
|
|
7213
7391
|
if (operation === "archive") {
|
|
7214
7392
|
requireCapability(runtime, typeId, "archive");
|
|
7215
|
-
requireCapability(runtime, "memory-spaces", "write");
|
|
7216
7393
|
return lifecycle.archiveDocument(sessionId, String(input.id ?? ""), workspaceRoot, signal);
|
|
7217
7394
|
}
|
|
7218
7395
|
if (operation === "mutate") {
|
|
@@ -8147,7 +8324,6 @@ function registerTools(ctx, runtimeSource, coordinator) {
|
|
|
8147
8324
|
const agent = requireAgent(exec);
|
|
8148
8325
|
if (args.action === "archive") {
|
|
8149
8326
|
requireSource(exec, "documents", "archive");
|
|
8150
|
-
requireSource(exec, "memory-spaces", "write");
|
|
8151
8327
|
if (isSubagent(agent)) throw new Error("idle document workers cannot cold-archive directly");
|
|
8152
8328
|
if (args.id === void 0) throw new Error("document id is required for archive");
|
|
8153
8329
|
return coordinator.archiveDocument(agent, args.id, exec.signal);
|
|
@@ -10,15 +10,15 @@ var dependencies = {
|
|
|
10
10
|
"dsh-mnemon-provider-holographic": "0.5.6",
|
|
11
11
|
"dsh-mnemon-provider-honcho": "0.5.5",
|
|
12
12
|
"dsh-mnemon-provider-mem0": "0.5.5",
|
|
13
|
-
"dsh-mnemon-provider-mnemon-native": "0.5.
|
|
13
|
+
"dsh-mnemon-provider-mnemon-native": "0.5.9",
|
|
14
14
|
"dsh-mnemon-provider-openviking": "0.5.7",
|
|
15
15
|
"dsh-mnemon-provider-retaindb": "0.5.5",
|
|
16
16
|
"dsh-mnemon-provider-supermemory": "0.5.5",
|
|
17
|
-
"dsh-mnemon-source-documents": "0.5.
|
|
18
|
-
"dsh-mnemon-source-memory-spaces": "0.5.
|
|
19
|
-
"dsh-mnemon-source-runtime": "0.5.
|
|
17
|
+
"dsh-mnemon-source-documents": "0.5.10",
|
|
18
|
+
"dsh-mnemon-source-memory-spaces": "0.5.17",
|
|
19
|
+
"dsh-mnemon-source-runtime": "0.5.13",
|
|
20
20
|
"dsh-mnemon-strategy-auto-capture": "0.5.5",
|
|
21
|
-
"dsh-mnemon-strategy-default-three-tier": "0.5.
|
|
21
|
+
"dsh-mnemon-strategy-default-three-tier": "0.5.8",
|
|
22
22
|
"dsh-mnemon-strategy-general": "0.5.1",
|
|
23
23
|
"dsh-mnemon-strategy-light-context": "0.5.5",
|
|
24
24
|
"dsh-mnemon-strategy-scoped": "0.5.5",
|
package/lib/starter.js
CHANGED
|
@@ -102,6 +102,7 @@ export declare const zh: {
|
|
|
102
102
|
'receipt.unfinished': string;
|
|
103
103
|
'receipt.failed': string;
|
|
104
104
|
'receipt.view': string;
|
|
105
|
+
'receipt.viewRuntime': string;
|
|
105
106
|
'taskAgent.ready': string;
|
|
106
107
|
'taskAgent.unavailable': string;
|
|
107
108
|
'saveAction.button': string;
|
|
@@ -116,6 +117,31 @@ export declare const zh: {
|
|
|
116
117
|
'saveAction.submitting': string;
|
|
117
118
|
'saveAction.readOnly': string;
|
|
118
119
|
'saveAction.close': string;
|
|
120
|
+
'saveAction.hintDirect': string;
|
|
121
|
+
'saveAction.to': string;
|
|
122
|
+
'saveAction.to.agent': string;
|
|
123
|
+
'saveAction.to.agentDetail': string;
|
|
124
|
+
'saveAction.to.memory': string;
|
|
125
|
+
'saveAction.to.user': string;
|
|
126
|
+
'saveAction.to.space': string;
|
|
127
|
+
'saveAction.save': string;
|
|
128
|
+
'saveAction.saving': string;
|
|
129
|
+
'saveAction.saved.runtime': string;
|
|
130
|
+
'saveAction.saved.runtimeMaintained': string;
|
|
131
|
+
'saveAction.saved.space': string;
|
|
132
|
+
'saveAction.saved.spacePending': string;
|
|
133
|
+
'saveAction.saved.spaceOther': string;
|
|
134
|
+
'saveAction.saved.duplicate': string;
|
|
135
|
+
'saveAction.unavailable': string;
|
|
136
|
+
'saveAction.place.delimiter': string;
|
|
137
|
+
'saveAction.place.tooLong': string;
|
|
138
|
+
'saveAction.place.orAgent': string;
|
|
139
|
+
'saveAction.place.full': string;
|
|
140
|
+
'saveAction.place.fullAll': string;
|
|
141
|
+
'saveAction.place.userCondense': string;
|
|
142
|
+
'saveAction.place.userTooLong': string;
|
|
143
|
+
'saveAction.place.userFull': string;
|
|
144
|
+
'saveAction.noPlace': string;
|
|
119
145
|
'readSources.all': string;
|
|
120
146
|
'readSources.mode.search': string;
|
|
121
147
|
'readSources.mode.graph': string;
|
|
@@ -887,6 +913,18 @@ export declare const zh: {
|
|
|
887
913
|
"entities.selectText": string;
|
|
888
914
|
"entities.emptyTitle": string;
|
|
889
915
|
"entities.emptyText": string;
|
|
916
|
+
"entities.railLoading": string;
|
|
917
|
+
"entities.memoriesHint": string;
|
|
918
|
+
"entities.relatedTitle": string;
|
|
919
|
+
"entities.relatedHint": string;
|
|
920
|
+
"entities.findRelated": string;
|
|
921
|
+
"entities.hideRelated": string;
|
|
922
|
+
"entities.noCarrying": string;
|
|
923
|
+
"entities.noRelated": string;
|
|
924
|
+
"entities.retry": string;
|
|
925
|
+
"entities.sourceReady": string;
|
|
926
|
+
"entities.sourcePartial": string;
|
|
927
|
+
"readSources.status.loading": string;
|
|
890
928
|
"remember.title": string;
|
|
891
929
|
"remember.description": string;
|
|
892
930
|
"remember.readOnlyTitle": string;
|
|
@@ -968,6 +1006,7 @@ export declare const zh: {
|
|
|
968
1006
|
"documents.updated": string;
|
|
969
1007
|
"documents.updatedAfterArchive": string;
|
|
970
1008
|
"documents.archived": string;
|
|
1009
|
+
"documents.archivedLocally": string;
|
|
971
1010
|
"documents.list": string;
|
|
972
1011
|
"documents.activeList": string;
|
|
973
1012
|
"documents.archiveList": string;
|
|
@@ -987,6 +1026,7 @@ export declare const zh: {
|
|
|
987
1026
|
"documents.hash": string;
|
|
988
1027
|
"documents.size": string;
|
|
989
1028
|
"documents.archiveReceipt": string;
|
|
1029
|
+
"documents.archiveNote": string;
|
|
990
1030
|
"documents.archiveTitle": string;
|
|
991
1031
|
"documents.archiveDescription": string;
|
|
992
1032
|
"documents.archive": string;
|
|
@@ -1036,6 +1076,7 @@ export declare const zh: {
|
|
|
1036
1076
|
"runtime.result.remove": string;
|
|
1037
1077
|
"runtime.result.maintenance": string;
|
|
1038
1078
|
"runtime.result.localCompaction": string;
|
|
1079
|
+
"runtime.result.localArchive": string;
|
|
1039
1080
|
"runtime.readOnly": string;
|
|
1040
1081
|
"runtime.footnote": string;
|
|
1041
1082
|
};
|
|
@@ -48,6 +48,7 @@ export declare function WriteReceipt(props: {
|
|
|
48
48
|
error?: string | undefined;
|
|
49
49
|
t?: MnemonTranslate | undefined;
|
|
50
50
|
onView?: (() => void) | undefined;
|
|
51
|
+
viewLabel?: string | undefined;
|
|
51
52
|
}): JSX.Element;
|
|
52
53
|
/** Whether a task Agent can take a write now. */
|
|
53
54
|
export declare function TaskAgentTag(props: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-mnemon",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.25",
|
|
4
4
|
"description": "Composable, view-based memory for DeepSeek Harness. Pluggable sources and strategies, with layered memory out of the box.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"deepseek-harness",
|
|
@@ -157,15 +157,15 @@
|
|
|
157
157
|
"dsh-mnemon-provider-holographic": "0.5.6",
|
|
158
158
|
"dsh-mnemon-provider-honcho": "0.5.5",
|
|
159
159
|
"dsh-mnemon-provider-mem0": "0.5.5",
|
|
160
|
-
"dsh-mnemon-provider-mnemon-native": "0.5.
|
|
160
|
+
"dsh-mnemon-provider-mnemon-native": "0.5.9",
|
|
161
161
|
"dsh-mnemon-provider-openviking": "0.5.7",
|
|
162
162
|
"dsh-mnemon-provider-retaindb": "0.5.5",
|
|
163
163
|
"dsh-mnemon-provider-supermemory": "0.5.5",
|
|
164
|
-
"dsh-mnemon-source-documents": "0.5.
|
|
165
|
-
"dsh-mnemon-source-memory-spaces": "0.5.
|
|
166
|
-
"dsh-mnemon-source-runtime": "0.5.
|
|
164
|
+
"dsh-mnemon-source-documents": "0.5.10",
|
|
165
|
+
"dsh-mnemon-source-memory-spaces": "0.5.17",
|
|
166
|
+
"dsh-mnemon-source-runtime": "0.5.13",
|
|
167
167
|
"dsh-mnemon-strategy-auto-capture": "0.5.5",
|
|
168
|
-
"dsh-mnemon-strategy-default-three-tier": "0.5.
|
|
168
|
+
"dsh-mnemon-strategy-default-three-tier": "0.5.8",
|
|
169
169
|
"dsh-mnemon-strategy-general": "0.5.1",
|
|
170
170
|
"dsh-mnemon-strategy-light-context": "0.5.5",
|
|
171
171
|
"dsh-mnemon-strategy-scoped": "0.5.5",
|