dsh-mnemon 0.3.5 → 0.4.0
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 +4 -2
- package/README.zh-CN.md +4 -2
- package/cordis.patch.yml +0 -1
- package/lib/client.js +2706 -3344
- package/lib/index.js +380 -151
- package/lib/kernel.js +47 -0
- package/lib/types/packages/kernel/src/view.d.ts +11 -0
- package/lib/types/src/agent-memory-turn.d.ts +42 -0
- package/lib/types/src/client/MnemonView.d.ts +0 -2
- package/lib/types/src/client/anchor.d.ts +2 -2
- package/lib/types/src/client/locales.d.ts +18 -84
- package/lib/types/src/client/view-styles.d.ts +2 -0
- package/lib/types/src/config-values.d.ts +1 -1
- package/lib/types/src/config.d.ts +1 -1
- package/lib/types/src/contracts.d.ts +18 -2
- package/lib/types/src/guidance.d.ts +1 -0
- package/lib/types/src/lifecycle.d.ts +4 -0
- package/lib/types/src/live-runtime.d.ts +1 -1
- package/lib/types/src/shared/contracts.d.ts +16 -2
- package/lib/types/src/subagent.d.ts +2 -2
- package/lib/types/src/tools.d.ts +1 -1
- package/package.json +10 -1
- package/lib/types/src/client/MnemonViewAppearance.d.ts +0 -20
package/lib/index.js
CHANGED
|
@@ -23,6 +23,17 @@ const MNEMON_SETTINGS_CHANNEL = "/dsh-mnemon-settings";
|
|
|
23
23
|
const MNEMON_SETTINGS_NAMESPACE = "mnemon";
|
|
24
24
|
const DEFAULT_EMBEDDING_ENDPOINT = "http://localhost:11434";
|
|
25
25
|
const DEFAULT_EMBEDDING_MODEL = "nomic-embed-text";
|
|
26
|
+
const EMBEDDING_PROTOCOL_AUTO = "auto";
|
|
27
|
+
const EMBEDDING_PROTOCOL_OLLAMA = "ollama";
|
|
28
|
+
const EMBEDDING_PROTOCOL_OPENAI = "openai";
|
|
29
|
+
/** Default protocol defers to Mnemon's /v1 auto-detection. */
|
|
30
|
+
const DEFAULT_EMBEDDING_PROTOCOL = EMBEDDING_PROTOCOL_AUTO;
|
|
31
|
+
/** Wire protocols accepted by the embedding protocol override; single source for schema, resolver, and UI validation. */
|
|
32
|
+
const MNEMON_EMBEDDING_PROTOCOLS = [
|
|
33
|
+
EMBEDDING_PROTOCOL_AUTO,
|
|
34
|
+
EMBEDDING_PROTOCOL_OLLAMA,
|
|
35
|
+
EMBEDDING_PROTOCOL_OPENAI
|
|
36
|
+
];
|
|
26
37
|
const CATEGORIES = [
|
|
27
38
|
"preference",
|
|
28
39
|
"decision",
|
|
@@ -114,7 +125,9 @@ const TaskAgentModelSchema = z.object({
|
|
|
114
125
|
const MnemonEmbeddingSchema = z.object({
|
|
115
126
|
enabled: z.boolean().default(false),
|
|
116
127
|
endpoint: z.string().default(DEFAULT_EMBEDDING_ENDPOINT),
|
|
117
|
-
model: z.string().default(DEFAULT_EMBEDDING_MODEL)
|
|
128
|
+
model: z.string().default(DEFAULT_EMBEDDING_MODEL),
|
|
129
|
+
apiKey: z.string().default(""),
|
|
130
|
+
protocol: z.union(MNEMON_EMBEDDING_PROTOCOLS).default(DEFAULT_EMBEDDING_PROTOCOL)
|
|
118
131
|
});
|
|
119
132
|
const RecallQualitySchema = z.object({
|
|
120
133
|
policy: z.string().default(DEFAULT_RECALL_QUALITY_POLICY),
|
|
@@ -175,7 +188,9 @@ const Config = z.object({
|
|
|
175
188
|
embedding: MnemonEmbeddingSchema.default({
|
|
176
189
|
enabled: false,
|
|
177
190
|
endpoint: DEFAULT_EMBEDDING_ENDPOINT,
|
|
178
|
-
model: DEFAULT_EMBEDDING_MODEL
|
|
191
|
+
model: DEFAULT_EMBEDDING_MODEL,
|
|
192
|
+
apiKey: "",
|
|
193
|
+
protocol: DEFAULT_EMBEDDING_PROTOCOL
|
|
179
194
|
}),
|
|
180
195
|
memoryTopology: MemoryTopologySchema,
|
|
181
196
|
recallQuality: RecallQualitySchema.default({
|
|
@@ -187,7 +202,6 @@ const Config = z.object({
|
|
|
187
202
|
maxUnknownResults: 2
|
|
188
203
|
}),
|
|
189
204
|
routingGuidance: z.boolean().default(true),
|
|
190
|
-
displayMode: z.union(["sidebar", "buildin"]).default("sidebar"),
|
|
191
205
|
tabEnabled: z.boolean().default(true),
|
|
192
206
|
writeEnabled: z.boolean().default(true),
|
|
193
207
|
remoteAccess: z.union(["read-only", "trusted-host"]).default("read-only"),
|
|
@@ -325,10 +339,16 @@ function resolveEmbedding(value) {
|
|
|
325
339
|
const normalizedEndpoint = endpoint.replace(/\/+$/u, "");
|
|
326
340
|
const model = optionalText$1(value?.model) ?? "nomic-embed-text";
|
|
327
341
|
if (model.length > 200 || /[\u0000-\u001f\u007f]/u.test(model)) throw new Error("dsh-mnemon: embedding model must contain 1..200 characters without control characters");
|
|
342
|
+
const apiKey = optionalText$1(value?.apiKey) ?? "";
|
|
343
|
+
if (apiKey.length > 2048 || /[\u0000-\u001f\u007f]/u.test(apiKey)) throw new Error("dsh-mnemon: embedding API key must contain 0..2048 characters without control characters");
|
|
344
|
+
const protocol = value?.protocol ?? "auto";
|
|
345
|
+
if (!MNEMON_EMBEDDING_PROTOCOLS.includes(protocol)) throw new Error(`dsh-mnemon: unsupported embedding protocol: ${String(protocol)}`);
|
|
328
346
|
return {
|
|
329
347
|
enabled: value?.enabled === true,
|
|
330
348
|
endpoint: normalizedEndpoint,
|
|
331
|
-
model
|
|
349
|
+
model,
|
|
350
|
+
apiKey,
|
|
351
|
+
protocol
|
|
332
352
|
};
|
|
333
353
|
}
|
|
334
354
|
function resolveRecallQuality(value) {
|
|
@@ -437,7 +457,6 @@ function resolveConfig(config = {}) {
|
|
|
437
457
|
memoryTopology: resolveMemoryTopology(config.memoryTopology),
|
|
438
458
|
recallQuality: resolveRecallQuality(config.recallQuality),
|
|
439
459
|
routingGuidance: config.routingGuidance ?? true,
|
|
440
|
-
displayMode: config.displayMode ?? "sidebar",
|
|
441
460
|
tabEnabled: config.tabEnabled ?? true,
|
|
442
461
|
writeEnabled: config.writeEnabled ?? true,
|
|
443
462
|
remoteAccess: config.remoteAccess ?? "read-only",
|
|
@@ -1930,20 +1949,7 @@ function applyAgentMemoryViewWake(assembly, wake) {
|
|
|
1930
1949
|
name: RUNTIME_MEMORY_PROTOCOL_SECTION_NAME,
|
|
1931
1950
|
text: protocol
|
|
1932
1951
|
});
|
|
1933
|
-
const
|
|
1934
|
-
let found = false;
|
|
1935
|
-
const contexts = assembly.contexts.map((context) => {
|
|
1936
|
-
if (context.name !== "mnemon:runtime-memory") return context;
|
|
1937
|
-
found = true;
|
|
1938
|
-
return {
|
|
1939
|
-
...context,
|
|
1940
|
-
text: rendered
|
|
1941
|
-
};
|
|
1942
|
-
});
|
|
1943
|
-
if (!found) contexts.push({
|
|
1944
|
-
name: RUNTIME_MEMORY_CONTEXT_NAME,
|
|
1945
|
-
text: rendered
|
|
1946
|
-
});
|
|
1952
|
+
const contexts = assembly.contexts.filter((context) => context.name !== RUNTIME_MEMORY_CONTEXT_NAME);
|
|
1947
1953
|
return {
|
|
1948
1954
|
...assembly,
|
|
1949
1955
|
sections,
|
|
@@ -1963,21 +1969,12 @@ function registerGuidance(ctx, config) {
|
|
|
1963
1969
|
}
|
|
1964
1970
|
/** Project only the immutable Wake pinned by the root Agent lifecycle. */
|
|
1965
1971
|
function registerAgentMemoryViewContext(agent, wake) {
|
|
1966
|
-
const
|
|
1967
|
-
const stopProtocol = prompt?.section?.({
|
|
1972
|
+
const stopProtocol = scopedSystemPrompt(agent)?.section?.({
|
|
1968
1973
|
name: RUNTIME_MEMORY_PROTOCOL_SECTION_NAME,
|
|
1969
1974
|
order: 145,
|
|
1970
1975
|
text: () => wakeHasRuntimeMemory(wake()) ? RUNTIME_MEMORY_PROTOCOL : ""
|
|
1971
1976
|
});
|
|
1972
|
-
|
|
1973
|
-
name: RUNTIME_MEMORY_CONTEXT_NAME,
|
|
1974
|
-
order: 145,
|
|
1975
|
-
text: () => {
|
|
1976
|
-
const current = wake();
|
|
1977
|
-
return current === void 0 ? "" : memoryPromptText(current.text);
|
|
1978
|
-
}
|
|
1979
|
-
});
|
|
1980
|
-
return disposer(stopProtocol, stopContext);
|
|
1977
|
+
return disposer(stopProtocol);
|
|
1981
1978
|
}
|
|
1982
1979
|
//#endregion
|
|
1983
1980
|
//#region src/pack.ts
|
|
@@ -2820,20 +2817,25 @@ function findMnemonCommand(config, options = {}) {
|
|
|
2820
2817
|
const env = options.env ?? process.env;
|
|
2821
2818
|
const home = options.home ?? homedir();
|
|
2822
2819
|
const isExecutable = options.isExecutable ?? ((path) => executable$1(path, platform));
|
|
2823
|
-
if (config.cliPath !== void 0) return expandHome$1(config.cliPath, home, platform);
|
|
2824
|
-
const envPath = envValue(env, "MNEMON_CLI_PATH", platform)?.trim();
|
|
2825
|
-
if (envPath !== void 0 && envPath !== "") {
|
|
2826
|
-
const path = expandHome$1(envPath, home, platform);
|
|
2827
|
-
if (isExecutable(path)) return path;
|
|
2828
|
-
}
|
|
2829
2820
|
const paths = pathApi(platform);
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2821
|
+
const resolveCommand = (command) => {
|
|
2822
|
+
const expanded = expandHome$1(command, home, platform);
|
|
2823
|
+
if (expanded.includes("/") || expanded.includes("\\")) return expanded;
|
|
2824
|
+
const name = platform === "win32" && paths.extname(expanded) === "" ? `${expanded}.exe` : expanded;
|
|
2825
|
+
for (const directory of (envValue(env, "PATH", platform) ?? "").split(paths.delimiter)) {
|
|
2826
|
+
if (directory === "") continue;
|
|
2833
2827
|
const path = paths.join(directory, name);
|
|
2834
2828
|
if (isExecutable(path)) return path;
|
|
2835
2829
|
}
|
|
2830
|
+
};
|
|
2831
|
+
if (config.cliPath !== void 0) return resolveCommand(config.cliPath);
|
|
2832
|
+
const envPath = envValue(env, "MNEMON_CLI_PATH", platform)?.trim();
|
|
2833
|
+
if (envPath !== void 0 && envPath !== "") {
|
|
2834
|
+
const path = resolveCommand(envPath);
|
|
2835
|
+
if (path !== void 0 && isExecutable(path)) return path;
|
|
2836
2836
|
}
|
|
2837
|
+
const fromPath = resolveCommand("mnemon");
|
|
2838
|
+
if (fromPath !== void 0) return fromPath;
|
|
2837
2839
|
for (const path of commonCliPaths(platform, env, home)) if (isExecutable(path)) return path;
|
|
2838
2840
|
}
|
|
2839
2841
|
var MnemonCliError = class extends Error {
|
|
@@ -2846,19 +2848,25 @@ var MnemonCliError = class extends Error {
|
|
|
2846
2848
|
this.stderr = stderr;
|
|
2847
2849
|
}
|
|
2848
2850
|
};
|
|
2849
|
-
const EMBEDDING_ENVIRONMENT_KEYS = /* @__PURE__ */ new Set([
|
|
2851
|
+
const EMBEDDING_ENVIRONMENT_KEYS = /* @__PURE__ */ new Set([
|
|
2852
|
+
"MNEMON_EMBED_ENDPOINT",
|
|
2853
|
+
"MNEMON_EMBED_MODEL",
|
|
2854
|
+
"MNEMON_EMBED_API_KEY",
|
|
2855
|
+
"MNEMON_EMBED_PROTOCOL"
|
|
2856
|
+
]);
|
|
2850
2857
|
/** Preserve the Host environment while making saved embedding overrides authoritative. */
|
|
2851
2858
|
function processEnvironment(config) {
|
|
2852
2859
|
if (!config.embedding.enabled) return void 0;
|
|
2853
2860
|
return {
|
|
2854
2861
|
...Object.fromEntries(Object.entries(process.env).filter(([key]) => !EMBEDDING_ENVIRONMENT_KEYS.has(key.toUpperCase()))),
|
|
2855
2862
|
MNEMON_EMBED_ENDPOINT: config.embedding.endpoint,
|
|
2856
|
-
MNEMON_EMBED_MODEL: config.embedding.model
|
|
2863
|
+
MNEMON_EMBED_MODEL: config.embedding.model,
|
|
2864
|
+
MNEMON_EMBED_API_KEY: config.embedding.apiKey,
|
|
2865
|
+
...config.embedding.protocol === "auto" ? {} : { MNEMON_EMBED_PROTOCOL: config.embedding.protocol }
|
|
2857
2866
|
};
|
|
2858
2867
|
}
|
|
2859
2868
|
function createRunner(config, processRunner = runProcess, workspaceRoot) {
|
|
2860
|
-
const
|
|
2861
|
-
const command = found ?? config.cliPath ?? "mnemon";
|
|
2869
|
+
const currentCommand = () => findMnemonCommand(config) ?? config.cliPath ?? "mnemon";
|
|
2862
2870
|
let processQueue = Promise.resolve();
|
|
2863
2871
|
const globalArgs = (store) => {
|
|
2864
2872
|
const args = [];
|
|
@@ -2891,7 +2899,7 @@ function createRunner(config, processRunner = runProcess, workspaceRoot) {
|
|
|
2891
2899
|
};
|
|
2892
2900
|
let result;
|
|
2893
2901
|
try {
|
|
2894
|
-
result = await processRunner(
|
|
2902
|
+
result = await processRunner(currentCommand(), argv, processOptions);
|
|
2895
2903
|
} catch (error) {
|
|
2896
2904
|
throw new MnemonCliError(`${error instanceof Error ? error.message : String(error)}. ${process.platform === "win32" ? "Install the official Mnemon Windows release, ensure mnemon.exe is on PATH or under %LOCALAPPDATA%\\Programs\\mnemon, or set MNEMON_CLI_PATH or mnemon.cliPath to its absolute path." : "Install Mnemon and ensure \"mnemon\" is on PATH, or set MNEMON_CLI_PATH or mnemon.cliPath."}`);
|
|
2897
2905
|
}
|
|
@@ -2907,8 +2915,13 @@ function createRunner(config, processRunner = runProcess, workspaceRoot) {
|
|
|
2907
2915
|
return result;
|
|
2908
2916
|
};
|
|
2909
2917
|
return {
|
|
2910
|
-
command
|
|
2911
|
-
|
|
2918
|
+
get command() {
|
|
2919
|
+
return currentCommand();
|
|
2920
|
+
},
|
|
2921
|
+
get commandFound() {
|
|
2922
|
+
const found = findMnemonCommand(config);
|
|
2923
|
+
return found !== void 0 && executable$1(found);
|
|
2924
|
+
},
|
|
2912
2925
|
config,
|
|
2913
2926
|
async runJson(args, options) {
|
|
2914
2927
|
const stdout = await execute(args, options);
|
|
@@ -4318,8 +4331,9 @@ var MnemonService = class {
|
|
|
4318
4331
|
/** Probe the effective Mnemon embedding runtime and its default Store coverage. */
|
|
4319
4332
|
async embeddingStatus(signal) {
|
|
4320
4333
|
const output = record$1(await this.runner.runJson(["embed", "--status"], signal === void 0 ? {} : { signal }));
|
|
4321
|
-
const available = output?.ollama_available;
|
|
4334
|
+
const available = output?.embedding_available ?? output?.ollama_available;
|
|
4322
4335
|
const model = text$1(output?.model)?.trim();
|
|
4336
|
+
const protocol = text$1(output?.protocol)?.trim();
|
|
4323
4337
|
const totalInsights = number(output?.total_insights);
|
|
4324
4338
|
const embedded = number(output?.embedded);
|
|
4325
4339
|
const coverage = text$1(output?.coverage)?.trim();
|
|
@@ -4329,7 +4343,8 @@ var MnemonService = class {
|
|
|
4329
4343
|
model,
|
|
4330
4344
|
totalInsights,
|
|
4331
4345
|
embedded,
|
|
4332
|
-
coverage
|
|
4346
|
+
coverage,
|
|
4347
|
+
...protocol !== void 0 && protocol.length <= 32 && !/[\u0000-\u001f\u007f]/u.test(protocol) ? { protocol } : {}
|
|
4333
4348
|
};
|
|
4334
4349
|
}
|
|
4335
4350
|
async status(signal) {
|
|
@@ -6412,8 +6427,16 @@ function boundedModelText(value, maximum) {
|
|
|
6412
6427
|
function insightDigest(result) {
|
|
6413
6428
|
return sha256(result.content.trim().replace(/\s+/gu, " "));
|
|
6414
6429
|
}
|
|
6415
|
-
function recallQueryDigest(
|
|
6416
|
-
|
|
6430
|
+
function recallQueryDigest(request) {
|
|
6431
|
+
const lexical = (request.query.match(/[\p{L}\p{N}]+/gu) ?? []).join(" ").toLocaleLowerCase();
|
|
6432
|
+
return sha256(JSON.stringify({
|
|
6433
|
+
query: lexical,
|
|
6434
|
+
memoryBodyIds: [...request.memoryBodyIds ?? []].sort()
|
|
6435
|
+
}));
|
|
6436
|
+
}
|
|
6437
|
+
/** A replay must still respect the current call's selected Source subset. */
|
|
6438
|
+
function replayEvidence(results, memoryBodyIds) {
|
|
6439
|
+
return structuredClone(memoryBodyIds === void 0 ? results : results.filter((result) => result.memoryBodyId !== void 0 && memoryBodyIds.includes(result.memoryBodyId)));
|
|
6417
6440
|
}
|
|
6418
6441
|
/** Admit a small, deduplicated evidence envelope after Provider quality policy. */
|
|
6419
6442
|
function boundedModelInsights(results, admission = {}) {
|
|
@@ -6863,7 +6886,7 @@ var MnemonSubagentCoordinator = class {
|
|
|
6863
6886
|
};
|
|
6864
6887
|
runtimeQueue = Promise.resolve();
|
|
6865
6888
|
documentQueue = Promise.resolve();
|
|
6866
|
-
retrievalTurns = /* @__PURE__ */ new
|
|
6889
|
+
retrievalTurns = /* @__PURE__ */ new WeakMap();
|
|
6867
6890
|
constructor(subagents, runtimeMemoryOrSource, documents, resultRuntime, taskAgentModelResolver, runtimeMaintenanceMaxTokensResolver) {
|
|
6868
6891
|
this.subagents = subagents;
|
|
6869
6892
|
this.runtimeMemoryOrSource = runtimeMemoryOrSource;
|
|
@@ -6887,17 +6910,19 @@ var MnemonSubagentCoordinator = class {
|
|
|
6887
6910
|
...limit === void 0 ? {} : { limit }
|
|
6888
6911
|
});
|
|
6889
6912
|
}
|
|
6890
|
-
/** Admit at most one model-facing Documents query for one
|
|
6913
|
+
/** Admit at most one model-facing Documents query for one executing turn. */
|
|
6891
6914
|
claimDocumentSearch(parent) {
|
|
6892
6915
|
const authority = this.turnAuthority(parent, false);
|
|
6893
6916
|
if (authority === void 0) return true;
|
|
6894
|
-
const retrieval = this.turnRetrievalState(authority.
|
|
6917
|
+
const retrieval = this.turnRetrievalState(authority.context);
|
|
6895
6918
|
if (retrieval.documentSearchClaimed === true) return false;
|
|
6896
6919
|
retrieval.documentSearchClaimed = true;
|
|
6897
6920
|
return true;
|
|
6898
6921
|
}
|
|
6899
6922
|
async recall(parent, request, signal, options = {}) {
|
|
6923
|
+
signal.throwIfAborted();
|
|
6900
6924
|
const authority = this.recallAuthority(parent, options.requirePinnedView === true);
|
|
6925
|
+
const service = authority?.service ?? this.serviceFor(parent);
|
|
6901
6926
|
const limited = {
|
|
6902
6927
|
query: request.query,
|
|
6903
6928
|
...request.mode === void 0 ? {} : { mode: request.mode },
|
|
@@ -6905,15 +6930,15 @@ var MnemonSubagentCoordinator = class {
|
|
|
6905
6930
|
...request.memoryBodyIds === void 0 ? {} : { memoryBodyIds: request.memoryBodyIds }
|
|
6906
6931
|
};
|
|
6907
6932
|
const scoped = this.scopeRecallWithAuthority(limited, authority);
|
|
6908
|
-
const digest = authority === void 0 ? void 0 : recallQueryDigest(scoped
|
|
6909
|
-
const retrieval = authority === void 0 ? void 0 : this.turnRetrievalState(authority.
|
|
6933
|
+
const digest = authority === void 0 ? void 0 : recallQueryDigest(scoped);
|
|
6934
|
+
const retrieval = authority === void 0 ? void 0 : this.turnRetrievalState(authority.context);
|
|
6910
6935
|
const repeated = digest === void 0 ? void 0 : retrieval?.recallAttempts.find((attempt) => attempt.queryDigest === digest);
|
|
6911
6936
|
if (repeated !== void 0) {
|
|
6912
6937
|
const previous = repeated.result ?? await repeated.pending;
|
|
6913
6938
|
return {
|
|
6914
6939
|
query: previous?.query ?? scoped.query,
|
|
6915
6940
|
mode: previous?.mode ?? scoped.mode ?? "smart",
|
|
6916
|
-
results:
|
|
6941
|
+
results: replayEvidence(previous?.results ?? [], scoped.memoryBodyIds),
|
|
6917
6942
|
hint: retrieval?.recallAttempts.length === MODEL_RECALL_ATTEMPT_LIMIT ? "This Recall query already ran. The Host replayed its admitted evidence without another Provider query. The turn Recall budget is closed; stop retrieval and answer from the evidence or state what remains unknown." : "This Recall query already ran. The Host replayed its admitted evidence without another Provider query. If this evidence is insufficient, use at most one materially different focused query; otherwise stop retrieval."
|
|
6918
6943
|
};
|
|
6919
6944
|
}
|
|
@@ -6923,7 +6948,7 @@ var MnemonSubagentCoordinator = class {
|
|
|
6923
6948
|
return {
|
|
6924
6949
|
query: previous?.query ?? scoped.query,
|
|
6925
6950
|
mode: previous?.mode ?? scoped.mode ?? "smart",
|
|
6926
|
-
results:
|
|
6951
|
+
results: replayEvidence(previous?.results ?? [], scoped.memoryBodyIds),
|
|
6927
6952
|
hint: "The two-query turn Recall budget is exhausted. The Host replayed the latest admitted evidence without another Provider query; stop retrieval and answer from the evidence or state what remains unknown."
|
|
6928
6953
|
};
|
|
6929
6954
|
}
|
|
@@ -6933,7 +6958,8 @@ var MnemonSubagentCoordinator = class {
|
|
|
6933
6958
|
if (attempt !== void 0 && retrieval !== void 0) retrieval.recallAttempts.push(attempt);
|
|
6934
6959
|
const operation = (async () => {
|
|
6935
6960
|
if (predecessor !== void 0) await predecessor;
|
|
6936
|
-
|
|
6961
|
+
signal.throwIfAborted();
|
|
6962
|
+
const result = await service.search(scoped, signal);
|
|
6937
6963
|
const priorResults = (retrieval?.recallAttempts.slice(0, attemptIndex) ?? []).flatMap((entry) => entry.result?.results ?? []);
|
|
6938
6964
|
const priorContentCharacters = priorResults.reduce((total, insight) => total + insight.content.length, 0);
|
|
6939
6965
|
const requestedLimit = Math.min(limited.limit ?? MODEL_RECALL_RESULT_LIMIT, MODEL_RECALL_RESULT_LIMIT);
|
|
@@ -6974,7 +7000,7 @@ var MnemonSubagentCoordinator = class {
|
|
|
6974
7000
|
if (attempt?.pending === operation) delete attempt.pending;
|
|
6975
7001
|
}
|
|
6976
7002
|
}
|
|
6977
|
-
/** Bind a model read to the Source state pinned by its
|
|
7003
|
+
/** Bind a model read to the Source state pinned by its own executing turn. */
|
|
6978
7004
|
scopeRecallRequest(agent, request, requirePinnedView = false) {
|
|
6979
7005
|
const authority = this.recallAuthority(agent, requirePinnedView);
|
|
6980
7006
|
return this.scopeRecallWithAuthority(request, authority);
|
|
@@ -7004,9 +7030,11 @@ var MnemonSubagentCoordinator = class {
|
|
|
7004
7030
|
return requested;
|
|
7005
7031
|
}
|
|
7006
7032
|
async related(parent, id, memoryBodyId, signal, options = {}) {
|
|
7033
|
+
signal.throwIfAborted();
|
|
7007
7034
|
const authority = this.recallAuthority(parent, options.requirePinnedView === true);
|
|
7035
|
+
const service = authority?.service ?? this.serviceFor(parent);
|
|
7008
7036
|
const selected = this.scopeRelatedWithAuthority(memoryBodyId, authority);
|
|
7009
|
-
const retrieval = authority === void 0 ? void 0 : this.turnRetrievalState(authority.
|
|
7037
|
+
const retrieval = authority === void 0 ? void 0 : this.turnRetrievalState(authority.context);
|
|
7010
7038
|
const reference = `${selected ?? ""}/${id}`;
|
|
7011
7039
|
if (retrieval !== void 0 && !retrieval.evidenceReferences.has(reference)) return {
|
|
7012
7040
|
query: `related:${id}`,
|
|
@@ -7025,13 +7053,13 @@ var MnemonSubagentCoordinator = class {
|
|
|
7025
7053
|
return {
|
|
7026
7054
|
query: previous?.query ?? `related:${id}`,
|
|
7027
7055
|
mode: previous?.mode ?? "related",
|
|
7028
|
-
results:
|
|
7056
|
+
results: replayEvidence(previous?.results ?? [], selected === void 0 ? void 0 : [selected]),
|
|
7029
7057
|
hint: retrieval.relatedDigest === digest ? "This exact Related traversal already ran. The Host replayed its admitted evidence without another Provider query; stop retrieval and answer from it." : "Related traversal is complete for this turn. The Host replayed the admitted evidence; stop retrieval and answer from it."
|
|
7030
7058
|
};
|
|
7031
7059
|
}
|
|
7032
7060
|
if (retrieval !== void 0 && digest !== void 0) retrieval.relatedDigest = digest;
|
|
7033
7061
|
const operation = (async () => {
|
|
7034
|
-
const admitted = boundedModelInsights(await
|
|
7062
|
+
const admitted = boundedModelInsights(await service.related(id, options.depth, options.edge, signal, selected), {
|
|
7035
7063
|
resultLimit: 4,
|
|
7036
7064
|
totalContentLimit: 4e3,
|
|
7037
7065
|
mediumLimit: 4,
|
|
@@ -7630,45 +7658,38 @@ Completion protocol: call \`${resultToolName}\` exactly once with the final resu
|
|
|
7630
7658
|
}
|
|
7631
7659
|
recallAuthority(agent, required) {
|
|
7632
7660
|
const authority = this.turnAuthority(agent, required);
|
|
7633
|
-
if (authority === void 0
|
|
7634
|
-
const
|
|
7635
|
-
|
|
7661
|
+
if (authority === void 0) return void 0;
|
|
7662
|
+
const { context, graph } = authority;
|
|
7663
|
+
const value = optionalObject(graph.memoryViews.sourceState(context.viewId, "memory-spaces"));
|
|
7664
|
+
if (value === void 0 || !Array.isArray(value.memoryBodyIds) || value.memoryBodyIds.some((id) => typeof id !== "string" || id.trim() === "")) throw new Error(`pinned MemorySource has invalid recall authority: ${context.viewId}`);
|
|
7636
7665
|
const memoryBodyIds = [...new Set(value.memoryBodyIds.map((id) => String(id).trim()))];
|
|
7637
|
-
if (memoryBodyIds.length === 0) throw new Error(`pinned MemorySource has no recall-authorized Memory Spaces: ${
|
|
7666
|
+
if (memoryBodyIds.length === 0) throw new Error(`pinned MemorySource has no recall-authorized Memory Spaces: ${context.viewId}`);
|
|
7638
7667
|
return {
|
|
7639
|
-
|
|
7640
|
-
|
|
7668
|
+
context,
|
|
7669
|
+
viewId: context.viewId,
|
|
7670
|
+
memoryBodyIds,
|
|
7671
|
+
service: graph.service
|
|
7641
7672
|
};
|
|
7642
7673
|
}
|
|
7643
7674
|
turnAuthority(agent, required) {
|
|
7644
7675
|
if (!isAgentRuntimeSource$1(this.runtimeMemoryOrSource)) return void 0;
|
|
7645
|
-
const
|
|
7646
|
-
const
|
|
7647
|
-
|
|
7648
|
-
|
|
7649
|
-
|
|
7650
|
-
if (required) throw new Error("Recall requires the MemorySource generation pinned to the current turn");
|
|
7651
|
-
return;
|
|
7652
|
-
}
|
|
7653
|
-
return {
|
|
7654
|
-
turnId: pinned.turnId,
|
|
7655
|
-
viewId: pinned.viewId
|
|
7676
|
+
const graph = this.runtimeMemoryOrSource.forAgent(agent);
|
|
7677
|
+
const context = graph.memoryViews.activeTurn(agent.id);
|
|
7678
|
+
if (context !== void 0) return {
|
|
7679
|
+
context,
|
|
7680
|
+
graph
|
|
7656
7681
|
};
|
|
7682
|
+
if (required) throw new Error("Recall requires the MemorySource generation pinned to the current turn");
|
|
7657
7683
|
}
|
|
7658
|
-
turnRetrievalState(
|
|
7659
|
-
const current = this.retrievalTurns.get(
|
|
7684
|
+
turnRetrievalState(context) {
|
|
7685
|
+
const current = this.retrievalTurns.get(context);
|
|
7660
7686
|
if (current !== void 0) return current;
|
|
7661
|
-
while (this.retrievalTurns.size >= 128) {
|
|
7662
|
-
const oldest = this.retrievalTurns.keys().next().value;
|
|
7663
|
-
if (oldest === void 0) break;
|
|
7664
|
-
this.retrievalTurns.delete(oldest);
|
|
7665
|
-
}
|
|
7666
7687
|
const created = {
|
|
7667
7688
|
recallAttempts: [],
|
|
7668
7689
|
evidenceDigests: /* @__PURE__ */ new Set(),
|
|
7669
7690
|
evidenceReferences: /* @__PURE__ */ new Set()
|
|
7670
7691
|
};
|
|
7671
|
-
this.retrievalTurns.set(
|
|
7692
|
+
this.retrievalTurns.set(context, created);
|
|
7672
7693
|
return created;
|
|
7673
7694
|
}
|
|
7674
7695
|
recordRecall() {
|
|
@@ -7829,6 +7850,148 @@ var TurnActivityProjection = class {
|
|
|
7829
7850
|
}
|
|
7830
7851
|
};
|
|
7831
7852
|
//#endregion
|
|
7853
|
+
//#region src/agent-memory-turn.ts
|
|
7854
|
+
function agentMemoryScope(agent, graph) {
|
|
7855
|
+
const cwd = agent.session.header?.cwd?.trim();
|
|
7856
|
+
return {
|
|
7857
|
+
storage: graph.config.storageScope,
|
|
7858
|
+
...cwd === void 0 || cwd === "" ? {} : { workspaceId: resolve(cwd) },
|
|
7859
|
+
sessionId: agent.id,
|
|
7860
|
+
agentId: agent.id
|
|
7861
|
+
};
|
|
7862
|
+
}
|
|
7863
|
+
/** The durable log, not a parent session id, identifies the executing turn. */
|
|
7864
|
+
function openAgentTurn(agent) {
|
|
7865
|
+
let open;
|
|
7866
|
+
for (const event of agent.session.events) {
|
|
7867
|
+
const turn = typeof event.data.turn === "number" ? event.data.turn : void 0;
|
|
7868
|
+
if (event.type === "turn/start" && turn !== void 0) open = turn;
|
|
7869
|
+
else if (event.type === "turn/end" && turn === open) open = void 0;
|
|
7870
|
+
}
|
|
7871
|
+
return open;
|
|
7872
|
+
}
|
|
7873
|
+
/**
|
|
7874
|
+
* One Agent owns each turn pin. A child additionally retains its delegation
|
|
7875
|
+
* across parent completion, collection, and runtime swaps until it is disposed.
|
|
7876
|
+
*/
|
|
7877
|
+
var AgentMemoryTurn = class {
|
|
7878
|
+
agent;
|
|
7879
|
+
runtime;
|
|
7880
|
+
delegation;
|
|
7881
|
+
pinned;
|
|
7882
|
+
pending;
|
|
7883
|
+
generation = 0;
|
|
7884
|
+
closed = false;
|
|
7885
|
+
releaseDelegation;
|
|
7886
|
+
constructor(agent, runtime, delegation) {
|
|
7887
|
+
this.agent = agent;
|
|
7888
|
+
this.runtime = runtime;
|
|
7889
|
+
this.delegation = delegation;
|
|
7890
|
+
if (delegation === void 0) return;
|
|
7891
|
+
const releaseView = delegation.viewId === void 0 ? void 0 : delegation.graph.memoryViews.retainView(delegation.viewId);
|
|
7892
|
+
try {
|
|
7893
|
+
const releaseRuntime = runtime.bindAgentRuntime(agent.id, delegation.graph);
|
|
7894
|
+
this.releaseDelegation = () => {
|
|
7895
|
+
try {
|
|
7896
|
+
releaseView?.();
|
|
7897
|
+
} finally {
|
|
7898
|
+
releaseRuntime();
|
|
7899
|
+
}
|
|
7900
|
+
};
|
|
7901
|
+
} catch (error) {
|
|
7902
|
+
releaseView?.();
|
|
7903
|
+
throw error;
|
|
7904
|
+
}
|
|
7905
|
+
}
|
|
7906
|
+
get current() {
|
|
7907
|
+
return this.pinned;
|
|
7908
|
+
}
|
|
7909
|
+
/** Capture now; descendants must not resolve a later parent turn on demand. */
|
|
7910
|
+
delegate() {
|
|
7911
|
+
if (this.closed) throw new Error("memory Agent lifetime has ended");
|
|
7912
|
+
if (this.pinned !== void 0) return {
|
|
7913
|
+
graph: this.pinned.graph,
|
|
7914
|
+
scope: this.pinned.context.scope,
|
|
7915
|
+
viewId: this.pinned.context.viewId
|
|
7916
|
+
};
|
|
7917
|
+
if (this.delegation !== void 0) return this.delegation;
|
|
7918
|
+
const graph = this.runtime.forAgent(this.agent);
|
|
7919
|
+
return {
|
|
7920
|
+
graph,
|
|
7921
|
+
scope: agentMemoryScope(this.agent, graph)
|
|
7922
|
+
};
|
|
7923
|
+
}
|
|
7924
|
+
async begin(turn, signal) {
|
|
7925
|
+
if (this.closed) throw new Error("memory Agent lifetime has ended");
|
|
7926
|
+
signal?.throwIfAborted();
|
|
7927
|
+
if (this.pinned?.turn === turn) return;
|
|
7928
|
+
if (this.pending?.turn === turn) return this.pending.result;
|
|
7929
|
+
this.end();
|
|
7930
|
+
const generation = this.generation;
|
|
7931
|
+
const result = this.pin(turn, generation, signal);
|
|
7932
|
+
this.pending = {
|
|
7933
|
+
turn,
|
|
7934
|
+
generation,
|
|
7935
|
+
result
|
|
7936
|
+
};
|
|
7937
|
+
try {
|
|
7938
|
+
await result;
|
|
7939
|
+
} finally {
|
|
7940
|
+
if (this.pending?.generation === generation) this.pending = void 0;
|
|
7941
|
+
}
|
|
7942
|
+
}
|
|
7943
|
+
end(turn) {
|
|
7944
|
+
if (turn !== void 0 && this.pinned?.turn !== turn && this.pending?.turn !== turn) return;
|
|
7945
|
+
this.generation += 1;
|
|
7946
|
+
this.pending = void 0;
|
|
7947
|
+
const pinned = this.pinned;
|
|
7948
|
+
this.pinned = void 0;
|
|
7949
|
+
if (pinned === void 0) return;
|
|
7950
|
+
try {
|
|
7951
|
+
if (pinned.manager.turn(pinned.context.turnId) === pinned.context) pinned.manager.endTurn(pinned.context.turnId);
|
|
7952
|
+
} finally {
|
|
7953
|
+
pinned.releaseRuntime?.();
|
|
7954
|
+
}
|
|
7955
|
+
}
|
|
7956
|
+
dispose() {
|
|
7957
|
+
if (this.closed) return;
|
|
7958
|
+
this.closed = true;
|
|
7959
|
+
try {
|
|
7960
|
+
this.end();
|
|
7961
|
+
} finally {
|
|
7962
|
+
this.releaseDelegation?.();
|
|
7963
|
+
}
|
|
7964
|
+
}
|
|
7965
|
+
async pin(turn, generation, signal) {
|
|
7966
|
+
const graph = this.delegation?.graph ?? this.runtime.forAgent(this.agent);
|
|
7967
|
+
const manager = graph.memoryViews;
|
|
7968
|
+
const scope = this.delegation === void 0 ? agentMemoryScope(this.agent, graph) : {
|
|
7969
|
+
...this.delegation.scope,
|
|
7970
|
+
sessionId: this.agent.id,
|
|
7971
|
+
agentId: this.agent.id
|
|
7972
|
+
};
|
|
7973
|
+
const turnId = `${this.agent.id}:${turn}`;
|
|
7974
|
+
const context = this.delegation?.viewId === void 0 ? await manager.beginTurn(turnId, scope) : manager.pinTurn(turnId, scope, this.delegation.viewId);
|
|
7975
|
+
let releaseRuntime;
|
|
7976
|
+
try {
|
|
7977
|
+
if (this.closed || this.generation !== generation) throw new Error("memory turn ended during View preparation");
|
|
7978
|
+
signal?.throwIfAborted();
|
|
7979
|
+
if (this.delegation === void 0) releaseRuntime = this.runtime.bindAgentRuntime(this.agent.id, graph);
|
|
7980
|
+
this.pinned = {
|
|
7981
|
+
turn,
|
|
7982
|
+
graph,
|
|
7983
|
+
manager,
|
|
7984
|
+
context,
|
|
7985
|
+
...releaseRuntime === void 0 ? {} : { releaseRuntime }
|
|
7986
|
+
};
|
|
7987
|
+
} catch (error) {
|
|
7988
|
+
if (manager.turn(context.turnId) === context) manager.endTurn(context.turnId);
|
|
7989
|
+
releaseRuntime?.();
|
|
7990
|
+
throw error;
|
|
7991
|
+
}
|
|
7992
|
+
}
|
|
7993
|
+
};
|
|
7994
|
+
//#endregion
|
|
7832
7995
|
//#region src/lifecycle.ts
|
|
7833
7996
|
function modelService(value) {
|
|
7834
7997
|
if (typeof value !== "object" || value === null || !("currentSelection" in value) || typeof value.currentSelection !== "function") return void 0;
|
|
@@ -7935,7 +8098,7 @@ var MnemonAgentLifecycle = class {
|
|
|
7935
8098
|
coordinator;
|
|
7936
8099
|
config;
|
|
7937
8100
|
counters;
|
|
7938
|
-
|
|
8101
|
+
memoryTurn;
|
|
7939
8102
|
primePending = true;
|
|
7940
8103
|
startSource;
|
|
7941
8104
|
guidedTurns = /* @__PURE__ */ new Set();
|
|
@@ -7947,6 +8110,14 @@ var MnemonAgentLifecycle = class {
|
|
|
7947
8110
|
* actually see, which is what makes a rewind self-correcting.
|
|
7948
8111
|
*/
|
|
7949
8112
|
cueInjected = false;
|
|
8113
|
+
/**
|
|
8114
|
+
* Text of the runtime memory snapshot most recently injected as this
|
|
8115
|
+
* plugin's own message. `.context()` used to get supersede-on-change for free
|
|
8116
|
+
* from the host's runtime-context projection; carrying the snapshot as an own
|
|
8117
|
+
* message means re-emitting on change is this plugin's responsibility, and
|
|
8118
|
+
* the rendered text (which carries the revision digest) is the key.
|
|
8119
|
+
*/
|
|
8120
|
+
injectedMemoryText;
|
|
7950
8121
|
idleReviewTimer;
|
|
7951
8122
|
reviewController;
|
|
7952
8123
|
reviewRunning = false;
|
|
@@ -7957,13 +8128,12 @@ var MnemonAgentLifecycle = class {
|
|
|
7957
8128
|
lastPhase = "idle";
|
|
7958
8129
|
lastAt;
|
|
7959
8130
|
lastError;
|
|
7960
|
-
|
|
7961
|
-
constructor(agent, coordinator, config, counters, source, runtimeSource) {
|
|
8131
|
+
constructor(agent, coordinator, config, counters, source, memoryTurn) {
|
|
7962
8132
|
this.agent = agent;
|
|
7963
8133
|
this.coordinator = coordinator;
|
|
7964
8134
|
this.config = config;
|
|
7965
8135
|
this.counters = counters;
|
|
7966
|
-
this.
|
|
8136
|
+
this.memoryTurn = memoryTurn;
|
|
7967
8137
|
this.startSource = source;
|
|
7968
8138
|
}
|
|
7969
8139
|
start() {
|
|
@@ -7981,7 +8151,7 @@ var MnemonAgentLifecycle = class {
|
|
|
7981
8151
|
})),
|
|
7982
8152
|
this.agent.ctx.on("session/event", ((session, event) => this.sessionEvent(session, event))),
|
|
7983
8153
|
this.agent.ctx.on("system-prompt/assemble", ((assembly, context, next) => this.assemblePrompt(assembly, context, next))),
|
|
7984
|
-
this.agent.ctx.on("agent/pre-step", ((payload, next) => this.preStep(payload, next))),
|
|
8154
|
+
this.agent.ctx.on("agent/pre-step", ((payload, next) => this.preStep(payload, next)), { prepend: true }),
|
|
7985
8155
|
this.agent.ctx.on("agent/turn-stopping", ((payload) => this.finishTurn(payload)))
|
|
7986
8156
|
];
|
|
7987
8157
|
return () => {
|
|
@@ -8023,7 +8193,7 @@ var MnemonAgentLifecycle = class {
|
|
|
8023
8193
|
return assistantMessageText(this.agent.session.events, messageId);
|
|
8024
8194
|
}
|
|
8025
8195
|
memoryWake() {
|
|
8026
|
-
const pinned = this.
|
|
8196
|
+
const pinned = this.memoryTurn?.current;
|
|
8027
8197
|
return pinned === void 0 ? void 0 : pinned.manager.wake(pinned.context.viewId);
|
|
8028
8198
|
}
|
|
8029
8199
|
/**
|
|
@@ -8044,6 +8214,23 @@ var MnemonAgentLifecycle = class {
|
|
|
8044
8214
|
for (const seq of nodes) if (isOwnUserMessageEvent(this.agent.session.events[seq])) return true;
|
|
8045
8215
|
return false;
|
|
8046
8216
|
}
|
|
8217
|
+
/**
|
|
8218
|
+
* The runtime memory snapshot, as this plugin's own message, when it changed.
|
|
8219
|
+
*
|
|
8220
|
+
* `.context()` used to carry this inside the host's shared runtime-context
|
|
8221
|
+
* projection. Carrying it here instead attributes it to dsh-mnemon and keeps
|
|
8222
|
+
* a memory write from re-emitting other contributors' sections; supersede
|
|
8223
|
+
* stays intact because the block is still a complete state replacing its
|
|
8224
|
+
* predecessor, keyed on the rendered text's revision digest.
|
|
8225
|
+
*/
|
|
8226
|
+
memorySnapshotMessage() {
|
|
8227
|
+
const wake = this.memoryWake();
|
|
8228
|
+
if (wake === void 0) return void 0;
|
|
8229
|
+
const text = memoryPromptText(wake.text);
|
|
8230
|
+
if (text.trim() === "" || text === this.injectedMemoryText) return void 0;
|
|
8231
|
+
this.injectedMemoryText = text;
|
|
8232
|
+
return createPluginMessage(text, "recall", "Runtime memory snapshot");
|
|
8233
|
+
}
|
|
8047
8234
|
async preStep(payload, next) {
|
|
8048
8235
|
if (payload.step === 1) this.cancelIdleReview(true);
|
|
8049
8236
|
const decision = await next();
|
|
@@ -8059,14 +8246,22 @@ var MnemonAgentLifecycle = class {
|
|
|
8059
8246
|
return source.kind === "plugin" && source.plugin === "dsh-mnemon";
|
|
8060
8247
|
})) return decision;
|
|
8061
8248
|
if (decision.messages.length === 0) return decision;
|
|
8249
|
+
const snapshot = this.memorySnapshotMessage();
|
|
8250
|
+
const withSnapshot = (messages) => snapshot === void 0 ? messages : [...messages, snapshot];
|
|
8062
8251
|
if (this.primePending) {
|
|
8063
8252
|
this.primePending = false;
|
|
8064
8253
|
this.counters.primes += 1;
|
|
8065
8254
|
this.mark("prime");
|
|
8066
8255
|
}
|
|
8067
|
-
if (this.cueAlreadyVisible()) return
|
|
8256
|
+
if (this.cueAlreadyVisible()) return {
|
|
8257
|
+
kind: "enter",
|
|
8258
|
+
messages: withSnapshot(decision.messages)
|
|
8259
|
+
};
|
|
8068
8260
|
const reminder = guidedReminder(this.config);
|
|
8069
|
-
if (reminder === void 0) return
|
|
8261
|
+
if (reminder === void 0) return {
|
|
8262
|
+
kind: "enter",
|
|
8263
|
+
messages: withSnapshot(decision.messages)
|
|
8264
|
+
};
|
|
8070
8265
|
this.cueInjected = true;
|
|
8071
8266
|
this.guidedTurns.add(payload.turn);
|
|
8072
8267
|
if (this.config.recallMode === "guided") this.counters.recallCues += 1;
|
|
@@ -8074,63 +8269,21 @@ var MnemonAgentLifecycle = class {
|
|
|
8074
8269
|
this.mark(this.config.recallMode === "guided" ? "recall" : "writeback");
|
|
8075
8270
|
return {
|
|
8076
8271
|
kind: "enter",
|
|
8077
|
-
messages: [...decision.messages, createPluginMessage(reminder, "instructions", "Optional memory recall and remember reminder")]
|
|
8272
|
+
messages: withSnapshot([...decision.messages, createPluginMessage(reminder, "instructions", "Optional memory recall and remember reminder")])
|
|
8078
8273
|
};
|
|
8079
8274
|
}
|
|
8080
8275
|
async assemblePrompt(assembly, context, next) {
|
|
8081
8276
|
if (context.agent !== void 0 && context.agent.id !== this.agent.id) return next();
|
|
8082
8277
|
const turn = this.openTurn();
|
|
8083
8278
|
if (turn === void 0 || context.signal?.aborted === true) return next();
|
|
8084
|
-
await this.
|
|
8279
|
+
await this.memoryTurn?.begin(turn, context.signal);
|
|
8085
8280
|
return applyAgentMemoryViewWake(await next(), this.memoryWake());
|
|
8086
8281
|
}
|
|
8087
8282
|
openTurn() {
|
|
8088
|
-
|
|
8089
|
-
for (const event of this.agent.session.events) {
|
|
8090
|
-
const turn = eventTurn(event);
|
|
8091
|
-
if (event.type === "turn/start" && turn !== void 0) open = turn;
|
|
8092
|
-
else if (event.type === "turn/end" && turn === open) open = void 0;
|
|
8093
|
-
}
|
|
8094
|
-
return open;
|
|
8095
|
-
}
|
|
8096
|
-
async pinView(turn) {
|
|
8097
|
-
if (this.pinnedView?.turn === turn) return;
|
|
8098
|
-
this.releaseView();
|
|
8099
|
-
const graph = this.runtimeSource?.forAgent(this.agent);
|
|
8100
|
-
const manager = graph?.memoryViews;
|
|
8101
|
-
if (manager === void 0 || graph === void 0 || this.runtimeSource === void 0) return;
|
|
8102
|
-
const cwd = this.agent.session.header?.cwd?.trim();
|
|
8103
|
-
const scope = {
|
|
8104
|
-
storage: this.config.storageScope,
|
|
8105
|
-
...cwd === void 0 || cwd === "" ? {} : { workspaceId: resolve(cwd) },
|
|
8106
|
-
sessionId: this.agent.id,
|
|
8107
|
-
agentId: this.agent.id
|
|
8108
|
-
};
|
|
8109
|
-
const context = await manager.beginTurn(`${this.agent.id}:${turn}`, scope);
|
|
8110
|
-
let releaseRuntime;
|
|
8111
|
-
try {
|
|
8112
|
-
releaseRuntime = this.runtimeSource.bindAgentRuntime(this.agent.id, graph);
|
|
8113
|
-
this.pinnedView = {
|
|
8114
|
-
turn,
|
|
8115
|
-
manager,
|
|
8116
|
-
context,
|
|
8117
|
-
releaseRuntime
|
|
8118
|
-
};
|
|
8119
|
-
} catch (error) {
|
|
8120
|
-
manager.endTurn(context.turnId);
|
|
8121
|
-
releaseRuntime?.();
|
|
8122
|
-
throw error;
|
|
8123
|
-
}
|
|
8283
|
+
return openAgentTurn(this.agent);
|
|
8124
8284
|
}
|
|
8125
8285
|
releaseView(turn) {
|
|
8126
|
-
|
|
8127
|
-
if (pinned === void 0 || turn !== void 0 && pinned.turn !== turn) return;
|
|
8128
|
-
this.pinnedView = void 0;
|
|
8129
|
-
try {
|
|
8130
|
-
pinned.manager.endTurn(pinned.context.turnId);
|
|
8131
|
-
} finally {
|
|
8132
|
-
pinned.releaseRuntime();
|
|
8133
|
-
}
|
|
8286
|
+
this.memoryTurn?.end(turn);
|
|
8134
8287
|
}
|
|
8135
8288
|
async finishTurn(payload) {
|
|
8136
8289
|
this.scheduleIdleReview(payload.turn);
|
|
@@ -8138,7 +8291,8 @@ var MnemonAgentLifecycle = class {
|
|
|
8138
8291
|
sessionEvent(session, event) {
|
|
8139
8292
|
if (session !== this.agent.session || event.type !== "turn/end") return;
|
|
8140
8293
|
const turn = eventTurn(event);
|
|
8141
|
-
const
|
|
8294
|
+
const current = this.memoryTurn?.current;
|
|
8295
|
+
const pinned = turn === void 0 || current?.turn !== turn ? void 0 : current;
|
|
8142
8296
|
if (pinned === void 0) return;
|
|
8143
8297
|
this.releaseView(turn);
|
|
8144
8298
|
pinned.manager.reconcile(pinned.context.scope).catch((error) => this.fail(error));
|
|
@@ -8267,6 +8421,8 @@ var MnemonLifecycle = class {
|
|
|
8267
8421
|
config;
|
|
8268
8422
|
runtimeSource;
|
|
8269
8423
|
owners = /* @__PURE__ */ new Map();
|
|
8424
|
+
children = /* @__PURE__ */ new Map();
|
|
8425
|
+
memoryTurns = /* @__PURE__ */ new Map();
|
|
8270
8426
|
counters = {
|
|
8271
8427
|
primes: 0,
|
|
8272
8428
|
recallCues: 0,
|
|
@@ -8291,8 +8447,11 @@ var MnemonLifecycle = class {
|
|
|
8291
8447
|
for (const agent of this.ctx.agents.roots()) this.install(agent, "adopted");
|
|
8292
8448
|
return () => {
|
|
8293
8449
|
stopCreated();
|
|
8450
|
+
for (const dispose of [...this.children.values()].reverse()) dispose();
|
|
8294
8451
|
for (const owner of [...this.owners.values()].reverse()) owner.dispose();
|
|
8452
|
+
this.children.clear();
|
|
8295
8453
|
this.owners.clear();
|
|
8454
|
+
this.memoryTurns.clear();
|
|
8296
8455
|
};
|
|
8297
8456
|
}
|
|
8298
8457
|
snapshot(sessionId, workspaceRoot) {
|
|
@@ -8634,22 +8793,93 @@ var MnemonLifecycle = class {
|
|
|
8634
8793
|
return this.taskAgentModelRoute(fallbackSessionId, workspaceRoot)?.options;
|
|
8635
8794
|
}
|
|
8636
8795
|
install(agent, source) {
|
|
8637
|
-
if (this.taskAgentIds.has(agent.id) || this.owners.has(agent) ||
|
|
8638
|
-
|
|
8796
|
+
if (this.taskAgentIds.has(agent.id) || this.owners.has(agent) || this.children.has(agent)) return;
|
|
8797
|
+
if (agent.session.header?.origin === "subagent") {
|
|
8798
|
+
this.installChild(agent);
|
|
8799
|
+
return;
|
|
8800
|
+
}
|
|
8801
|
+
if (!this.ctx.agents.roots().includes(agent)) return;
|
|
8802
|
+
const memoryTurn = this.runtimeSource === void 0 ? void 0 : new AgentMemoryTurn(agent, this.runtimeSource);
|
|
8803
|
+
const lifecycle = new MnemonAgentLifecycle(agent, this.coordinator, this.config, this.counters, source, memoryTurn);
|
|
8639
8804
|
let dispose;
|
|
8640
8805
|
dispose = agent.ctx.effect(() => {
|
|
8641
8806
|
const stop = lifecycle.start();
|
|
8642
8807
|
const stopRuntimeContext = this.runtimeSource === void 0 ? () => {} : registerAgentMemoryViewContext(agent, () => lifecycle.memoryWake());
|
|
8643
8808
|
return () => {
|
|
8644
|
-
|
|
8645
|
-
|
|
8646
|
-
|
|
8809
|
+
try {
|
|
8810
|
+
stopRuntimeContext();
|
|
8811
|
+
stop();
|
|
8812
|
+
} finally {
|
|
8813
|
+
memoryTurn?.dispose();
|
|
8814
|
+
if (this.owners.get(agent)?.dispose === dispose) this.owners.delete(agent);
|
|
8815
|
+
if (this.memoryTurns.get(agent) === memoryTurn) this.memoryTurns.delete(agent);
|
|
8816
|
+
}
|
|
8647
8817
|
};
|
|
8648
8818
|
}, "dsh-mnemon.lifecycle()");
|
|
8649
8819
|
this.owners.set(agent, {
|
|
8650
8820
|
lifecycle,
|
|
8651
8821
|
dispose
|
|
8652
8822
|
});
|
|
8823
|
+
if (memoryTurn !== void 0) this.memoryTurns.set(agent, memoryTurn);
|
|
8824
|
+
}
|
|
8825
|
+
/** Child memory ownership is independent of root-only reminders and idle review. */
|
|
8826
|
+
installChild(agent) {
|
|
8827
|
+
const runtime = this.runtimeSource;
|
|
8828
|
+
const parentId = agent.session.header?.parentSession?.trim();
|
|
8829
|
+
const parent = parentId === void 0 || parentId === "" ? void 0 : this.ctx.agents.get(parentId);
|
|
8830
|
+
if (runtime === void 0 || parent === void 0 || parent === agent) return;
|
|
8831
|
+
const parentMemory = this.memoryTurns.get(parent);
|
|
8832
|
+
let delegation;
|
|
8833
|
+
if (parentMemory !== void 0) delegation = parentMemory.delegate();
|
|
8834
|
+
else {
|
|
8835
|
+
const graph = runtime.forAgent(parent);
|
|
8836
|
+
const parentPin = graph.memoryViews.activeTurn(parent.id);
|
|
8837
|
+
delegation = {
|
|
8838
|
+
graph,
|
|
8839
|
+
scope: parentPin?.scope ?? agentMemoryScope(parent, graph),
|
|
8840
|
+
...parentPin === void 0 ? {} : { viewId: parentPin.viewId }
|
|
8841
|
+
};
|
|
8842
|
+
}
|
|
8843
|
+
let dispose;
|
|
8844
|
+
dispose = agent.ctx.effect(() => {
|
|
8845
|
+
const memory = new AgentMemoryTurn(agent, runtime, delegation);
|
|
8846
|
+
this.memoryTurns.set(agent, memory);
|
|
8847
|
+
const stops = [];
|
|
8848
|
+
const cleanup = () => {
|
|
8849
|
+
try {
|
|
8850
|
+
for (const stop of stops.reverse()) stop();
|
|
8851
|
+
} finally {
|
|
8852
|
+
try {
|
|
8853
|
+
memory.dispose();
|
|
8854
|
+
} finally {
|
|
8855
|
+
if (this.memoryTurns.get(agent) === memory) this.memoryTurns.delete(agent);
|
|
8856
|
+
if (this.children.get(agent) === dispose) this.children.delete(agent);
|
|
8857
|
+
}
|
|
8858
|
+
}
|
|
8859
|
+
};
|
|
8860
|
+
try {
|
|
8861
|
+
stops.push(agent.ctx.on("agent/session-start", (() => memory.end())));
|
|
8862
|
+
stops.push(agent.ctx.on("system-prompt/assemble", (async (_assembly, context, next) => {
|
|
8863
|
+
if (context.agent !== void 0 && context.agent !== agent) return next();
|
|
8864
|
+
const turn = openAgentTurn(agent);
|
|
8865
|
+
if (turn !== void 0) await memory.begin(turn, context.signal);
|
|
8866
|
+
return next();
|
|
8867
|
+
})));
|
|
8868
|
+
stops.push(agent.ctx.on("agent/pre-step", (async (payload, next) => {
|
|
8869
|
+
const decision = await next();
|
|
8870
|
+
if (decision.kind === "reject" || payload.signal.aborted) memory.end(payload.turn);
|
|
8871
|
+
return decision;
|
|
8872
|
+
})));
|
|
8873
|
+
stops.push(agent.ctx.on("session/event", ((session, event) => {
|
|
8874
|
+
if (session === agent.session && event.type === "turn/end") memory.end(eventTurn(event));
|
|
8875
|
+
})));
|
|
8876
|
+
} catch (error) {
|
|
8877
|
+
cleanup();
|
|
8878
|
+
throw error;
|
|
8879
|
+
}
|
|
8880
|
+
return cleanup;
|
|
8881
|
+
}, "dsh-mnemon.child-memory()");
|
|
8882
|
+
this.children.set(agent, dispose);
|
|
8653
8883
|
}
|
|
8654
8884
|
};
|
|
8655
8885
|
//#endregion
|
|
@@ -9662,7 +9892,6 @@ const MUTABLE_FIELDS = [
|
|
|
9662
9892
|
"recallMode",
|
|
9663
9893
|
"writebackMode",
|
|
9664
9894
|
"idleReviewMs",
|
|
9665
|
-
"displayMode",
|
|
9666
9895
|
"tabEnabled",
|
|
9667
9896
|
"writeEnabled",
|
|
9668
9897
|
"persistenceStrategy",
|
|
@@ -9850,7 +10079,7 @@ function requireAgent(exec) {
|
|
|
9850
10079
|
function isAgentRuntimeSource(value) {
|
|
9851
10080
|
return "forAgent" in value && typeof value.forAgent === "function";
|
|
9852
10081
|
}
|
|
9853
|
-
/**
|
|
10082
|
+
/** Model tools use the executing Agent's pinned runtime and deterministic service. */
|
|
9854
10083
|
function registerTools(ctx, serviceOrSource, coordinator, runtimeMemory, documents) {
|
|
9855
10084
|
const runtimeFor = (exec) => {
|
|
9856
10085
|
if (isAgentRuntimeSource(serviceOrSource)) return serviceOrSource.forAgent(requireAgent(exec));
|
|
@@ -10029,7 +10258,7 @@ function registerTools(ctx, serviceOrSource, coordinator, runtimeMemory, documen
|
|
|
10029
10258
|
}));
|
|
10030
10259
|
ctx.tools.register(definition({
|
|
10031
10260
|
name: "mnemon_document_search",
|
|
10032
|
-
description: "Run one focused search over project-scoped managed Documents before durable Recall. The Host admits only one Documents query
|
|
10261
|
+
description: "Run one focused search over project-scoped managed Documents before durable Recall. The Host admits only one Documents query per executing Agent turn; parallel calls share that slot, while child turns have independent budgets. Results contain bounded query-local evidence, not complete records. Cold archives are excluded unless a known archive reference requires them.",
|
|
10033
10262
|
parameters: {
|
|
10034
10263
|
type: "object",
|
|
10035
10264
|
properties: {
|
|
@@ -10060,7 +10289,7 @@ function registerTools(ctx, serviceOrSource, coordinator, runtimeMemory, documen
|
|
|
10060
10289
|
includeArchived: args.includeArchived === true,
|
|
10061
10290
|
notRun: true,
|
|
10062
10291
|
results: [],
|
|
10063
|
-
hint: "
|
|
10292
|
+
hint: "This Agent turn already used its Documents search slot, so no second disk query ran. Use the admitted evidence, make one focused mnemon_recall only if exact durable history is still missing, or answer with appropriate uncertainty."
|
|
10064
10293
|
};
|
|
10065
10294
|
const result = await controller.search(args.query, {
|
|
10066
10295
|
...args.includeArchived === void 0 ? {} : { includeArchived: args.includeArchived },
|