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/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 rendered = wake === void 0 ? "" : memoryPromptText(wake.text);
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 prompt = scopedSystemPrompt(agent);
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
- const stopContext = prompt?.context?.({
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
- for (const directory of (envValue(env, "PATH", platform) ?? "").split(paths.delimiter)) {
2831
- if (directory === "") continue;
2832
- for (const name of platform === "win32" ? ["mnemon.exe"] : ["mnemon"]) {
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(["MNEMON_EMBED_ENDPOINT", "MNEMON_EMBED_MODEL"]);
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 found = findMnemonCommand(config);
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(command, argv, processOptions);
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
- commandFound: found !== void 0 && executable$1(found),
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(query) {
6416
- return sha256((query.match(/[\p{L}\p{N}]+/gu) ?? []).join(" ").toLocaleLowerCase());
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 Map();
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 root turn. */
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.turnId);
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.query);
6909
- const retrieval = authority === void 0 ? void 0 : this.turnRetrievalState(authority.turnId);
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: structuredClone(previous?.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: structuredClone(previous?.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
- const result = await this.serviceFor(parent).search(scoped, signal);
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 root turn. */
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.turnId);
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: structuredClone(previous?.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 this.serviceFor(parent).related(id, options.depth, options.edge, signal, selected), {
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 || !isAgentRuntimeSource$1(this.runtimeMemoryOrSource)) return void 0;
7634
- const value = optionalObject(this.runtimeMemoryOrSource.forAgent(agent).memoryViews.sourceState(authority.viewId, "memory-spaces"));
7635
- 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: ${authority.viewId}`);
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: ${authority.viewId}`);
7666
+ if (memoryBodyIds.length === 0) throw new Error(`pinned MemorySource has no recall-authorized Memory Spaces: ${context.viewId}`);
7638
7667
  return {
7639
- ...authority,
7640
- memoryBodyIds
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 views = this.runtimeMemoryOrSource.forAgent(agent).memoryViews;
7646
- const parentId = isSubagent(agent) ? agent.session.header?.parentSession?.trim() : void 0;
7647
- const ownerId = parentId === void 0 || parentId === "" ? agent.id : parentId;
7648
- const pinned = views.activeTurn(ownerId);
7649
- if (pinned === void 0) {
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(turnId) {
7659
- const current = this.retrievalTurns.get(turnId);
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(turnId, created);
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
- runtimeSource;
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
- pinnedView;
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.runtimeSource = runtimeSource;
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.pinnedView;
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 decision;
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 decision;
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.pinView(turn);
8279
+ await this.memoryTurn?.begin(turn, context.signal);
8085
8280
  return applyAgentMemoryViewWake(await next(), this.memoryWake());
8086
8281
  }
8087
8282
  openTurn() {
8088
- let open;
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
- const pinned = this.pinnedView;
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 pinned = turn === void 0 || this.pinnedView?.turn !== turn ? void 0 : this.pinnedView;
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) || !this.ctx.agents.roots().includes(agent)) return;
8638
- const lifecycle = new MnemonAgentLifecycle(agent, this.coordinator, this.config, this.counters, source, this.runtimeSource);
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
- stopRuntimeContext();
8645
- stop();
8646
- if (this.owners.get(agent)?.dispose === dispose) this.owners.delete(agent);
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
- /** Root calls delegate to a bounded child; memory-worker calls reach the deterministic service. */
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 for the root turn, shared with child and parallel calls. Results contain bounded query-local evidence, not complete records. Cold archives are excluded unless a known archive reference requires them.",
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: "The root 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."
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 },