dsh-mnemon 0.5.43 → 0.5.44
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/bin/repair-legacy-session.mjs +18 -2
- package/lib/bundle.js +1 -1
- package/lib/client.js +448 -84
- package/lib/index.js +270 -76
- package/lib/{starter-resolution-CTY14Exj.js → starter-resolution-LTLQsJPW.js} +2 -2
- package/lib/starter.js +1 -1
- package/lib/types/src/client/locales.d.ts +15 -0
- package/lib/types/src/host/protocol.d.ts +6 -0
- package/locale/detail.en.md +7 -0
- package/locale/detail.zh.md +7 -0
- package/locale/en.json +3 -1
- package/locale/zh.json +2 -1
- package/package.json +3 -3
package/lib/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Context } from "@deepseek-ai/cordis";
|
|
|
6
6
|
import z from "@deepseek-ai/schemastery";
|
|
7
7
|
import { basename, delimiter, dirname, isAbsolute, join, normalize, relative, resolve, sep } from "node:path";
|
|
8
8
|
import { resolveEmbedding, resolvePersistenceStrategy, resolveRecallQuality } from "dsh-mnemon-source-memory-spaces";
|
|
9
|
-
import { CATEGORIES, DEFAULT_EMBEDDING_ENDPOINT, DEFAULT_EMBEDDING_MODEL, DEFAULT_EMBEDDING_PROTOCOL, EDGE_TYPES, MEMORY_PLACEMENT_CAPABILITIES, MEMORY_PROVIDER_REGISTRY_FILE, MEMORY_SPACES_DIRECTORY, MEMORY_SPACE_DATABASE_FILE, MEMORY_SPACE_ID_PATTERN, MEMORY_SPACE_NAME_MAX_LENGTH, MEMORY_SPACE_REGISTRY_FILE, MNEMON_ACTIVE_STORE_FILE, MNEMON_EMBEDDING_PROTOCOLS, SOURCES, parseMemorySpaceRegistry, summarizeMemoryProviderRegistry, summarizeMemorySpaceRegistry } from "dsh-mnemon-source-memory-spaces/contracts";
|
|
9
|
+
import { CATEGORIES, DEFAULT_EMBEDDING_ENDPOINT, DEFAULT_EMBEDDING_MODEL, DEFAULT_EMBEDDING_PROTOCOL, EDGE_TYPES, EMBEDDING_CREDENTIAL_PREFIX, MEMORY_PLACEMENT_CAPABILITIES, MEMORY_PROVIDER_REGISTRY_FILE, MEMORY_SPACES_DIRECTORY, MEMORY_SPACE_DATABASE_FILE, MEMORY_SPACE_ID_PATTERN, MEMORY_SPACE_NAME_MAX_LENGTH, MEMORY_SPACE_REGISTRY_FILE, MNEMON_ACTIVE_STORE_FILE, MNEMON_EMBEDDING_PROTOCOLS, SOURCES, parseMemorySpaceRegistry, summarizeMemoryProviderRegistry, summarizeMemorySpaceRegistry } from "dsh-mnemon-source-memory-spaces/contracts";
|
|
10
10
|
import { RUNTIME_ARCHIVE_DIRECTORY, RUNTIME_DIRECTORY, RUNTIME_ENTRY_DELIMITER, RUNTIME_ENTRY_MAX_BYTES, RUNTIME_LOCK_FILE, RUNTIME_LOCK_STALE_MS, RUNTIME_MEMORIES_FILE, RUNTIME_MEMORY_LIMITS, RUNTIME_MEMORY_LIMIT_MAX_BYTES, RUNTIME_MEMORY_VERSION, RUNTIME_PROJECTION_FILES, assertRuntimePinnedBudget, parseRuntimeBranches, runtimeBytes, runtimeProjection, summarizeRuntimeMemories } from "dsh-mnemon-source-runtime/contracts";
|
|
11
11
|
import { createHash, randomUUID } from "node:crypto";
|
|
12
12
|
import fs, { accessSync, chmodSync, closeSync, constants, copyFileSync, existsSync, fstatSync, lstatSync, mkdirSync, openSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
@@ -392,6 +392,8 @@ const DEFAULT_SKILLS_CONFIG = Object.freeze({
|
|
|
392
392
|
targetScope: "user",
|
|
393
393
|
autoBacktest: true,
|
|
394
394
|
autoAdopt: false,
|
|
395
|
+
autoAdoptDailyLimit: 2,
|
|
396
|
+
autoAdoptTimeZone: "local",
|
|
395
397
|
draftMaxTokens: 32768,
|
|
396
398
|
draftRetryMaxTokens: 65536,
|
|
397
399
|
hints: true,
|
|
@@ -487,6 +489,17 @@ const SkillsConfig = z.object({
|
|
|
487
489
|
]).default(DEFAULT_SKILLS_CONFIG.targetScope),
|
|
488
490
|
autoBacktest: z.boolean().default(DEFAULT_SKILLS_CONFIG.autoBacktest),
|
|
489
491
|
autoAdopt: z.boolean().default(DEFAULT_SKILLS_CONFIG.autoAdopt),
|
|
492
|
+
autoAdoptDailyLimit: z.number().step(1).min(0).max(100).default(DEFAULT_SKILLS_CONFIG.autoAdoptDailyLimit),
|
|
493
|
+
autoAdoptTimeZone: z.transform(z.string(), (value) => {
|
|
494
|
+
if (value === "local") return value;
|
|
495
|
+
if (!value || value.length > 100) throw new Error("skills.autoAdoptTimeZone must be an IANA time zone or local");
|
|
496
|
+
try {
|
|
497
|
+
new Intl.DateTimeFormat("en", { timeZone: value }).format(0);
|
|
498
|
+
} catch {
|
|
499
|
+
throw new Error("skills.autoAdoptTimeZone must be an IANA time zone or local");
|
|
500
|
+
}
|
|
501
|
+
return value;
|
|
502
|
+
}).default(DEFAULT_SKILLS_CONFIG.autoAdoptTimeZone),
|
|
490
503
|
draftMaxTokens: z.number().step(1).min(128).max(131072).default(DEFAULT_SKILLS_CONFIG.draftMaxTokens),
|
|
491
504
|
draftRetryMaxTokens: z.number().step(1).min(128).max(131072).default(DEFAULT_SKILLS_CONFIG.draftRetryMaxTokens),
|
|
492
505
|
hints: z.boolean().default(DEFAULT_SKILLS_CONFIG.hints),
|
|
@@ -530,7 +543,9 @@ const MnemonEmbeddingSchema = z.object({
|
|
|
530
543
|
enabled: z.boolean().default(false),
|
|
531
544
|
endpoint: z.string().default(DEFAULT_EMBEDDING_ENDPOINT),
|
|
532
545
|
model: z.string().default(DEFAULT_EMBEDDING_MODEL),
|
|
533
|
-
apiKey: z.string().default(""),
|
|
546
|
+
apiKey: z.string().role("secret").default(""),
|
|
547
|
+
apiKeyEnv: z.string(),
|
|
548
|
+
apiKeyRef: z.string(),
|
|
534
549
|
protocol: z.union(MNEMON_EMBEDDING_PROTOCOLS).default(DEFAULT_EMBEDDING_PROTOCOL)
|
|
535
550
|
});
|
|
536
551
|
const RecallQualitySchema = z.object({
|
|
@@ -3580,6 +3595,44 @@ var MnemonReviewLedger = class {
|
|
|
3580
3595
|
}
|
|
3581
3596
|
};
|
|
3582
3597
|
//#endregion
|
|
3598
|
+
//#region src/host/disposable-directory.ts
|
|
3599
|
+
function makeWritable(path) {
|
|
3600
|
+
let entry;
|
|
3601
|
+
try {
|
|
3602
|
+
entry = lstatSync(path);
|
|
3603
|
+
} catch (error) {
|
|
3604
|
+
if (error.code === "ENOENT") return;
|
|
3605
|
+
throw error;
|
|
3606
|
+
}
|
|
3607
|
+
if (entry.isSymbolicLink()) return;
|
|
3608
|
+
if ((entry.mode & 128) === 0) chmodSync(path, entry.mode | 128);
|
|
3609
|
+
if (entry.isDirectory()) for (const name of readdirSync(path)) makeWritable(join(path, name));
|
|
3610
|
+
}
|
|
3611
|
+
/** Remove only a caller-owned disposable tree, including read-only Git packs on Windows. */
|
|
3612
|
+
function removeDisposableDirectory(path) {
|
|
3613
|
+
try {
|
|
3614
|
+
rmSync(path, {
|
|
3615
|
+
recursive: true,
|
|
3616
|
+
force: true
|
|
3617
|
+
});
|
|
3618
|
+
} catch (error) {
|
|
3619
|
+
const code = error.code;
|
|
3620
|
+
if (process.platform !== "win32" || ![
|
|
3621
|
+
"EPERM",
|
|
3622
|
+
"EACCES",
|
|
3623
|
+
"ENOTEMPTY",
|
|
3624
|
+
"EBUSY"
|
|
3625
|
+
].includes(code ?? "")) throw error;
|
|
3626
|
+
makeWritable(path);
|
|
3627
|
+
rmSync(path, {
|
|
3628
|
+
recursive: true,
|
|
3629
|
+
force: true,
|
|
3630
|
+
maxRetries: 3,
|
|
3631
|
+
retryDelay: 100
|
|
3632
|
+
});
|
|
3633
|
+
}
|
|
3634
|
+
}
|
|
3635
|
+
//#endregion
|
|
3583
3636
|
//#region src/host/github-transport.ts
|
|
3584
3637
|
/**
|
|
3585
3638
|
* How GitHub sign-in reaches GitHub.
|
|
@@ -4618,10 +4671,7 @@ var MnemonSyncSettingsStore = class {
|
|
|
4618
4671
|
};
|
|
4619
4672
|
}
|
|
4620
4673
|
clearMirror() {
|
|
4621
|
-
|
|
4622
|
-
recursive: true,
|
|
4623
|
-
force: true
|
|
4624
|
-
});
|
|
4674
|
+
removeDisposableDirectory(this.mirror());
|
|
4625
4675
|
}
|
|
4626
4676
|
};
|
|
4627
4677
|
//#endregion
|
|
@@ -6003,16 +6053,10 @@ var MnemonGitSync = class {
|
|
|
6003
6053
|
cwd: mirror,
|
|
6004
6054
|
signal
|
|
6005
6055
|
});
|
|
6006
|
-
if (origin.exitCode !== 0 || origin.stdout.trim() !== settings.repoUrl)
|
|
6007
|
-
recursive: true,
|
|
6008
|
-
force: true
|
|
6009
|
-
});
|
|
6056
|
+
if (origin.exitCode !== 0 || origin.stdout.trim() !== settings.repoUrl) removeDisposableDirectory(mirror);
|
|
6010
6057
|
}
|
|
6011
6058
|
if (!existsSync(join(mirror, ".git"))) {
|
|
6012
|
-
|
|
6013
|
-
recursive: true,
|
|
6014
|
-
force: true
|
|
6015
|
-
});
|
|
6059
|
+
removeDisposableDirectory(mirror);
|
|
6016
6060
|
const initialized = await this.git([
|
|
6017
6061
|
"init",
|
|
6018
6062
|
"--quiet",
|
|
@@ -6139,10 +6183,7 @@ var MnemonGitSync = class {
|
|
|
6139
6183
|
const root = this.payloadRoot(subdir);
|
|
6140
6184
|
const mirror = resolve(this.store.mirror());
|
|
6141
6185
|
if (root === mirror || !root.startsWith(mirror + (process.platform === "win32" ? "\\" : "/"))) throw new Error("sync directory escapes the mirror");
|
|
6142
|
-
|
|
6143
|
-
recursive: true,
|
|
6144
|
-
force: true
|
|
6145
|
-
});
|
|
6186
|
+
removeDisposableDirectory(root);
|
|
6146
6187
|
for (const [path, bytes] of Object.entries(entries)) {
|
|
6147
6188
|
const file = resolve(root, path);
|
|
6148
6189
|
mkdirSync(join(file, ".."), {
|
|
@@ -9476,7 +9517,7 @@ const WRITE_TOOL_FALLBACK_ACTION = {
|
|
|
9476
9517
|
};
|
|
9477
9518
|
function reviewReceipt(receipt) {
|
|
9478
9519
|
if (!mutationResultCommitted(receipt.value)) return void 0;
|
|
9479
|
-
const value = object$
|
|
9520
|
+
const value = object$7(receipt.value);
|
|
9480
9521
|
const args = optionalObject(receipt.arguments);
|
|
9481
9522
|
const document = optionalObject(value.document);
|
|
9482
9523
|
return {
|
|
@@ -9487,7 +9528,7 @@ function reviewReceipt(receipt) {
|
|
|
9487
9528
|
...typeof value.revision === "string" ? { revision: value.revision } : {}
|
|
9488
9529
|
};
|
|
9489
9530
|
}
|
|
9490
|
-
function object$
|
|
9531
|
+
function object$7(value) {
|
|
9491
9532
|
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error("memory subagent returned an invalid structured result");
|
|
9492
9533
|
return value;
|
|
9493
9534
|
}
|
|
@@ -9727,7 +9768,7 @@ async function runtimeArchiveSource(runtimeSource, graph, scope, view, generatio
|
|
|
9727
9768
|
return {
|
|
9728
9769
|
source,
|
|
9729
9770
|
cleanup,
|
|
9730
|
-
memoryBodyIds: new Set(strings(object$
|
|
9771
|
+
memoryBodyIds: new Set(strings(object$7(grant.value).memoryBodyIds)),
|
|
9731
9772
|
writeScope: {
|
|
9732
9773
|
viewId: view.id,
|
|
9733
9774
|
grant
|
|
@@ -9852,13 +9893,13 @@ ${chunk.context}
|
|
|
9852
9893
|
provider = delegated.provider;
|
|
9853
9894
|
runId = delegated.runId;
|
|
9854
9895
|
}
|
|
9855
|
-
const value = object$
|
|
9896
|
+
const value = object$7(delegated.result.structured);
|
|
9856
9897
|
if (value.action !== "planned") throw new Error(typeof value.summary === "string" && value.summary !== "" ? value.summary : "runtime memory archival routing failed");
|
|
9857
9898
|
if (!Array.isArray(value.routes) || value.routes.length === 0) throw new Error("runtime memory migration returned no routes");
|
|
9858
9899
|
const allowedIndexes = new Set(chunk.indexes);
|
|
9859
9900
|
const proposed = /* @__PURE__ */ new Map();
|
|
9860
9901
|
for (const candidate of value.routes) {
|
|
9861
|
-
const route = object$
|
|
9902
|
+
const route = object$7(candidate);
|
|
9862
9903
|
const memoryBodyId = typeof route.memoryBodyId === "string" ? route.memoryBodyId.trim() : "";
|
|
9863
9904
|
if (memoryBodyId === "" || !eligibleById.has(memoryBodyId)) throw new Error(`runtime memory migration selected an invalid Memory Space: ${memoryBodyId || "(empty)"}`);
|
|
9864
9905
|
if (!Array.isArray(route.sourceIndexes) || route.sourceIndexes.length === 0) throw new Error("runtime memory migration route must contain source indexes");
|
|
@@ -10013,10 +10054,10 @@ ${pendingMutationContext(plan)}
|
|
|
10013
10054
|
|
|
10014
10055
|
${runtimeSnapshotContext("user", mutable)}`;
|
|
10015
10056
|
const { provider, runId, result } = await context.model("compaction", "Consolidate local user profile", prompt, USER_COMPACTION_SCHEMA, USER_COMPACTION_PERSONA);
|
|
10016
|
-
const value = object$
|
|
10057
|
+
const value = object$7(result.structured);
|
|
10017
10058
|
if (value.action !== "compacted") throw new Error(typeof value.summary === "string" && value.summary !== "" ? value.summary : "USER.md compaction failed");
|
|
10018
10059
|
const compactedEntries = Array.isArray(value.compactedEntries) ? value.compactedEntries.map((entry) => {
|
|
10019
|
-
const item = object$
|
|
10060
|
+
const item = object$7(entry);
|
|
10020
10061
|
if (typeof item.content !== "string" || ![
|
|
10021
10062
|
"critical",
|
|
10022
10063
|
"normal",
|
|
@@ -10194,7 +10235,7 @@ async function archiveDocumentLocked(host, parent, id, signal) {
|
|
|
10194
10235
|
const cleanup = graph.source("memory-spaces", agentScope(parent, graph.config)).forInstance(identity.sourceInstanceKey).forGeneration(lease.generation);
|
|
10195
10236
|
const grant = authority?.context.view.readGrants.find((grant) => grant.sourceInstanceKey === identity.sourceInstanceKey && grant.schema === "dsh-mnemon.memory-spaces/v1");
|
|
10196
10237
|
if (authority !== void 0 && grant === void 0) throw new Error("document archive requires a Memory Space namespace grant");
|
|
10197
|
-
const allowed = grant === void 0 ? void 0 : new Set(strings(object$
|
|
10238
|
+
const allowed = grant === void 0 ? void 0 : new Set(strings(object$7(grant.value).memoryBodyIds));
|
|
10198
10239
|
const directory = await memoryService.read("body-directory", null, signal);
|
|
10199
10240
|
const indexable = (body) => archivableSpace(directory, body);
|
|
10200
10241
|
const eligible = (body) => indexable(body) && (allowed === void 0 || allowed.has(body.id));
|
|
@@ -10204,7 +10245,7 @@ async function archiveDocumentLocked(host, parent, id, signal) {
|
|
|
10204
10245
|
throw new Error("document archive requires an existing active Memory Space with exact writes and safe forget");
|
|
10205
10246
|
}
|
|
10206
10247
|
const { provider, runId, result } = await host.delegate(parent, "document-archive", "Plan managed document archive", documentArchivePrompt(document, source, bodies), [], DOCUMENT_ARCHIVE_SCHEMA, signal, "spawn", DOCUMENT_ARCHIVE_PERSONA);
|
|
10207
|
-
const value = object$
|
|
10248
|
+
const value = object$7(result.structured);
|
|
10208
10249
|
const summary = typeof value.summary === "string" ? value.summary.trim() : "";
|
|
10209
10250
|
if (value.action !== "planned") throw new Error(summary || "document archive planning failed");
|
|
10210
10251
|
if (summary === "" || summary.length > 1e3) throw new Error("document archive summary must contain 1–1000 characters");
|
|
@@ -10507,6 +10548,23 @@ function openAgentTurn(agent) {
|
|
|
10507
10548
|
}
|
|
10508
10549
|
return open;
|
|
10509
10550
|
}
|
|
10551
|
+
/** PTC dispatch records belong to a real open step, not just an open turn. */
|
|
10552
|
+
function openAgentStep(agent) {
|
|
10553
|
+
let turn;
|
|
10554
|
+
let open;
|
|
10555
|
+
for (const event of agent.session.snapshotEvents()) if (event.type === "turn/start") {
|
|
10556
|
+
turn = typeof event.data.turn === "number" ? event.data.turn : void 0;
|
|
10557
|
+
open = void 0;
|
|
10558
|
+
} else if (event.type === "turn/end" && event.data.turn === turn) {
|
|
10559
|
+
turn = void 0;
|
|
10560
|
+
open = void 0;
|
|
10561
|
+
} else if (event.type === "step/start" && turn !== void 0 && event.data.turn === turn && typeof event.data.step === "number") open = {
|
|
10562
|
+
turn,
|
|
10563
|
+
step: event.data.step
|
|
10564
|
+
};
|
|
10565
|
+
else if (event.type === "step/end" && open?.turn === event.data.turn && open?.step === event.data.step) open = void 0;
|
|
10566
|
+
return open;
|
|
10567
|
+
}
|
|
10510
10568
|
/**
|
|
10511
10569
|
* One Agent owns each turn pin. A child additionally retains its delegation
|
|
10512
10570
|
* across parent completion, collection, and runtime swaps until it is disposed.
|
|
@@ -10677,7 +10735,7 @@ async function executeHostTool(tools, input) {
|
|
|
10677
10735
|
//#region src/host/review-admission.ts
|
|
10678
10736
|
const RESULT_TOOL = "mnemon_subagent_result";
|
|
10679
10737
|
const CHECK_TIMEOUT_MS = 5e3;
|
|
10680
|
-
/** An in-
|
|
10738
|
+
/** An in-step no-op challenge through the mandatory review completion channel.
|
|
10681
10739
|
* Inventory alone cannot see execution-time guards. No errors are classified as
|
|
10682
10740
|
* permission failures, and an unavailable checkpoint is never a permanent ban.
|
|
10683
10741
|
*/
|
|
@@ -10703,7 +10761,7 @@ var AutomaticReviewAdmission = class {
|
|
|
10703
10761
|
async check(agent, signal) {
|
|
10704
10762
|
signal.throwIfAborted();
|
|
10705
10763
|
const tools = agent.ctx.tools;
|
|
10706
|
-
if (this.disposed || tools?.execute === void 0 || this.draining.has(agent) ||
|
|
10764
|
+
if (this.disposed || tools?.execute === void 0 || this.draining.has(agent) || openAgentStep(agent) === void 0) return false;
|
|
10707
10765
|
const controller = new AbortController();
|
|
10708
10766
|
this.controllers.add(controller);
|
|
10709
10767
|
const combined = AbortSignal.any([signal, controller.signal]);
|
|
@@ -11116,7 +11174,7 @@ var MnemonSubagentCoordinator = class {
|
|
|
11116
11174
|
if (!isSubagent(execution.agent)) throw new Error("Mnemon subagent result tools are restricted to delegated children");
|
|
11117
11175
|
execution.signal.throwIfAborted();
|
|
11118
11176
|
assertDshOutputValue(RESULT_TOOL_INPUT_SCHEMA, args);
|
|
11119
|
-
const request = object$
|
|
11177
|
+
const request = object$7(args);
|
|
11120
11178
|
const submit = this.resultRequests.get(String(request.requestId));
|
|
11121
11179
|
if (this.disposed || submit === void 0) throw new Error("Mnemon subagent result request is unknown or no longer active");
|
|
11122
11180
|
return submit(request.result, execution);
|
|
@@ -11353,7 +11411,7 @@ var MnemonSubagentCoordinator = class {
|
|
|
11353
11411
|
].join("\n\n");
|
|
11354
11412
|
const schema = providerPlacementSchema(prepared.candidates.map((candidate) => candidate.id));
|
|
11355
11413
|
const { provider, runId, result } = await this.delegate(parent, "placement", "Choose Memory Space provider", prompt, [], schema, signal, "spawn", PROVIDER_PLACEMENT_PERSONA);
|
|
11356
|
-
const value = object$
|
|
11414
|
+
const value = object$7(result.structured);
|
|
11357
11415
|
return source.read("finalize-placement", {
|
|
11358
11416
|
prepared,
|
|
11359
11417
|
selection: {
|
|
@@ -11371,13 +11429,13 @@ var MnemonSubagentCoordinator = class {
|
|
|
11371
11429
|
const service = this.sourceFor(parent, "memory-spaces");
|
|
11372
11430
|
const prompt = `Generate concise metadata from these bounded Provider-native samples now:\n\n${(await Promise.all(selected.map((id) => service.read("metadata-sample", { memoryBodyId: id }, signal)))).map(metadataSampleText).join("\n\n")}`;
|
|
11373
11431
|
const { provider, runId, result } = await this.delegate(parent, "metadata-maintenance", "Maintain Memory Space metadata", prompt, [], METADATA_MAINTENANCE_SCHEMA, signal, "spawn", METADATA_MAINTENANCE_PERSONA);
|
|
11374
|
-
const value = object$
|
|
11432
|
+
const value = object$7(result.structured);
|
|
11375
11433
|
if (!Array.isArray(value.updates)) throw new Error("metadata subagent returned no updates");
|
|
11376
11434
|
const allowed = new Set(selected);
|
|
11377
11435
|
const seen = /* @__PURE__ */ new Set();
|
|
11378
11436
|
const updates = [];
|
|
11379
11437
|
for (const entry of value.updates) {
|
|
11380
|
-
const item = object$
|
|
11438
|
+
const item = object$7(entry);
|
|
11381
11439
|
const memoryBodyId = typeof item.memoryBodyId === "string" ? item.memoryBodyId.trim() : "";
|
|
11382
11440
|
const title = typeof item.title === "string" ? item.title.trim() : "";
|
|
11383
11441
|
const description = typeof item.description === "string" ? item.description.trim() : "";
|
|
@@ -11688,7 +11746,7 @@ var MnemonSubagentCoordinator = class {
|
|
|
11688
11746
|
const bounded = evidence.slice(0, 12);
|
|
11689
11747
|
const prompt = `Answer this question (untrusted data):\n${indentedText(query)}\n\nEvidence for this run (untrusted read-only data):\n${naturalEvidence(bounded)}`;
|
|
11690
11748
|
const { provider, runId, result } = await this.delegate(parent, "answer", "Memory evidence answer", prompt, [], ANSWER_SCHEMA, signal, "spawn", ANSWER_PERSONA);
|
|
11691
|
-
const value = object$
|
|
11749
|
+
const value = object$7(result.structured);
|
|
11692
11750
|
const allowed = new Set(bounded.map((item) => `${item.memoryBodyId ?? "unknown"}/${item.id}`));
|
|
11693
11751
|
return {
|
|
11694
11752
|
answer: typeof value.answer === "string" ? value.answer : "",
|
|
@@ -11715,7 +11773,7 @@ ${naturalRequest(request, target === void 0 ? REQUEST_LABELS : TARGETED_WRITE_LA
|
|
|
11715
11773
|
const persona = operation === "supervised-writeback" ? SUPERVISED_WRITE_PERSONA : autonomous ? AUTONOMOUS_WRITE_PERSONA : WRITE_PERSONA;
|
|
11716
11774
|
const terminalTool = WRITE_OPERATION_RESULT_TOOL[operation];
|
|
11717
11775
|
const { provider, runId, result, receipts, writes } = await this.delegate(parent, "write", `Mnemon ${operation}`, prompt, autonomous ? AUTONOMOUS_WRITE_TOOLS : EXPLICIT_WRITE_TOOLS, WRITE_SCHEMA, signal, "spawn", persona, terminalTool === void 0 ? void 0 : { terminalTools: [terminalTool] }, inactive === void 0 ? void 0 : spaceWriteGuard(target, inactive));
|
|
11718
|
-
const value = object$
|
|
11776
|
+
const value = object$7(result.structured);
|
|
11719
11777
|
const observed = terminalTool === void 0 ? void 0 : recoverStructuredResult({ terminalTools: [terminalTool] }, receipts);
|
|
11720
11778
|
const claimed = typeof observed?.action === "string" ? observed.action : typeof value.action === "string" ? value.action : "failed";
|
|
11721
11779
|
if (!autonomous) return {
|
|
@@ -11824,7 +11882,7 @@ ${naturalRequest(request, target === void 0 ? REQUEST_LABELS : TARGETED_WRITE_LA
|
|
|
11824
11882
|
const base = reviewPersona(tools.includes("mnemon_runtime_memory"));
|
|
11825
11883
|
const persona = preferred === "fork" ? base : base.replaceAll("inherited", "supplied bounded");
|
|
11826
11884
|
const { provider, runId, result } = await this.delegate(parent, "review", "Mnemon idle checkpoint review", prompt, tools, WRITE_SCHEMA, execution.signal, preferred, persona, { terminalTools: writers }, void 0, void 0, admission);
|
|
11827
|
-
const value = object$
|
|
11885
|
+
const value = object$7(result.structured);
|
|
11828
11886
|
return {
|
|
11829
11887
|
delegated: true,
|
|
11830
11888
|
runId,
|
|
@@ -11995,7 +12053,7 @@ This is the only completion channel for this run. Do not finish with a plain-tex
|
|
|
11995
12053
|
"failed",
|
|
11996
12054
|
"partial",
|
|
11997
12055
|
"unknown"
|
|
11998
|
-
].includes(String(object$
|
|
12056
|
+
].includes(String(object$7(structured).action))) throw new Error(`memory review reported ${object$7(structured).action}`);
|
|
11999
12057
|
completed = {
|
|
12000
12058
|
provider,
|
|
12001
12059
|
runId: activeRun.id,
|
|
@@ -12158,7 +12216,7 @@ const MNEMON_ACTIVITY_SCHEMA = "dsh-mnemon.activity/v1";
|
|
|
12158
12216
|
const MAX_ITEMS = 8;
|
|
12159
12217
|
const MAX_TITLE = 160;
|
|
12160
12218
|
const MAX_EXCERPT = 500;
|
|
12161
|
-
function object$
|
|
12219
|
+
function object$6(value) {
|
|
12162
12220
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
12163
12221
|
}
|
|
12164
12222
|
function bounded(value, maximum) {
|
|
@@ -12168,7 +12226,7 @@ function bounded(value, maximum) {
|
|
|
12168
12226
|
return truncate(normalized, maximum);
|
|
12169
12227
|
}
|
|
12170
12228
|
function item(value, index) {
|
|
12171
|
-
const entry = object$
|
|
12229
|
+
const entry = object$6(value);
|
|
12172
12230
|
if (entry === void 0) return void 0;
|
|
12173
12231
|
const content = bounded(entry.content ?? entry.text ?? entry.excerpt, MAX_EXCERPT);
|
|
12174
12232
|
const explicitTitle = bounded(entry.title ?? entry.label ?? entry.name ?? entry.memoryBodyName, MAX_TITLE);
|
|
@@ -12182,7 +12240,7 @@ function item(value, index) {
|
|
|
12182
12240
|
};
|
|
12183
12241
|
}
|
|
12184
12242
|
function resultItems(value) {
|
|
12185
|
-
const root = object$
|
|
12243
|
+
const root = object$6(value);
|
|
12186
12244
|
if (root === void 0) return [];
|
|
12187
12245
|
const candidates = [
|
|
12188
12246
|
root.results,
|
|
@@ -12201,8 +12259,8 @@ function resultItems(value) {
|
|
|
12201
12259
|
return items;
|
|
12202
12260
|
}
|
|
12203
12261
|
function writeItem(argsValue, operationId) {
|
|
12204
|
-
const outer = object$
|
|
12205
|
-
const input = object$
|
|
12262
|
+
const outer = object$6(argsValue) ?? {};
|
|
12263
|
+
const input = object$6(outer.input) ?? outer;
|
|
12206
12264
|
const content = bounded(input.content ?? input.description ?? input.reason ?? input.summary ?? input.old_text ?? input.oldText, MAX_EXCERPT);
|
|
12207
12265
|
const explicitTitle = bounded(input.title ?? input.name, MAX_TITLE);
|
|
12208
12266
|
const identity = bounded(input.id ?? input.memoryBodyId ?? input.targetMemoryBodyId ?? input.sourceId, 300);
|
|
@@ -12214,7 +12272,7 @@ function writeItem(argsValue, operationId) {
|
|
|
12214
12272
|
};
|
|
12215
12273
|
}
|
|
12216
12274
|
function reference(argsValue, key) {
|
|
12217
|
-
return bounded(object$
|
|
12275
|
+
return bounded(object$6(argsValue)?.[key], 600);
|
|
12218
12276
|
}
|
|
12219
12277
|
function memoryReadPresentation(sourceTypeId, operationId, referenceKey) {
|
|
12220
12278
|
return (args, value) => ({
|
|
@@ -12233,7 +12291,7 @@ function memoryWritePresentation(sourceTypeId, operationId, referenceKey) {
|
|
|
12233
12291
|
operationId,
|
|
12234
12292
|
...sourceTypeId === void 0 ? {} : { sourceTypeId },
|
|
12235
12293
|
...referenceKey === void 0 || reference(args, referenceKey) === void 0 ? {} : { reference: reference(args, referenceKey) },
|
|
12236
|
-
committed: mutationResultCommitted(value) || operationId === "mutate" && object$
|
|
12294
|
+
committed: mutationResultCommitted(value) || operationId === "mutate" && object$6(value)?.success === true,
|
|
12237
12295
|
item: writeItem(args, operationId)
|
|
12238
12296
|
});
|
|
12239
12297
|
}
|
|
@@ -12243,7 +12301,7 @@ function namedToolPresentation(name) {
|
|
|
12243
12301
|
return tool.kind === "write" ? memoryWritePresentation(tool.sourceTypeId, tool.operation) : memoryReadPresentation(tool.sourceTypeId, tool.operation);
|
|
12244
12302
|
}
|
|
12245
12303
|
function validItem(value) {
|
|
12246
|
-
const entry = object$
|
|
12304
|
+
const entry = object$6(value);
|
|
12247
12305
|
return entry !== void 0 && bounded(entry.id, 300) === entry.id && bounded(entry.title, MAX_TITLE) === entry.title && (entry.excerpt === void 0 || bounded(entry.excerpt, MAX_EXCERPT) === entry.excerpt);
|
|
12248
12306
|
}
|
|
12249
12307
|
function cleanItem(value) {
|
|
@@ -12256,7 +12314,7 @@ function cleanItem(value) {
|
|
|
12256
12314
|
}
|
|
12257
12315
|
/** Fail closed on arbitrary third-party/session metadata. */
|
|
12258
12316
|
function parseMnemonActivityMeta(value, callId, toolName) {
|
|
12259
|
-
const meta = object$
|
|
12317
|
+
const meta = object$6(value);
|
|
12260
12318
|
if (meta?.schema !== "dsh-mnemon.activity/v1" || meta.kind !== "read" && meta.kind !== "write") return {};
|
|
12261
12319
|
const operationId = bounded(meta.operationId, 300);
|
|
12262
12320
|
const sourceTypeId = bounded(meta.sourceTypeId, 128);
|
|
@@ -12825,6 +12883,7 @@ var MnemonAgentLifecycle = class {
|
|
|
12825
12883
|
reviewController;
|
|
12826
12884
|
reviewRunning = false;
|
|
12827
12885
|
reviewAccessBlocked = false;
|
|
12886
|
+
reviewAdmission;
|
|
12828
12887
|
lastReviewAt;
|
|
12829
12888
|
lastReviewAction;
|
|
12830
12889
|
lastReviewScore;
|
|
@@ -12862,6 +12921,10 @@ var MnemonAgentLifecycle = class {
|
|
|
12862
12921
|
this.agent.ctx.on("session/event", ((session, event) => this.sessionEvent(session, event))),
|
|
12863
12922
|
this.agent.ctx.on("system-prompt/assemble", ((assembly, context, next) => this.assemblePrompt(assembly, context, next))),
|
|
12864
12923
|
this.agent.ctx.on("agent/pre-step", ((payload, next) => this.preStep(payload, next)), { prepend: true }),
|
|
12924
|
+
this.agent.ctx.on("agent/request", (async (payload, next) => {
|
|
12925
|
+
await this.prepareReviewAccess(payload);
|
|
12926
|
+
return next();
|
|
12927
|
+
}), { prepend: true }),
|
|
12865
12928
|
this.agent.ctx.on("agent/turn-stopping", ((payload) => this.finishTurn(payload)))
|
|
12866
12929
|
];
|
|
12867
12930
|
return () => {
|
|
@@ -13006,18 +13069,28 @@ var MnemonAgentLifecycle = class {
|
|
|
13006
13069
|
activity.toolCallCount = tools.count;
|
|
13007
13070
|
activity.toolNames = tools.names;
|
|
13008
13071
|
if (!this.reviewActivity().eligible || !this.reviewAdmitted(payload.turn)) return;
|
|
13072
|
+
const admission = this.reviewAdmission;
|
|
13073
|
+
if (admission?.turn === payload.turn && admission.policy === this.reviewPolicy() && admission.available) this.scheduleIdleReview(payload.turn);
|
|
13074
|
+
}
|
|
13075
|
+
async prepareReviewAccess(payload) {
|
|
13076
|
+
this.recordComposedTurn(payload.turn);
|
|
13077
|
+
if (payload.signal.aborted || !this.restoreWatermark() || !this.idleReviewAllowed() || this.turnActivity.get(payload.turn)?.noMaintenance) return;
|
|
13078
|
+
const policy = this.reviewPolicy();
|
|
13079
|
+
if (this.reviewAdmission?.turn === payload.turn && this.reviewAdmission.policy === policy) return;
|
|
13009
13080
|
const controller = new AbortController();
|
|
13010
13081
|
const signal = AbortSignal.any([payload.signal, controller.signal]);
|
|
13011
13082
|
const epoch = this.reviewEpoch;
|
|
13012
|
-
const policy = this.reviewPolicy();
|
|
13013
13083
|
this.reviewController = controller;
|
|
13014
13084
|
this.reviewRunning = true;
|
|
13015
|
-
let admitted = false;
|
|
13016
13085
|
try {
|
|
13017
13086
|
const available = await this.coordinator.checkReviewAccess(this.agent, signal);
|
|
13018
13087
|
if (signal.aborted || epoch !== this.reviewEpoch || policy !== this.reviewPolicy() || !this.idleReviewAllowed()) return;
|
|
13019
13088
|
this.reviewAccessBlocked = !available;
|
|
13020
|
-
|
|
13089
|
+
this.reviewAdmission = {
|
|
13090
|
+
turn: payload.turn,
|
|
13091
|
+
policy,
|
|
13092
|
+
available
|
|
13093
|
+
};
|
|
13021
13094
|
} catch (error) {
|
|
13022
13095
|
if (!signal.aborted) this.fail(error);
|
|
13023
13096
|
} finally {
|
|
@@ -13026,7 +13099,6 @@ var MnemonAgentLifecycle = class {
|
|
|
13026
13099
|
this.reviewController = void 0;
|
|
13027
13100
|
}
|
|
13028
13101
|
}
|
|
13029
|
-
if (admitted) this.scheduleIdleReview(payload.turn);
|
|
13030
13102
|
}
|
|
13031
13103
|
sessionEvent(session, event) {
|
|
13032
13104
|
if (session !== this.agent.session) return;
|
|
@@ -13119,6 +13191,7 @@ var MnemonAgentLifecycle = class {
|
|
|
13119
13191
|
if (policy !== this.observedReviewPolicy) {
|
|
13120
13192
|
this.cancelIdleReview(true);
|
|
13121
13193
|
this.reviewAccessBlocked = false;
|
|
13194
|
+
this.reviewAdmission = void 0;
|
|
13122
13195
|
}
|
|
13123
13196
|
this.observedReviewPolicy = policy;
|
|
13124
13197
|
this.restoreWatermark();
|
|
@@ -14139,9 +14212,17 @@ var SkillAutoAdoption = class {
|
|
|
14139
14212
|
if (suggestion?.status !== "pending" || suggestion.draftId !== void 0) throw new AutomaticSkillStop("changed");
|
|
14140
14213
|
job.action = suggestion.action;
|
|
14141
14214
|
this.checkpoint(job);
|
|
14215
|
+
const settings = this.host.settings();
|
|
14216
|
+
const reserved = await job.source.mutate("auto-adoption-reserve", {
|
|
14217
|
+
id: job.id,
|
|
14218
|
+
limit: settings.autoAdoptDailyLimit,
|
|
14219
|
+
timeZone: settings.autoAdoptTimeZone
|
|
14220
|
+
}, job.controller.signal);
|
|
14221
|
+
if (!reserved.allowed) throw new AutomaticSkillStop(reserved.reason, `${reserved.used}/${reserved.limit} · ${reserved.date} · ${reserved.timeZone}`);
|
|
14142
14222
|
await this.record(job, {
|
|
14143
14223
|
stage: "queued",
|
|
14144
|
-
attempt
|
|
14224
|
+
attempt,
|
|
14225
|
+
detail: `${reserved.used}/${reserved.limit} · ${reserved.date} · ${reserved.timeZone}`
|
|
14145
14226
|
});
|
|
14146
14227
|
const cases = (await job.source.read("cases", { skill: suggestion.skillName })).filter((entry) => entry.enabled);
|
|
14147
14228
|
if (cases.length === 0) throw new AutomaticSkillStop("no-cases");
|
|
@@ -14213,6 +14294,7 @@ var SkillAutoAdoption = class {
|
|
|
14213
14294
|
await job.source.mutate("draft-adopt", {
|
|
14214
14295
|
id: draft.id,
|
|
14215
14296
|
automatic: {
|
|
14297
|
+
reservationId: reserved.reservationId,
|
|
14216
14298
|
draftHash: hashSkillDraft(draft),
|
|
14217
14299
|
baselineRunId: baseline.runId,
|
|
14218
14300
|
draftRunId: candidate.runId,
|
|
@@ -14244,7 +14326,7 @@ var SkillAutoAdoption = class {
|
|
|
14244
14326
|
attempt: Math.min(attempt, 3),
|
|
14245
14327
|
reason,
|
|
14246
14328
|
...scores,
|
|
14247
|
-
...failure instanceof AutomaticSkillStop ? {} : { detail: failure instanceof Error ? failure.message : String(failure) }
|
|
14329
|
+
...failure instanceof AutomaticSkillStop && failure.message === failure.reason ? {} : { detail: failure instanceof Error ? failure.message : String(failure) }
|
|
14248
14330
|
}).catch((recordError) => this.host.warn("Could not record automatic adoption outcome", recordError));
|
|
14249
14331
|
} finally {
|
|
14250
14332
|
for (const id of runIds) await job.source.mutate("run-cancel", { id }).catch((error) => this.host.warn("Could not stop automatic skill backtest", error));
|
|
@@ -15120,7 +15202,9 @@ function newSkillRoot(settings, source, catalog, explicit) {
|
|
|
15120
15202
|
if (settings.targetScope === "storage" && source.scope === void 0) throw new Error("The skill destination needs a known storage scope; select User or Project in Skills settings.");
|
|
15121
15203
|
root = settings.targetScope === "project" || settings.targetScope === "storage" && (source.scope?.storage === "workspace" || source.scope?.storage === "workspaces") ? "project-dsh" : "user-dsh";
|
|
15122
15204
|
}
|
|
15123
|
-
const
|
|
15205
|
+
const destination = catalog.roots.find((candidate) => candidate.kind === root);
|
|
15206
|
+
if (destination?.readOnly) throw new Error(`Cannot create a skill in ${root}: linked skill roots are read-only.`);
|
|
15207
|
+
const directory = destination?.path;
|
|
15124
15208
|
if (directory === void 0 || root.startsWith("project-") && catalog.projectRoot === void 0) throw new Error("Project skill roots need a selected workspace; select a workspace or choose User in Skills settings.");
|
|
15125
15209
|
if (root.startsWith("project-")) try {
|
|
15126
15210
|
if (!statSync(catalog.projectRoot).isDirectory()) throw new Error("not a directory");
|
|
@@ -15456,6 +15540,7 @@ var SkillEvolution = class {
|
|
|
15456
15540
|
...input.draftId === void 0 ? {} : { draftId: input.draftId },
|
|
15457
15541
|
...input.skill === void 0 ? {} : { skill: input.skill }
|
|
15458
15542
|
});
|
|
15543
|
+
if (pack.skill?.readOnly) throw new Error("Linked skills are read-only; use a local copy before generating an improvement draft.");
|
|
15459
15544
|
const previousId = input.draftId ?? pack.suggestion?.draftId;
|
|
15460
15545
|
const previous = previousId === void 0 ? (await source.read("drafts", {
|
|
15461
15546
|
skill: pack.skillName,
|
|
@@ -15510,6 +15595,7 @@ var SkillEvolution = class {
|
|
|
15510
15595
|
return await abortable(signal, async () => {
|
|
15511
15596
|
const pack = await source.read("evidence-pack", { suggestionId: input.suggestionId }, signal);
|
|
15512
15597
|
signal.throwIfAborted();
|
|
15598
|
+
if (pack.skill?.readOnly) throw new AutomaticSkillStop("changed");
|
|
15513
15599
|
if (pack.action !== input.action || pack.action === "update" && pack.suggestion?.skillFileHash !== pack.skill?.hash) throw new AutomaticSkillStop("changed");
|
|
15514
15600
|
const targetRoot = pack.action === "update" ? pack.skill.root : newSkillRoot(this.host.settings(), source, await source.read("catalog", null, signal), input.previous?.targetRoot ?? pack.suggestion?.targetRoot);
|
|
15515
15601
|
const guidance = [...input.previous?.guidance ?? [], ...input.guidance === "" ? [] : [input.guidance]].slice(-8);
|
|
@@ -15923,7 +16009,7 @@ function skillsSourceFor(runtime, agent) {
|
|
|
15923
16009
|
}
|
|
15924
16010
|
//#endregion
|
|
15925
16011
|
//#region src/host/rpc.ts
|
|
15926
|
-
function object$
|
|
16012
|
+
function object$5(value) {
|
|
15927
16013
|
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error("payload must be an object");
|
|
15928
16014
|
return value;
|
|
15929
16015
|
}
|
|
@@ -16119,7 +16205,7 @@ async function assisted(runtime, lifecycle, typeId, operation, input, signal, ta
|
|
|
16119
16205
|
...signal === void 0 ? {} : { signal }
|
|
16120
16206
|
});
|
|
16121
16207
|
return {
|
|
16122
|
-
...object$
|
|
16208
|
+
...object$5(result.value),
|
|
16123
16209
|
revision: result.revision
|
|
16124
16210
|
};
|
|
16125
16211
|
} finally {
|
|
@@ -16246,7 +16332,7 @@ async function skillAssistance(runtime, lifecycle, operation, input, signal) {
|
|
|
16246
16332
|
case "skill-backtest": {
|
|
16247
16333
|
const skillName = optionalString(input.skillName, "skillName");
|
|
16248
16334
|
if (skillName === void 0) throw new Error("skillName is required");
|
|
16249
|
-
const target = object$
|
|
16335
|
+
const target = object$5(input.target);
|
|
16250
16336
|
if (![
|
|
16251
16337
|
"current",
|
|
16252
16338
|
"draft",
|
|
@@ -16286,7 +16372,7 @@ async function skillAssistance(runtime, lifecycle, operation, input, signal) {
|
|
|
16286
16372
|
function createReadHandler(input, lifecycle, versions) {
|
|
16287
16373
|
return async (endpoint, rawPayload, signal) => {
|
|
16288
16374
|
try {
|
|
16289
|
-
const payload = object$
|
|
16375
|
+
const payload = object$5(rawPayload);
|
|
16290
16376
|
if (endpoint === "versions") {
|
|
16291
16377
|
if (versions === void 0) throw new Error("version checks are unavailable");
|
|
16292
16378
|
return success$1(await versions.check());
|
|
@@ -16307,7 +16393,7 @@ function createReadHandler(input, lifecycle, versions) {
|
|
|
16307
16393
|
if (lifecycle === void 0 || payload.operation !== "agent-search") throw new Error("Read-only Host assistance is unavailable");
|
|
16308
16394
|
const source = (await catalog(runtime, lifecycle)).sources.find((item) => item.sourceInstanceKey === payload.sourceInstanceKey);
|
|
16309
16395
|
if (source === void 0 || !source.assistance.includes("agent-search")) throw new Error("Host assistance is not available for this Source instance");
|
|
16310
|
-
const value = await assisted(runtime, lifecycle, source.sourceTypeId, "agent-search", object$
|
|
16396
|
+
const value = await assisted(runtime, lifecycle, source.sourceTypeId, "agent-search", object$5(payload.input), signal);
|
|
16311
16397
|
return success$1({
|
|
16312
16398
|
revision: (await catalog(runtime)).sources.find((item) => item.sourceInstanceKey === source.sourceInstanceKey)?.revision ?? source.revision,
|
|
16313
16399
|
value
|
|
@@ -16419,9 +16505,9 @@ function createActivationHandler(input) {
|
|
|
16419
16505
|
return async (endpoint, rawPayload, signal) => {
|
|
16420
16506
|
try {
|
|
16421
16507
|
if (endpoint === "source-assistance") {
|
|
16422
|
-
const payload = object$
|
|
16508
|
+
const payload = object$5(rawPayload);
|
|
16423
16509
|
if (payload.operation !== "activation" || payload.confirmed !== true) throw new Error("Unsupported activation operation");
|
|
16424
|
-
const fields = object$
|
|
16510
|
+
const fields = object$5(payload.input);
|
|
16425
16511
|
if (Object.keys(fields).some((key) => key !== "memoryBodyId" && key !== "active") || typeof fields.active !== "boolean" || typeof fields.memoryBodyId !== "string") throw new Error("Activation accepts only a Memory Space id and boolean state");
|
|
16426
16512
|
const runtime = scoped(input, payload);
|
|
16427
16513
|
requireWritable(runtime);
|
|
@@ -16445,7 +16531,7 @@ function createActivationHandler(input) {
|
|
|
16445
16531
|
}
|
|
16446
16532
|
}
|
|
16447
16533
|
if (endpoint !== "body") return badRequest$1("unknown activation endpoint: " + endpoint);
|
|
16448
|
-
const payload = object$
|
|
16534
|
+
const payload = object$5(rawPayload);
|
|
16449
16535
|
const unexpected = Object.keys(payload).filter((field) => !ACTIVATION_FIELDS.has(field));
|
|
16450
16536
|
if (unexpected.length > 0) return badRequest$1("unsupported activation fields: " + unexpected.join(", "));
|
|
16451
16537
|
if (typeof payload.memoryBodyId !== "string" || payload.memoryBodyId.trim() === "") return badRequest$1("memoryBodyId must be a non-empty string");
|
|
@@ -16464,7 +16550,7 @@ function createActivationHandler(input) {
|
|
|
16464
16550
|
function createWriteHandler(input, lifecycle, versions) {
|
|
16465
16551
|
return async (endpoint, rawPayload, signal) => {
|
|
16466
16552
|
try {
|
|
16467
|
-
const payload = object$
|
|
16553
|
+
const payload = object$5(rawPayload);
|
|
16468
16554
|
if (endpoint === "version-update") {
|
|
16469
16555
|
if (versions === void 0) throw new Error("version updates are unavailable");
|
|
16470
16556
|
if (!input.config.writeEnabled) throw new Error("dsh-mnemon is configured read-only (writeEnabled: false)");
|
|
@@ -16500,12 +16586,12 @@ function createWriteHandler(input, lifecycle, versions) {
|
|
|
16500
16586
|
if (source === void 0 || !source.assistance.includes(operation)) throw new Error("Host assistance is not available for this Source instance");
|
|
16501
16587
|
requireLayerOn(runtime, source.sourceTypeId);
|
|
16502
16588
|
if (operation !== "agent-search" && (payload.confirmed !== true || payload.expectedRevision !== source.revision)) throw new Error("Host assistance requires confirmation of the current Source revision");
|
|
16503
|
-
const value = await assisted(runtime, lifecycle, source.sourceTypeId, operation, object$
|
|
16589
|
+
const value = await assisted(runtime, lifecycle, source.sourceTypeId, operation, object$5(payload.input), signal, {
|
|
16504
16590
|
sourceInstanceKey: source.sourceInstanceKey,
|
|
16505
16591
|
expectedRevision: source.revision
|
|
16506
16592
|
});
|
|
16507
16593
|
if (source.sourceTypeId === "runtime") return success$1({
|
|
16508
|
-
revision: object$
|
|
16594
|
+
revision: object$5(value).revision,
|
|
16509
16595
|
value
|
|
16510
16596
|
});
|
|
16511
16597
|
return success$1({
|
|
@@ -16549,7 +16635,7 @@ function createWriteHandler(input, lifecycle, versions) {
|
|
|
16549
16635
|
function createPackHandler(input, nativeDirectoryPicker = () => false) {
|
|
16550
16636
|
return async (endpoint, rawPayload) => {
|
|
16551
16637
|
try {
|
|
16552
|
-
const payload = object$
|
|
16638
|
+
const payload = object$5(rawPayload);
|
|
16553
16639
|
const runtime = scoped(input, payload);
|
|
16554
16640
|
const manager = runtime.graph.packs;
|
|
16555
16641
|
if (endpoint === "target") return success$1({
|
|
@@ -16586,7 +16672,7 @@ function githubAuth(input) {
|
|
|
16586
16672
|
function createSyncHandler(input, onConfigured) {
|
|
16587
16673
|
return async (endpoint, rawPayload, signal) => {
|
|
16588
16674
|
try {
|
|
16589
|
-
const payload = object$
|
|
16675
|
+
const payload = object$5(rawPayload);
|
|
16590
16676
|
const runtime = scoped(input, payload);
|
|
16591
16677
|
const sync = runtime.graph.sync;
|
|
16592
16678
|
if (endpoint === "status") return success$1(await sync.status(signal));
|
|
@@ -16659,7 +16745,7 @@ function createSyncHandler(input, onConfigured) {
|
|
|
16659
16745
|
function createReviewHandler(input, lifecycle) {
|
|
16660
16746
|
return async (endpoint, rawPayload, signal) => {
|
|
16661
16747
|
try {
|
|
16662
|
-
const payload = object$
|
|
16748
|
+
const payload = object$5(rawPayload);
|
|
16663
16749
|
const ledger = input.reviews;
|
|
16664
16750
|
if (endpoint === "view") return success$1(ledger.view());
|
|
16665
16751
|
if (endpoint === "opinion") {
|
|
@@ -16746,6 +16832,106 @@ function hasNativeDirectoryPicker(ctx) {
|
|
|
16746
16832
|
}
|
|
16747
16833
|
}
|
|
16748
16834
|
//#endregion
|
|
16835
|
+
//#region src/host/embedding-settings.ts
|
|
16836
|
+
const object$4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
|
|
16837
|
+
/** Preserve other Host redaction while never returning a legacy inline key. */
|
|
16838
|
+
function publicEmbeddingSettings(value, original, metadata = false) {
|
|
16839
|
+
const config = object$4(value);
|
|
16840
|
+
if (!metadata && config.embedding === void 0) return value;
|
|
16841
|
+
const embedding = object$4(config.embedding);
|
|
16842
|
+
const raw = object$4(object$4(original).embedding);
|
|
16843
|
+
const apiKeyStorage = raw.apiKeyEnv ? "environment" : raw.apiKeyRef ? "credentials" : raw.apiKey ? "legacy" : "none";
|
|
16844
|
+
return {
|
|
16845
|
+
...config,
|
|
16846
|
+
embedding: {
|
|
16847
|
+
...embedding,
|
|
16848
|
+
..."apiKey" in embedding ? { apiKey: "" } : {},
|
|
16849
|
+
...metadata ? {
|
|
16850
|
+
apiKeyStorage,
|
|
16851
|
+
apiKeyConfigured: apiKeyStorage !== "none"
|
|
16852
|
+
} : {}
|
|
16853
|
+
}
|
|
16854
|
+
};
|
|
16855
|
+
}
|
|
16856
|
+
/** Write/verify a new record before referencing it; failures keep the old configuration and key intact. */
|
|
16857
|
+
async function prepareEmbeddingSettings(settings, namespace, operations, revision, store) {
|
|
16858
|
+
const last = operations.findLastIndex((operation) => operation.path.length === 1 && operation.path[0] === "embedding");
|
|
16859
|
+
if (namespace !== "mnemon" || last === -1) return {
|
|
16860
|
+
operations,
|
|
16861
|
+
revision
|
|
16862
|
+
};
|
|
16863
|
+
const operation = operations[last];
|
|
16864
|
+
const edits = operations.filter((entry, index) => index === last || entry.path[0] !== "embedding");
|
|
16865
|
+
if (operation.op === "unset") return {
|
|
16866
|
+
operations: edits,
|
|
16867
|
+
revision
|
|
16868
|
+
};
|
|
16869
|
+
const view = settings.describe({ redactSecrets: false }).find((candidate) => candidate.ns === namespace);
|
|
16870
|
+
if (view === void 0) throw new Error("Mnemon settings are unavailable");
|
|
16871
|
+
if (revision !== void 0 && revision !== view.revision) throw new Error("Settings changed; reload before saving the embedding connection");
|
|
16872
|
+
const previous = resolveEmbedding(object$4(object$4(view.value).embedding));
|
|
16873
|
+
const input = object$4(operation.value);
|
|
16874
|
+
if (typeof operation.value !== "object" || operation.value === null || Array.isArray(operation.value)) throw new Error("Embedding settings must be an object");
|
|
16875
|
+
if (input.apiKey !== void 0 && typeof input.apiKey !== "string") throw new Error("Embedding API key must be text");
|
|
16876
|
+
if (input.clearApiKey !== void 0 && typeof input.clearApiKey !== "boolean") throw new Error("clearApiKey must be boolean");
|
|
16877
|
+
const { apiKeyStorage: _storage, apiKeyConfigured: _configured, clearApiKey: _clear, ...next } = input;
|
|
16878
|
+
let resolved = resolveEmbedding(next);
|
|
16879
|
+
let rollback;
|
|
16880
|
+
if (input.clearApiKey === true) {
|
|
16881
|
+
next.apiKey = "";
|
|
16882
|
+
next.apiKeyRef = "";
|
|
16883
|
+
next.apiKeyEnv = "";
|
|
16884
|
+
} else if (resolved.apiKeyEnv) {
|
|
16885
|
+
if (resolved.apiKey) throw new Error("Choose an embedding API key or an environment variable, not both");
|
|
16886
|
+
next.apiKey = "";
|
|
16887
|
+
next.apiKeyRef = "";
|
|
16888
|
+
} else {
|
|
16889
|
+
if (resolved.apiKeyRef && resolved.apiKeyRef !== previous.apiKeyRef) throw new Error("Save a key to create an embedding credential reference");
|
|
16890
|
+
const sameEndpoint = resolved.endpoint === previous.endpoint;
|
|
16891
|
+
if (!resolved.apiKey && !sameEndpoint && (previous.apiKeyRef || previous.apiKey)) throw new Error("Changing the embedding endpoint requires a new key, an environment variable, or explicitly removing the saved key");
|
|
16892
|
+
const key = resolved.apiKey || (sameEndpoint ? previous.apiKey : "");
|
|
16893
|
+
if (key) {
|
|
16894
|
+
const credentials = store?.();
|
|
16895
|
+
if (credentials === void 0) throw new Error("DSH credentials storage is unavailable; configure apiKeyEnv instead. The existing connection was not changed");
|
|
16896
|
+
const reference = EMBEDDING_CREDENTIAL_PREFIX + randomUUID();
|
|
16897
|
+
const payload = {
|
|
16898
|
+
version: 1,
|
|
16899
|
+
endpoint: resolved.endpoint,
|
|
16900
|
+
apiKey: key
|
|
16901
|
+
};
|
|
16902
|
+
rollback = async () => {
|
|
16903
|
+
await credentials.deleteRecord(reference);
|
|
16904
|
+
};
|
|
16905
|
+
try {
|
|
16906
|
+
await credentials.modifyRecord(reference, async () => ({
|
|
16907
|
+
kind: "grant",
|
|
16908
|
+
payload
|
|
16909
|
+
}));
|
|
16910
|
+
const record = await credentials.readRecord(reference);
|
|
16911
|
+
if (record?.kind !== "grant" || record.payload?.version !== 1 || record.payload.endpoint !== payload.endpoint || record.payload.apiKey !== key) throw new Error("Credential readback failed");
|
|
16912
|
+
} catch {
|
|
16913
|
+
await rollback().catch(() => {});
|
|
16914
|
+
throw new Error("Could not save and verify the embedding credential; the existing connection was not changed");
|
|
16915
|
+
}
|
|
16916
|
+
next.apiKey = "";
|
|
16917
|
+
next.apiKeyRef = reference;
|
|
16918
|
+
} else if (sameEndpoint && previous.apiKeyRef) {
|
|
16919
|
+
next.apiKey = "";
|
|
16920
|
+
next.apiKeyRef = previous.apiKeyRef;
|
|
16921
|
+
}
|
|
16922
|
+
}
|
|
16923
|
+
resolved = resolveEmbedding(next);
|
|
16924
|
+
if (resolved.apiKey) throw new Error("Embedding settings must not persist a plaintext key");
|
|
16925
|
+
return {
|
|
16926
|
+
operations: edits.map((entry) => entry === operation ? {
|
|
16927
|
+
...entry,
|
|
16928
|
+
value: next
|
|
16929
|
+
} : entry),
|
|
16930
|
+
revision: revision ?? view.revision,
|
|
16931
|
+
...rollback === void 0 ? {} : { rollback }
|
|
16932
|
+
};
|
|
16933
|
+
}
|
|
16934
|
+
//#endregion
|
|
16749
16935
|
//#region src/host/settings.ts
|
|
16750
16936
|
function success(value) {
|
|
16751
16937
|
return {
|
|
@@ -16776,14 +16962,16 @@ function badRequest(message) {
|
|
|
16776
16962
|
function descriptor(settings, namespace) {
|
|
16777
16963
|
const view = settings.describe({ redactSecrets: true }).find((candidate) => candidate.ns === namespace);
|
|
16778
16964
|
if (view === void 0) throw new Error(`${namespace} settings namespace is unavailable`);
|
|
16965
|
+
const raw = namespace === "mnemon" ? settings.describe({ redactSecrets: false }).find((candidate) => candidate.ns === namespace) : void 0;
|
|
16966
|
+
const visible = namespace === "mnemon" ? publicEmbeddingSettings(view.value, raw?.value, true) : view.value;
|
|
16779
16967
|
return {
|
|
16780
16968
|
status: "ready",
|
|
16781
16969
|
value: namespace === "mnemon" && displayModeOf(view.value) === "buildin" ? {
|
|
16782
|
-
...object$3(
|
|
16970
|
+
...object$3(visible),
|
|
16783
16971
|
displayMode: "builtin"
|
|
16784
|
-
} :
|
|
16785
|
-
base: view.base,
|
|
16786
|
-
user: view.user,
|
|
16972
|
+
} : visible,
|
|
16973
|
+
base: namespace === "mnemon" ? publicEmbeddingSettings(view.base, raw?.base) : view.base,
|
|
16974
|
+
user: namespace === "mnemon" ? publicEmbeddingSettings(view.user, raw?.user) : view.user,
|
|
16787
16975
|
revision: view.revision,
|
|
16788
16976
|
writable: settings.writable,
|
|
16789
16977
|
mode: "host",
|
|
@@ -16860,7 +17048,7 @@ function mutablePath(namespace, path) {
|
|
|
16860
17048
|
if (path.length === 4 && path[0] === "memoryTopology" && path[1] === "layers" && path[3] === "enabled") return MEMORY_LAYER_ID.test(path[2]);
|
|
16861
17049
|
return INTERACTION_PATHS.some((allowed) => allowed.length === path.length && allowed.every((segment, index) => segment === path[index]));
|
|
16862
17050
|
}
|
|
16863
|
-
function createSettingsHandler(settings) {
|
|
17051
|
+
function createSettingsHandler(settings, credentials) {
|
|
16864
17052
|
return async (endpoint, rawPayload) => {
|
|
16865
17053
|
let namespace = MNEMON_SETTINGS_NAMESPACE;
|
|
16866
17054
|
try {
|
|
@@ -16887,7 +17075,13 @@ function createSettingsHandler(settings) {
|
|
|
16887
17075
|
};
|
|
16888
17076
|
});
|
|
16889
17077
|
const revision = payload.expectedRevision === void 0 ? void 0 : Number(payload.expectedRevision);
|
|
16890
|
-
await settings
|
|
17078
|
+
const prepared = await prepareEmbeddingSettings(settings, namespace, ops, revision, credentials);
|
|
17079
|
+
try {
|
|
17080
|
+
await settings.mutate(namespace, prepared.operations, prepared.revision);
|
|
17081
|
+
} catch (error) {
|
|
17082
|
+
await prepared.rollback?.().catch(() => {});
|
|
17083
|
+
throw error;
|
|
17084
|
+
}
|
|
16891
17085
|
if (namespace === "mnemon") await migrateLegacyDisplayMode(settings);
|
|
16892
17086
|
return success(descriptor(settings, namespace));
|
|
16893
17087
|
} catch (error) {
|
|
@@ -16895,8 +17089,8 @@ function createSettingsHandler(settings) {
|
|
|
16895
17089
|
}
|
|
16896
17090
|
};
|
|
16897
17091
|
}
|
|
16898
|
-
function registerSettingsRpc(connection, settings) {
|
|
16899
|
-
const handler = createSettingsHandler(settings);
|
|
17092
|
+
function registerSettingsRpc(connection, settings, credentials) {
|
|
17093
|
+
const handler = createSettingsHandler(settings, credentials);
|
|
16900
17094
|
connection.rpc.handle(MNEMON_SETTINGS_CHANNEL, handler);
|
|
16901
17095
|
return handler;
|
|
16902
17096
|
}
|
|
@@ -19981,7 +20175,7 @@ function apply(rawContext, rawConfig = {}) {
|
|
|
19981
20175
|
pluginCommand: () => dshPluginCommand(ctx.get("profileContext"))
|
|
19982
20176
|
});
|
|
19983
20177
|
const rpc = registerRpc(connection, runtime, lifecycle, versions, () => autoBackup.refresh(), () => hasNativeDirectoryPicker(ctx));
|
|
19984
|
-
const settings = registerSettingsRpc(connection, hostSettings);
|
|
20178
|
+
const settings = registerSettingsRpc(connection, hostSettings, () => ctx.get("credentials") ?? ctx.credentials);
|
|
19985
20179
|
const view = registerViewRpc(connection, runtime, extensions, memoryPlugins, lifecycle, pluginInstallation);
|
|
19986
20180
|
if (Context.is(webContext)) new MnemonRemoteService(webContext, {
|
|
19987
20181
|
...rpc,
|