dsh-mnemon 0.5.40 → 0.5.41
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/bundle.js +1 -1
- package/lib/client.js +70 -0
- package/lib/index.js +424 -57
- package/lib/{starter-resolution-C5nNk-cs.js → starter-resolution-xVjONc6g.js} +1 -1
- package/lib/starter.js +1 -1
- package/lib/types/src/client/locales.d.ts +4 -0
- package/lib/types/src/host/protocol.d.ts +7 -0
- package/package.json +2 -2
package/lib/bundle.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as prepareStarterResolution } from "./starter-resolution-
|
|
1
|
+
import { t as prepareStarterResolution } from "./starter-resolution-xVjONc6g.js";
|
|
2
2
|
//#region src/bundle.ts
|
|
3
3
|
const groupKey = Symbol.for("cordis.group");
|
|
4
4
|
const init = Symbol.for("cordis.init");
|
package/lib/client.js
CHANGED
|
@@ -318,6 +318,8 @@ window.__ModuleLoader__.load({
|
|
|
318
318
|
allowUpdate: true,
|
|
319
319
|
targetScope: "user",
|
|
320
320
|
autoBacktest: true,
|
|
321
|
+
draftMaxTokens: 32768,
|
|
322
|
+
draftRetryMaxTokens: 65536,
|
|
321
323
|
hints: true,
|
|
322
324
|
sidebar: false,
|
|
323
325
|
reviewThreshold: 5,
|
|
@@ -3145,6 +3147,10 @@ window.__ModuleLoader__.load({
|
|
|
3145
3147
|
"skills.autoBacktest": "草案自动回测",
|
|
3146
3148
|
"skills.autoBacktestHint": "草案写好后,用测试用例与当前版本对比",
|
|
3147
3149
|
"skills.parameters": "复盘参数",
|
|
3150
|
+
"skills.draftGeneration": "草案生成",
|
|
3151
|
+
"skills.draftMaxTokens": "草案输出 token 上限",
|
|
3152
|
+
"skills.draftRetryMaxTokens": "重试输出 token 上限",
|
|
3153
|
+
"skills.draftBudgetHint": "预算包含推理与完整 SKILL.md。截断时仅在重试上限更大时重新生成一次;设为相同或更小值可关闭扩容重试。两项均需符合模型提供方的输出限制,保存后用于下一次草案。",
|
|
3148
3154
|
"skills.reviewThreshold": "复盘阈值",
|
|
3149
3155
|
"skills.idleSeconds": "空闲等待(秒)",
|
|
3150
3156
|
"skills.cooldownSeconds": "复盘间隔(秒)",
|
|
@@ -3965,6 +3971,10 @@ window.__ModuleLoader__.load({
|
|
|
3965
3971
|
"skills.autoBacktest": "Backtest drafts",
|
|
3966
3972
|
"skills.autoBacktestHint": "Compare a new draft with the current version on its test cases",
|
|
3967
3973
|
"skills.parameters": "Review parameters",
|
|
3974
|
+
"skills.draftGeneration": "Draft generation",
|
|
3975
|
+
"skills.draftMaxTokens": "Draft output token limit",
|
|
3976
|
+
"skills.draftRetryMaxTokens": "Retry output token limit",
|
|
3977
|
+
"skills.draftBudgetHint": "Budgets include reasoning and the complete SKILL.md. Truncation triggers one fresh attempt only when the retry limit is higher; an equal or lower value disables it. Keep both within the model provider’s output limit. Saved changes apply to the next draft.",
|
|
3968
3978
|
"skills.reviewThreshold": "Review threshold",
|
|
3969
3979
|
"skills.idleSeconds": "Idle wait (s)",
|
|
3970
3980
|
"skills.cooldownSeconds": "Review interval (s)",
|
|
@@ -12032,6 +12042,17 @@ window.__ModuleLoader__.load({
|
|
|
12032
12042
|
integer: true
|
|
12033
12043
|
}
|
|
12034
12044
|
];
|
|
12045
|
+
const DRAFT_PARAMETERS = [{
|
|
12046
|
+
key: "draftMaxTokens",
|
|
12047
|
+
min: 128,
|
|
12048
|
+
max: 131072,
|
|
12049
|
+
integer: true
|
|
12050
|
+
}, {
|
|
12051
|
+
key: "draftRetryMaxTokens",
|
|
12052
|
+
min: 128,
|
|
12053
|
+
max: 131072,
|
|
12054
|
+
integer: true
|
|
12055
|
+
}];
|
|
12035
12056
|
/** The value a parameter stores, or undefined when the Host would refuse it. */
|
|
12036
12057
|
function parameterValue(field, text) {
|
|
12037
12058
|
if (text.trim() === "") return void 0;
|
|
@@ -12072,8 +12093,16 @@ window.__ModuleLoader__.load({
|
|
|
12072
12093
|
const changed = PARAMETERS.filter((field) => parameterValue(field, draft[field.key]) !== saved[field.key]);
|
|
12073
12094
|
if (changed.length > 0) await scope.mutate(changed.map((field) => set(field.key, parameterValue(field, draft[field.key]))));
|
|
12074
12095
|
});
|
|
12096
|
+
const draftBudgets = useStaged({
|
|
12097
|
+
draftMaxTokens: String(saved.draftMaxTokens),
|
|
12098
|
+
draftRetryMaxTokens: String(saved.draftRetryMaxTokens)
|
|
12099
|
+
}, async (draft) => {
|
|
12100
|
+
const changed = DRAFT_PARAMETERS.filter((field) => parameterValue(field, draft[field.key]) !== saved[field.key]);
|
|
12101
|
+
if (changed.length > 0) await scope.mutate(changed.map((field) => set(field.key, parameterValue(field, draft[field.key]))));
|
|
12102
|
+
});
|
|
12075
12103
|
const disabled = !page.writable || snapshot.status === "loading" || !snapshot.writable;
|
|
12076
12104
|
const invalid = PARAMETERS.find((field) => parameterValue(field, parameters.draft[field.key]) === void 0);
|
|
12105
|
+
const invalidDraft = DRAFT_PARAMETERS.find((field) => parameterValue(field, draftBudgets.draft[field.key]) === void 0);
|
|
12077
12106
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
12078
12107
|
className: MnemonSettingsCard_module_css_default.panelSection,
|
|
12079
12108
|
"aria-label": t("skills.label"),
|
|
@@ -12133,6 +12162,47 @@ window.__ModuleLoader__.load({
|
|
|
12133
12162
|
destination.apply();
|
|
12134
12163
|
}
|
|
12135
12164
|
}),
|
|
12165
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
|
|
12166
|
+
className: MnemonSettingsCard_module_css_default.advanced,
|
|
12167
|
+
children: [
|
|
12168
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("summary", { children: [t("skills.draftGeneration"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineRegular, { size: 12 })] }),
|
|
12169
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
12170
|
+
className: MnemonSettingsCard_module_css_default.panelNote,
|
|
12171
|
+
children: t("skills.draftBudgetHint")
|
|
12172
|
+
}),
|
|
12173
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
12174
|
+
className: MnemonSettingsCard_module_css_default.fieldGrid,
|
|
12175
|
+
children: DRAFT_PARAMETERS.map((field) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", { children: [t(`skills.${field.key}`), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
12176
|
+
type: "number",
|
|
12177
|
+
step: 1,
|
|
12178
|
+
min: field.min,
|
|
12179
|
+
max: field.max,
|
|
12180
|
+
inputMode: "numeric",
|
|
12181
|
+
value: draftBudgets.draft[field.key],
|
|
12182
|
+
disabled: disabled || draftBudgets.saving,
|
|
12183
|
+
"aria-invalid": parameterValue(field, draftBudgets.draft[field.key]) === void 0,
|
|
12184
|
+
onChange: (event) => draftBudgets.edit({ [field.key]: event.target.value })
|
|
12185
|
+
})] }, field.key))
|
|
12186
|
+
}),
|
|
12187
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(PanelActions, {
|
|
12188
|
+
dirty: draftBudgets.dirty,
|
|
12189
|
+
saving: draftBudgets.saving,
|
|
12190
|
+
applied: draftBudgets.applied,
|
|
12191
|
+
failed: draftBudgets.failed,
|
|
12192
|
+
disabled,
|
|
12193
|
+
t,
|
|
12194
|
+
invalid: invalidDraft === void 0 ? null : t("skills.invalid", {
|
|
12195
|
+
field: t(`skills.${invalidDraft.key}`),
|
|
12196
|
+
min: invalidDraft.min,
|
|
12197
|
+
max: invalidDraft.max
|
|
12198
|
+
}),
|
|
12199
|
+
onDiscard: draftBudgets.discard,
|
|
12200
|
+
onApply: () => {
|
|
12201
|
+
draftBudgets.apply();
|
|
12202
|
+
}
|
|
12203
|
+
})
|
|
12204
|
+
]
|
|
12205
|
+
}),
|
|
12136
12206
|
evolution.value && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToggleRow, {
|
|
12137
12207
|
id: "mnemon-skills-backtest",
|
|
12138
12208
|
label: t("skills.autoBacktest"),
|
package/lib/index.js
CHANGED
|
@@ -389,6 +389,8 @@ const DEFAULT_SKILLS_CONFIG = Object.freeze({
|
|
|
389
389
|
allowUpdate: true,
|
|
390
390
|
targetScope: "user",
|
|
391
391
|
autoBacktest: true,
|
|
392
|
+
draftMaxTokens: 32768,
|
|
393
|
+
draftRetryMaxTokens: 65536,
|
|
392
394
|
hints: true,
|
|
393
395
|
sidebar: false,
|
|
394
396
|
reviewThreshold: 5,
|
|
@@ -481,6 +483,8 @@ const SkillsConfig = z.object({
|
|
|
481
483
|
"project"
|
|
482
484
|
]).default(DEFAULT_SKILLS_CONFIG.targetScope),
|
|
483
485
|
autoBacktest: z.boolean().default(DEFAULT_SKILLS_CONFIG.autoBacktest),
|
|
486
|
+
draftMaxTokens: z.number().step(1).min(128).max(131072).default(DEFAULT_SKILLS_CONFIG.draftMaxTokens),
|
|
487
|
+
draftRetryMaxTokens: z.number().step(1).min(128).max(131072).default(DEFAULT_SKILLS_CONFIG.draftRetryMaxTokens),
|
|
484
488
|
hints: z.boolean().default(DEFAULT_SKILLS_CONFIG.hints),
|
|
485
489
|
sidebar: z.boolean().default(DEFAULT_SKILLS_CONFIG.sidebar),
|
|
486
490
|
reviewThreshold: z.number().step(1).min(1).max(50).default(DEFAULT_SKILLS_CONFIG.reviewThreshold),
|
|
@@ -640,6 +644,7 @@ const Config = z.object({
|
|
|
640
644
|
skills: SkillsConfig.default({ ...DEFAULT_SKILLS_CONFIG }),
|
|
641
645
|
persistenceStrategy: MemoryPersistenceStrategySchema,
|
|
642
646
|
taskAgentModel: TaskAgentModelSchema,
|
|
647
|
+
subagentProviderNames: z.array(z.string()).default([]),
|
|
643
648
|
syncEnabled: z.boolean().default(false)
|
|
644
649
|
});
|
|
645
650
|
function resolveInteractionConfig(config = {}) {
|
|
@@ -689,6 +694,11 @@ function resolveCustomPacks(value, legacyDataDir) {
|
|
|
689
694
|
}
|
|
690
695
|
return packs;
|
|
691
696
|
}
|
|
697
|
+
function resolveSubagentProviderNames(value) {
|
|
698
|
+
if (value === void 0) return [];
|
|
699
|
+
if (!Array.isArray(value) || value.length > 32 || value.some((name) => typeof name !== "string" || !name.trim() || name.length > 128)) throw new Error("dsh-mnemon: subagentProviderNames must contain at most 32 nonempty provider names of at most 128 characters");
|
|
700
|
+
return [...new Set(value.map((name) => name.trim()))];
|
|
701
|
+
}
|
|
692
702
|
function resolveTaskAgentModel(value) {
|
|
693
703
|
const mode = value?.mode ?? "inherit";
|
|
694
704
|
if (mode !== "inherit" && mode !== "fixed") throw new Error(`dsh-mnemon: unsupported task Agent model mode: ${String(mode)}`);
|
|
@@ -813,6 +823,7 @@ function resolveConfig(config = {}) {
|
|
|
813
823
|
},
|
|
814
824
|
persistenceStrategy: resolvePersistenceStrategy(config.persistenceStrategy),
|
|
815
825
|
taskAgentModel: resolveTaskAgentModel(config.taskAgentModel),
|
|
826
|
+
subagentProviderNames: resolveSubagentProviderNames(config.subagentProviderNames),
|
|
816
827
|
syncEnabled: config.syncEnabled ?? false
|
|
817
828
|
};
|
|
818
829
|
}
|
|
@@ -7187,9 +7198,9 @@ var MemoryExecutions = class {
|
|
|
7187
7198
|
constructor(runtime) {
|
|
7188
7199
|
this.runtime = runtime;
|
|
7189
7200
|
}
|
|
7190
|
-
async turn(agent, turn, signal, delegation) {
|
|
7201
|
+
async turn(agent, turn, signal, delegation, independent = false) {
|
|
7191
7202
|
signal.throwIfAborted();
|
|
7192
|
-
const slot = this.open(agent, "turn", `${agent.id}:${turn}`, "agent.root-turn", delegation);
|
|
7203
|
+
const slot = this.open(agent, "turn", `${agent.id}:${turn}`, "agent.root-turn", delegation, independent);
|
|
7193
7204
|
const abort = () => slot.controller.abort(signal.reason);
|
|
7194
7205
|
signal.addEventListener("abort", abort, { once: true });
|
|
7195
7206
|
try {
|
|
@@ -7272,7 +7283,7 @@ var MemoryExecutions = class {
|
|
|
7272
7283
|
if (slot.kind === "turn") slot.close();
|
|
7273
7284
|
}
|
|
7274
7285
|
}
|
|
7275
|
-
open(agent, kind, turnId, purpose, delegation) {
|
|
7286
|
+
open(agent, kind, turnId, purpose, delegation, independent = false) {
|
|
7276
7287
|
this.assertOpen();
|
|
7277
7288
|
const previous = this.slots.get(agent.id);
|
|
7278
7289
|
const done = deferred();
|
|
@@ -7307,7 +7318,7 @@ var MemoryExecutions = class {
|
|
|
7307
7318
|
await previous?.done;
|
|
7308
7319
|
slot.controller.signal.throwIfAborted();
|
|
7309
7320
|
this.assertOpen();
|
|
7310
|
-
const graph = delegation?.graph ?? this.runtime.forAgent(agent);
|
|
7321
|
+
const graph = delegation?.graph ?? (independent ? this.runtime.forAgent(agent, { independent: true }) : this.runtime.forAgent(agent));
|
|
7311
7322
|
const manager = graph.composableTurns;
|
|
7312
7323
|
const scope = delegation === void 0 ? agentScope(agent, graph.config) : {
|
|
7313
7324
|
...delegation.scope,
|
|
@@ -7619,13 +7630,15 @@ var LiveMnemonRuntime = class {
|
|
|
7619
7630
|
for (const graph of graphs) graph.dispose();
|
|
7620
7631
|
}
|
|
7621
7632
|
/** Resolve the runtime that must serve one Agent execution. */
|
|
7622
|
-
forAgent(agent) {
|
|
7633
|
+
forAgent(agent, options = {}) {
|
|
7623
7634
|
this.assertOpen();
|
|
7624
|
-
|
|
7625
|
-
|
|
7626
|
-
|
|
7627
|
-
|
|
7628
|
-
|
|
7635
|
+
if (!options.independent) {
|
|
7636
|
+
const pinned = this.agentGraphs.get(agent.id);
|
|
7637
|
+
if (pinned !== void 0) return pinned.graph;
|
|
7638
|
+
const parentSession = agent.session.header?.origin === "subagent" ? agent.session.header.parentSession?.trim() : void 0;
|
|
7639
|
+
const inherited = parentSession === void 0 || parentSession === "" ? void 0 : this.agentGraphs.get(parentSession);
|
|
7640
|
+
if (inherited !== void 0) return inherited.graph;
|
|
7641
|
+
}
|
|
7629
7642
|
if (!isWorkspaceStorageScope(this.current.config.storageScope)) return this.current;
|
|
7630
7643
|
const cwd = agent.session.header?.cwd?.trim();
|
|
7631
7644
|
if (cwd === void 0 || cwd === "") throw new Error("the current DSH session has no workspace for Mnemon");
|
|
@@ -8461,6 +8474,72 @@ async function applyReconcileOperations(operations, applier, signal, selection)
|
|
|
8461
8474
|
};
|
|
8462
8475
|
}
|
|
8463
8476
|
//#endregion
|
|
8477
|
+
//#region src/host/agent-compat.ts
|
|
8478
|
+
function configuredProviderNames(host) {
|
|
8479
|
+
const names = /* @__PURE__ */ new Set();
|
|
8480
|
+
for (const runtime of host?.registry?.values() ?? []) for (const fiber of runtime.fibers) {
|
|
8481
|
+
const config = fiber.effectiveConfig;
|
|
8482
|
+
if (config && typeof config === "object" && "providerName" in config && typeof config.providerName === "string") names.add(config.providerName);
|
|
8483
|
+
}
|
|
8484
|
+
return [...names];
|
|
8485
|
+
}
|
|
8486
|
+
/** Official 0.2.2-rc.1 has registry ownership; master fcc0ad4 moved it into Subagent. */
|
|
8487
|
+
function activationOwned(subagents) {
|
|
8488
|
+
return typeof subagents?.rootOf === "function";
|
|
8489
|
+
}
|
|
8490
|
+
/** Only live registry instances can be adopted; persisted lineage is not authority. */
|
|
8491
|
+
function isRootAgent(agents, subagents, agent) {
|
|
8492
|
+
if (agents.get(agent.id) !== agent) return false;
|
|
8493
|
+
if (typeof agents.roots === "function") return agents.roots().includes(agent);
|
|
8494
|
+
try {
|
|
8495
|
+
return subagents.rootOf?.(agent) === agent;
|
|
8496
|
+
} catch {
|
|
8497
|
+
return false;
|
|
8498
|
+
}
|
|
8499
|
+
}
|
|
8500
|
+
function rootAgents(agents, subagents) {
|
|
8501
|
+
if (typeof agents.roots === "function") return agents.roots();
|
|
8502
|
+
return (agents.list?.() ?? []).filter((agent) => isRootAgent(agents, subagents, agent));
|
|
8503
|
+
}
|
|
8504
|
+
/** Persisted IDs keep completed internal sessions out of conversation automation after restart. */
|
|
8505
|
+
function isTaskRecord(id) {
|
|
8506
|
+
return /^mnemon-(?:task|run)-v1-[0-9a-f-]{36}$/.test(id);
|
|
8507
|
+
}
|
|
8508
|
+
function titleTask(agent, title) {
|
|
8509
|
+
(agent.ctx.get?.("sessionTitle"))?.rename?.(agent.session, title);
|
|
8510
|
+
}
|
|
8511
|
+
const creatingChild = new AsyncLocalStorage();
|
|
8512
|
+
/** Share one reservation across guard, continuation and composition wrappers, never across nested runs. */
|
|
8513
|
+
function withReservedChild(parent, operation, fresh = false) {
|
|
8514
|
+
const current = creatingChild.getStore();
|
|
8515
|
+
if (!fresh && current?.parent === parent && !current.claimed) return operation();
|
|
8516
|
+
return creatingChild.run({
|
|
8517
|
+
parent,
|
|
8518
|
+
id: `mnemon-run-v1-${randomUUID()}`
|
|
8519
|
+
}, operation);
|
|
8520
|
+
}
|
|
8521
|
+
function reservedChildId(parent) {
|
|
8522
|
+
const current = creatingChild.getStore();
|
|
8523
|
+
return current?.parent === parent && !current.claimed ? current.id : void 0;
|
|
8524
|
+
}
|
|
8525
|
+
function claimReservedChild(parent) {
|
|
8526
|
+
const current = creatingChild.getStore();
|
|
8527
|
+
if (current?.parent !== parent || current.claimed) return void 0;
|
|
8528
|
+
current.claimed = true;
|
|
8529
|
+
return current.id;
|
|
8530
|
+
}
|
|
8531
|
+
function isCreatingChild(agents, child) {
|
|
8532
|
+
const current = creatingChild.getStore();
|
|
8533
|
+
return current !== void 0 && isReservedChild(agents, current.parent, child);
|
|
8534
|
+
}
|
|
8535
|
+
/** A lineage string or same-tree relationship is not a creation capability. */
|
|
8536
|
+
function isReservedChild(agents, parent, child) {
|
|
8537
|
+
const current = creatingChild.getStore();
|
|
8538
|
+
if (current?.parent !== parent || !current.claimed || current.id !== child.id || agents?.get?.(parent.id) !== parent || agents.get(child.id) !== child || current.child !== void 0 && current.child !== child) return false;
|
|
8539
|
+
current.child = child;
|
|
8540
|
+
return true;
|
|
8541
|
+
}
|
|
8542
|
+
//#endregion
|
|
8464
8543
|
//#region src/host/review-tools.ts
|
|
8465
8544
|
const startingChild$1 = new AsyncLocalStorage();
|
|
8466
8545
|
/**
|
|
@@ -8470,7 +8549,11 @@ const startingChild$1 = new AsyncLocalStorage();
|
|
|
8470
8549
|
* still requires startGuardedReview; it never removes another plugin's policy.
|
|
8471
8550
|
*/
|
|
8472
8551
|
function idleReviewBlockReason(parent, agentTeams = "pause") {
|
|
8473
|
-
|
|
8552
|
+
if (agentTeams === "scoped") return void 0;
|
|
8553
|
+
const teams = parent.ctx?.get?.("agentTeams");
|
|
8554
|
+
if (teams === void 0) return void 0;
|
|
8555
|
+
const tools = parent.ctx.tools;
|
|
8556
|
+
return tools?.get?.("spawn_teammate", parent) !== void 0 || typeof teams?.isEnabled === "function" && teams.isEnabled(parent) && tools?.get?.("team_task_create", parent) !== void 0 ? "agent-team" : void 0;
|
|
8474
8557
|
}
|
|
8475
8558
|
/** The two writes an idle review can make, one per layer; both are rows of the tool table. */
|
|
8476
8559
|
const DOCUMENT_WRITE = "mnemon_document_create";
|
|
@@ -8522,20 +8605,24 @@ function startGuardedReview(host, parent, toolNames, start, published, policy) {
|
|
|
8522
8605
|
async function startGuardedChild(host, parent, start, guard, options) {
|
|
8523
8606
|
const { purpose, published } = options;
|
|
8524
8607
|
const agents = host.agents;
|
|
8525
|
-
|
|
8608
|
+
const reserved = activationOwned(host.subagents);
|
|
8609
|
+
if (reserved && typeof agents?.get !== "function") throw new Error(`Mnemon ${purpose} requires exact live Agent lookup`);
|
|
8610
|
+
if (!reserved && typeof agents?.isOwnedBy !== "function") {
|
|
8526
8611
|
if (options.optional === true) return start();
|
|
8527
8612
|
throw new Error(`Mnemon ${purpose} requires DSH Agent ownership and scoped tool guard support`);
|
|
8528
8613
|
}
|
|
8529
8614
|
const pending = Symbol(`Mnemon ${purpose} publication`);
|
|
8530
8615
|
const guards = /* @__PURE__ */ new Map();
|
|
8531
8616
|
let attachmentError;
|
|
8617
|
+
let expectedChildId;
|
|
8532
8618
|
let run;
|
|
8533
8619
|
const listener = host.on("agent/created", (({ agent }) => {
|
|
8534
|
-
if (startingChild$1.getStore() !== pending
|
|
8620
|
+
if (startingChild$1.getStore() !== pending) return;
|
|
8621
|
+
if (reserved ? agent.id !== expectedChildId || !isReservedChild(agents, parent, agent) : !agents.isOwnedBy(agent.id, parent)) return;
|
|
8535
8622
|
try {
|
|
8536
8623
|
const tools = agent.ctx?.tools;
|
|
8537
8624
|
if (typeof tools?.guard !== "function") {
|
|
8538
|
-
if (options.optional === true) return;
|
|
8625
|
+
if (options.optional === true && !reserved) return;
|
|
8539
8626
|
throw new Error(`Mnemon ${purpose} requires DSH scoped tool guard support`);
|
|
8540
8627
|
}
|
|
8541
8628
|
const dispose = tools.guard(guard);
|
|
@@ -8563,13 +8650,16 @@ async function startGuardedChild(host, parent, start, guard, options) {
|
|
|
8563
8650
|
if (failed.length) throw new AggregateError(failed.map((outcome) => outcome.reason), `Mnemon ${purpose} guard cleanup failed`);
|
|
8564
8651
|
};
|
|
8565
8652
|
try {
|
|
8566
|
-
run = await startingChild$1.run(pending,
|
|
8653
|
+
run = await startingChild$1.run(pending, () => reserved ? withReservedChild(parent, () => {
|
|
8654
|
+
expectedChildId = reservedChildId(parent);
|
|
8655
|
+
return start();
|
|
8656
|
+
}, true) : start());
|
|
8567
8657
|
if (attachmentError !== void 0) throw attachmentError;
|
|
8568
8658
|
const runId = run.id;
|
|
8569
8659
|
const child = run.localAgent ?? [...guards.keys()].find((agent) => agent.id === runId);
|
|
8570
8660
|
if (child === void 0 || !guards.has(child)) {
|
|
8571
|
-
const local = run.localAgent ?? agents
|
|
8572
|
-
if (options.optional === true && guards.size === 0 && typeof local?.ctx?.tools?.guard !== "function") {
|
|
8661
|
+
const local = run.localAgent ?? agents?.get?.(runId);
|
|
8662
|
+
if (!reserved && options.optional === true && guards.size === 0 && typeof local?.ctx?.tools?.guard !== "function") {
|
|
8573
8663
|
await closeObserver();
|
|
8574
8664
|
return run;
|
|
8575
8665
|
}
|
|
@@ -8719,10 +8809,13 @@ function continueAfterRefusal(agent) {
|
|
|
8719
8809
|
* that does not report creation leaves the child as it was.
|
|
8720
8810
|
*/
|
|
8721
8811
|
async function startWithContinuationTurns(host, parent, start) {
|
|
8812
|
+
const reserved = activationOwned(host.subagents);
|
|
8722
8813
|
const pending = Symbol("Mnemon delegated start");
|
|
8723
8814
|
const stops = [];
|
|
8815
|
+
let expectedChildId;
|
|
8724
8816
|
const listener = host.on("agent/created", (({ agent }) => {
|
|
8725
8817
|
if (startingChild.getStore() !== pending) return;
|
|
8818
|
+
if (reserved && (agent.id !== expectedChildId || !isReservedChild(host.agents, parent, agent))) return;
|
|
8726
8819
|
if (typeof host.agents?.isOwnedBy === "function" && !host.agents.isOwnedBy(agent.id, parent)) return;
|
|
8727
8820
|
for (const stop of continueAfterRefusal(agent)) if (typeof stop === "function") stops.push(stop);
|
|
8728
8821
|
}));
|
|
@@ -8731,7 +8824,10 @@ async function startWithContinuationTurns(host, parent, start) {
|
|
|
8731
8824
|
};
|
|
8732
8825
|
let run;
|
|
8733
8826
|
try {
|
|
8734
|
-
run = await startingChild.run(pending,
|
|
8827
|
+
run = await startingChild.run(pending, () => reserved ? withReservedChild(parent, () => {
|
|
8828
|
+
expectedChildId = reservedChildId(parent);
|
|
8829
|
+
return start();
|
|
8830
|
+
}) : start());
|
|
8735
8831
|
} catch (error) {
|
|
8736
8832
|
await release();
|
|
8737
8833
|
throw error;
|
|
@@ -8790,6 +8886,7 @@ function childComposition(subagents, provider) {
|
|
|
8790
8886
|
* step, which needs `publications`.
|
|
8791
8887
|
*/
|
|
8792
8888
|
async function startSubagent(subagents, agents, provider, request, publications) {
|
|
8889
|
+
if (typeof subagents.startActivation === "function" && reservedChildId(request.parent) === void 0) return withReservedChild(request.parent, () => startSubagent(subagents, agents, provider, request, publications));
|
|
8793
8890
|
const { toolFilter, persona, ...task } = request;
|
|
8794
8891
|
if (toolFilter === void 0 && persona === void 0 || childComposition(subagents, subagents.getProvider(provider)) !== "publication") return startOnHost(subagents, agents, provider, request);
|
|
8795
8892
|
if (publications === void 0) throw new Error("This DSH takes no subagent persona or tool filter at start, and dsh-mnemon cannot observe the child it publishes");
|
|
@@ -8797,14 +8894,26 @@ async function startSubagent(subagents, agents, provider, request, publications)
|
|
|
8797
8894
|
...toolFilter === void 0 ? {} : { toolFilter },
|
|
8798
8895
|
...persona === void 0 ? {} : { persona }
|
|
8799
8896
|
};
|
|
8800
|
-
return startComposed(publications, agents, request.parent, composition, () => startOnHost(subagents, agents, provider, task));
|
|
8897
|
+
return startComposed(publications, agents, request.parent, composition, () => startOnHost(subagents, agents, provider, task), activationOwned(subagents));
|
|
8801
8898
|
}
|
|
8802
8899
|
async function startOnHost(subagents, agents, provider, request) {
|
|
8803
8900
|
if (typeof subagents.startActivation === "function") {
|
|
8804
8901
|
const { label, signal, ...task } = request;
|
|
8805
|
-
const
|
|
8902
|
+
const modern = activationOwned(subagents);
|
|
8903
|
+
const childId = claimReservedChild(request.parent);
|
|
8904
|
+
if (modern && (childId === void 0 || agents?.get?.(request.parent.id) !== request.parent)) throw new Error("Mnemon requires an exact live parent and reserved child identity on an activation-owned DSH");
|
|
8905
|
+
const startCurrent = subagents.startActivation;
|
|
8906
|
+
const activation = modern ? await startCurrent.call(subagents, {
|
|
8907
|
+
...task,
|
|
8908
|
+
provider,
|
|
8909
|
+
label,
|
|
8910
|
+
signal,
|
|
8911
|
+
childId,
|
|
8912
|
+
delivery: "caller"
|
|
8913
|
+
}) : await subagents.startActivation({
|
|
8806
8914
|
provider,
|
|
8807
8915
|
label,
|
|
8916
|
+
...childId === void 0 ? {} : { childId },
|
|
8808
8917
|
request: task,
|
|
8809
8918
|
signal,
|
|
8810
8919
|
delivery: "caller"
|
|
@@ -8818,7 +8927,9 @@ async function startOnHost(subagents, agents, provider, request) {
|
|
|
8818
8927
|
activation.result.then(release, release);
|
|
8819
8928
|
if (signal.aborted) stop();
|
|
8820
8929
|
const child = agents?.get?.(activation.childId);
|
|
8821
|
-
|
|
8930
|
+
if (modern && (activation.childId !== childId || child === void 0 || !isReservedChild(agents, request.parent, child))) throw new Error("DSH did not return the reserved live Mnemon child");
|
|
8931
|
+
if (modern && child !== void 0) titleTask(child, label.startsWith("Mnemon ") ? label : `Mnemon · ${label}`);
|
|
8932
|
+
const localAgent = child !== void 0 && (modern || typeof agents?.isOwnedBy !== "function" || agents.isOwnedBy(child.id, request.parent)) ? child : void 0;
|
|
8822
8933
|
return {
|
|
8823
8934
|
id: activation.childId,
|
|
8824
8935
|
...localAgent === void 0 ? {} : { localAgent },
|
|
@@ -8858,12 +8969,14 @@ function compose(agent, { toolFilter, persona }) {
|
|
|
8858
8969
|
* check confirms the parent. A failed composition makes DSH roll the child
|
|
8859
8970
|
* back; a child that was not seen published is disposed and refused.
|
|
8860
8971
|
*/
|
|
8861
|
-
async function startComposed(publications, agents, parent, composition, start) {
|
|
8972
|
+
async function startComposed(publications, agents, parent, composition, start, reserved = false) {
|
|
8862
8973
|
const pending = Symbol("Mnemon child composition");
|
|
8974
|
+
const expectedChildId = reserved ? reservedChildId(parent) : void 0;
|
|
8863
8975
|
const composed = /* @__PURE__ */ new Set();
|
|
8864
8976
|
let failure;
|
|
8865
8977
|
const listener = publications.on("agent/created", (({ agent }) => {
|
|
8866
8978
|
if (composingChild.getStore() !== pending) return;
|
|
8979
|
+
if (reserved && (agent.id !== expectedChildId || !isReservedChild(agents, parent, agent))) return;
|
|
8867
8980
|
if (typeof agents?.isOwnedBy === "function" && !agents.isOwnedBy(agent.id, parent)) return;
|
|
8868
8981
|
try {
|
|
8869
8982
|
compose(agent, composition);
|
|
@@ -10332,6 +10445,7 @@ var AgentMemoryTurn = class {
|
|
|
10332
10445
|
agent;
|
|
10333
10446
|
runtime;
|
|
10334
10447
|
delegation;
|
|
10448
|
+
independent;
|
|
10335
10449
|
pinned;
|
|
10336
10450
|
/** A turn that runs without memory because no composition was serving when it began. */
|
|
10337
10451
|
unavailable;
|
|
@@ -10342,10 +10456,11 @@ var AgentMemoryTurn = class {
|
|
|
10342
10456
|
lastInspection;
|
|
10343
10457
|
lastWorkspace;
|
|
10344
10458
|
releaseDelegation;
|
|
10345
|
-
constructor(agent, runtime, delegation) {
|
|
10459
|
+
constructor(agent, runtime, delegation, independent = false) {
|
|
10346
10460
|
this.agent = agent;
|
|
10347
10461
|
this.runtime = runtime;
|
|
10348
10462
|
this.delegation = delegation;
|
|
10463
|
+
this.independent = independent;
|
|
10349
10464
|
if (delegation === void 0) return;
|
|
10350
10465
|
this.releaseDelegation = runtime.executions.retain(agent, delegation);
|
|
10351
10466
|
}
|
|
@@ -10437,7 +10552,7 @@ var AgentMemoryTurn = class {
|
|
|
10437
10552
|
}
|
|
10438
10553
|
}
|
|
10439
10554
|
async pin(turn, generation, signal) {
|
|
10440
|
-
const execution = await this.runtime.executions.turn(this.agent, turn, signal, this.delegation);
|
|
10555
|
+
const execution = await this.runtime.executions.turn(this.agent, turn, signal, this.delegation, this.independent);
|
|
10441
10556
|
const { graph, context } = execution;
|
|
10442
10557
|
try {
|
|
10443
10558
|
if (this.closed || this.generation !== generation) throw new Error("memory turn ended during View preparation");
|
|
@@ -10581,6 +10696,136 @@ var AutomaticReviewAdmission = class {
|
|
|
10581
10696
|
}
|
|
10582
10697
|
};
|
|
10583
10698
|
//#endregion
|
|
10699
|
+
//#region src/host/subagent-errors.ts
|
|
10700
|
+
/** A provider stop, kept separate from schema, startup and cancellation errors. */
|
|
10701
|
+
var SubagentStoppedError = class extends Error {
|
|
10702
|
+
stopReason;
|
|
10703
|
+
maxTokens;
|
|
10704
|
+
constructor(stopReason, maxTokens, detail) {
|
|
10705
|
+
super(`memory subagent stopped with ${stopReason}${detail === void 0 ? "" : `: ${detail}`}`);
|
|
10706
|
+
this.stopReason = stopReason;
|
|
10707
|
+
this.maxTokens = maxTokens;
|
|
10708
|
+
this.name = "SubagentStoppedError";
|
|
10709
|
+
}
|
|
10710
|
+
};
|
|
10711
|
+
//#endregion
|
|
10712
|
+
//#region src/host/task-continuation.ts
|
|
10713
|
+
const FINISHED_TASK_REFUSAL = "This Mnemon task has finished. Send a new user message in this conversation to continue working with memory.";
|
|
10714
|
+
const CONTINUATION_GUIDANCE = "This is a new user request in a completed Mnemon task conversation. The previous task stays completed. Use the current memory View and ordinary memory tools for this request; require receipts for changes. Do not repeat the previous task or submit its expired completion request.";
|
|
10715
|
+
/** Older workers have no reserved ID: require their own Host descriptor and task contract. */
|
|
10716
|
+
function isLegacyMemoryTask(agent) {
|
|
10717
|
+
if (agent.session.header?.origin !== "subagent") return false;
|
|
10718
|
+
const events = agent.session.snapshotEvents(agent.session.inheritedEventCount ?? 0);
|
|
10719
|
+
const descriptor = events.findLastIndex((event) => event.type === "subagent/descriptor");
|
|
10720
|
+
if (descriptor < 0 || typeof events[descriptor].data.label !== "string" || !events[descriptor].data.label.startsWith("Mnemon ")) return false;
|
|
10721
|
+
const own = events.slice(descriptor + 1);
|
|
10722
|
+
const textOf = (value) => {
|
|
10723
|
+
return value?.content?.filter((block) => block.type === "text").map((block) => block.text ?? "").join("\n") ?? "";
|
|
10724
|
+
};
|
|
10725
|
+
const prompt = own.find((event) => event.type === "user/message" && (event.data.message ?? event.data).source?.kind === "user");
|
|
10726
|
+
if (prompt === void 0 || !/^\[dsh-mnemon:delegated [a-z-]+\](?:\n|$)/u.test(textOf(prompt.data.message ?? prompt.data))) return false;
|
|
10727
|
+
return own.some((event) => event.type === "system/message" && textOf(event.data.message).includes("Completion protocol: call `mnemon_subagent_result` exactly once with requestId `"));
|
|
10728
|
+
}
|
|
10729
|
+
/** A resumed task receives memory authority only for a newly accepted human turn. */
|
|
10730
|
+
var TaskContinuation = class {
|
|
10731
|
+
agent;
|
|
10732
|
+
runtime;
|
|
10733
|
+
liveAgent;
|
|
10734
|
+
memory;
|
|
10735
|
+
authorizedTurn;
|
|
10736
|
+
stops = [];
|
|
10737
|
+
views = /* @__PURE__ */ new Map();
|
|
10738
|
+
closed = false;
|
|
10739
|
+
constructor(agent, runtime, liveAgent) {
|
|
10740
|
+
this.agent = agent;
|
|
10741
|
+
this.runtime = runtime;
|
|
10742
|
+
this.liveAgent = liveAgent;
|
|
10743
|
+
this.memory = new AgentMemoryTurn(agent, runtime, void 0, true);
|
|
10744
|
+
}
|
|
10745
|
+
start() {
|
|
10746
|
+
try {
|
|
10747
|
+
const guard = this.agent.ctx.tools?.guard?.((execution) => this.guard(execution));
|
|
10748
|
+
if (typeof guard !== "function") throw new Error("Task continuation requires a scoped memory tool guard");
|
|
10749
|
+
this.stops.push(guard);
|
|
10750
|
+
this.stops.push(this.agent.ctx.on("agent/pre-step", ((step, next) => this.preStep(step, next)), { prepend: true }));
|
|
10751
|
+
this.stops.push(this.agent.ctx.on("system-prompt/assemble", (async (_assembly, context, next) => {
|
|
10752
|
+
const assembly = await next();
|
|
10753
|
+
if (context.agent !== void 0 && context.agent !== this.agent) return assembly;
|
|
10754
|
+
const pin = this.memory.current;
|
|
10755
|
+
return applyMemoryViewGuidance(assembly, pin?.context.view, pin?.graph.config.routingGuidance);
|
|
10756
|
+
})));
|
|
10757
|
+
this.stops.push(this.agent.ctx.on("session/event", ((session, event) => {
|
|
10758
|
+
if (session === this.agent.session && event.type === "turn/end" && event.data.turn === this.authorizedTurn) this.end();
|
|
10759
|
+
})));
|
|
10760
|
+
return () => this.dispose();
|
|
10761
|
+
} catch (error) {
|
|
10762
|
+
this.dispose();
|
|
10763
|
+
throw error;
|
|
10764
|
+
}
|
|
10765
|
+
}
|
|
10766
|
+
ownsHumanTurn(actor) {
|
|
10767
|
+
return !this.closed && actor === this.agent && this.liveAgent(actor.id) === actor && this.authorizedTurn !== void 0 && this.memory.current?.turn === this.authorizedTurn && openAgentTurn(actor) === this.authorizedTurn;
|
|
10768
|
+
}
|
|
10769
|
+
guard(execution) {
|
|
10770
|
+
if (!execution.name?.startsWith("mnemon_")) return void 0;
|
|
10771
|
+
const actor = execution.agent;
|
|
10772
|
+
if (this.closed || actor === void 0 || this.liveAgent(actor.id) !== actor) return FINISHED_TASK_REFUSAL;
|
|
10773
|
+
if (actor !== this.agent) {
|
|
10774
|
+
try {
|
|
10775
|
+
const graph = this.runtime.forAgent(actor);
|
|
10776
|
+
const pin = graph.composableTurns.activeTurn(actor.id);
|
|
10777
|
+
if (pin !== void 0 && this.views.get(pin.view.id) === graph) return void 0;
|
|
10778
|
+
} catch {}
|
|
10779
|
+
return FINISHED_TASK_REFUSAL;
|
|
10780
|
+
}
|
|
10781
|
+
if (this.authorizedTurn === void 0) return FINISHED_TASK_REFUSAL;
|
|
10782
|
+
if (execution.name === "mnemon_subagent_result") return "The previous Mnemon task result is already settled. Use ordinary memory tools for the new user request.";
|
|
10783
|
+
if (this.memory.current?.turn !== this.authorizedTurn) return this.memory.unavailableReason ?? "Memory is unavailable for this request.";
|
|
10784
|
+
}
|
|
10785
|
+
async preStep(step, next) {
|
|
10786
|
+
const decision = await next();
|
|
10787
|
+
if (step.agent !== this.agent) return decision;
|
|
10788
|
+
if (decision.kind === "reject" || step.signal.aborted || this.closed || this.liveAgent(this.agent.id) !== this.agent) {
|
|
10789
|
+
this.end();
|
|
10790
|
+
return decision;
|
|
10791
|
+
}
|
|
10792
|
+
const starting = this.authorizedTurn !== step.turn;
|
|
10793
|
+
if (starting) this.end();
|
|
10794
|
+
if (decision.messages.some((message) => message.source.kind === "user" && message.content.some((block) => block.type !== "text" || (block.text?.trim().length ?? 0) > 0))) this.authorizedTurn = step.turn;
|
|
10795
|
+
if (this.authorizedTurn !== step.turn || openAgentTurn(this.agent) !== step.turn) return decision;
|
|
10796
|
+
try {
|
|
10797
|
+
await this.memory.begin(step.turn, step.signal);
|
|
10798
|
+
} catch (error) {
|
|
10799
|
+
this.end();
|
|
10800
|
+
throw error;
|
|
10801
|
+
}
|
|
10802
|
+
const pin = this.memory.current;
|
|
10803
|
+
for (const [id, graph] of this.views) if (graph.composableTurns.get(id) === void 0) this.views.delete(id);
|
|
10804
|
+
if (pin !== void 0) this.views.set(pin.context.view.id, pin.graph);
|
|
10805
|
+
if (!starting && step.step !== 1) return decision;
|
|
10806
|
+
const wake = pin === void 0 ? "" : modelMemoryWake(pin.graph, pin.context).text;
|
|
10807
|
+
return {
|
|
10808
|
+
...decision,
|
|
10809
|
+
messages: [...decision.messages, createPluginMessage(`${CONTINUATION_GUIDANCE}\n\n${wake}`, "instructions")]
|
|
10810
|
+
};
|
|
10811
|
+
}
|
|
10812
|
+
end() {
|
|
10813
|
+
this.authorizedTurn = void 0;
|
|
10814
|
+
this.memory.end();
|
|
10815
|
+
}
|
|
10816
|
+
dispose() {
|
|
10817
|
+
if (this.closed) return;
|
|
10818
|
+
this.closed = true;
|
|
10819
|
+
try {
|
|
10820
|
+
for (const stop of this.stops.splice(0).reverse()) stop();
|
|
10821
|
+
} finally {
|
|
10822
|
+
this.authorizedTurn = void 0;
|
|
10823
|
+
this.memory.dispose();
|
|
10824
|
+
this.views.clear();
|
|
10825
|
+
}
|
|
10826
|
+
}
|
|
10827
|
+
};
|
|
10828
|
+
//#endregion
|
|
10584
10829
|
//#region src/host/subagent.ts
|
|
10585
10830
|
function evidenceInsights(evidence) {
|
|
10586
10831
|
return evidence.items.map((item) => {
|
|
@@ -10626,7 +10871,6 @@ const REVIEW_TOOLS = [
|
|
|
10626
10871
|
const RESULT_TOOL_NAME = "mnemon_subagent_result";
|
|
10627
10872
|
/** How many finished delegated children stay refused memory tools if DSH resumes one. */
|
|
10628
10873
|
const FINISHED_CHILDREN = 1e3;
|
|
10629
|
-
const FINISHED_CHILD_REFUSAL = "This Mnemon task has finished, so it no longer reads or changes memory. Reply without memory tools.";
|
|
10630
10874
|
const RESULT_TOOL_INPUT_SCHEMA = {
|
|
10631
10875
|
type: "object",
|
|
10632
10876
|
properties: {
|
|
@@ -10763,8 +11007,13 @@ var MnemonSubagentCoordinator = class {
|
|
|
10763
11007
|
resultRequests = /* @__PURE__ */ new Map();
|
|
10764
11008
|
disposeResultTool;
|
|
10765
11009
|
disposeResumeGuard;
|
|
11010
|
+
disposeTaskNotices;
|
|
10766
11011
|
/** Delegated children whose run has ended, newest last, at most FINISHED_CHILDREN. */
|
|
10767
11012
|
finishedChildren = /* @__PURE__ */ new Set();
|
|
11013
|
+
continuations = /* @__PURE__ */ new Map();
|
|
11014
|
+
continuationOwners = /* @__PURE__ */ new WeakMap();
|
|
11015
|
+
providerNames = /* @__PURE__ */ new Set(["spawn", "fork"]);
|
|
11016
|
+
providerObservers = [];
|
|
10768
11017
|
disposed = false;
|
|
10769
11018
|
reviewAdmission = new AutomaticReviewAdmission();
|
|
10770
11019
|
constructor(subagents, runtimeSource, resultRuntime, taskAgentModelResolver, runtimeMaintenanceMaxTokensResolver, runtimeMaintenanceTaskRunner) {
|
|
@@ -10799,11 +11048,39 @@ var MnemonSubagentCoordinator = class {
|
|
|
10799
11048
|
});
|
|
10800
11049
|
if (typeof registration !== "function") throw new Error("dsh-mnemon subagent result tool registration did not return a disposer");
|
|
10801
11050
|
this.disposeResultTool = registration;
|
|
11051
|
+
const notices = resultRuntime.on("agent/pre-step", (async (step, next) => {
|
|
11052
|
+
const ignored = new Set(step.messages.filter((message) => {
|
|
11053
|
+
const source = message.source;
|
|
11054
|
+
return source.kind === "subagent-settled" && typeof source.senderSessionId === "string" && (isTaskRecord(source.senderSessionId) || this.finishedChildren.has(source.senderSessionId));
|
|
11055
|
+
}).map((message) => message.id));
|
|
11056
|
+
if (ignored.size === 0) return next();
|
|
11057
|
+
if (step.step === 1 && ignored.size === step.messages.length) return {
|
|
11058
|
+
kind: "enter",
|
|
11059
|
+
messages: []
|
|
11060
|
+
};
|
|
11061
|
+
const decision = await next();
|
|
11062
|
+
return decision.kind === "reject" ? decision : {
|
|
11063
|
+
...decision,
|
|
11064
|
+
messages: decision.messages.filter((message) => !ignored.has(message.id))
|
|
11065
|
+
};
|
|
11066
|
+
}), { prepend: true });
|
|
11067
|
+
if (typeof notices === "function") this.disposeTaskNotices = notices;
|
|
11068
|
+
if (typeof subagents.list !== "function") {
|
|
11069
|
+
for (const stop of [resultRuntime.on("subagent/provider-added", ((provider) => {
|
|
11070
|
+
this.providerNames.add(provider.name);
|
|
11071
|
+
})), resultRuntime.on("subagent/provider-removed", ((name) => {
|
|
11072
|
+
this.providerNames.delete(name);
|
|
11073
|
+
}))]) if (typeof stop === "function") this.providerObservers.push(stop);
|
|
11074
|
+
}
|
|
10802
11075
|
}
|
|
10803
11076
|
dispose() {
|
|
10804
11077
|
this.disposed = true;
|
|
10805
11078
|
this.reviewAdmission.dispose();
|
|
10806
11079
|
this.resultRequests.clear();
|
|
11080
|
+
this.disposeTaskNotices?.();
|
|
11081
|
+
this.disposeTaskNotices = void 0;
|
|
11082
|
+
for (const stop of [...this.continuations.values()].reverse()) stop();
|
|
11083
|
+
for (const stop of this.providerObservers.splice(0)) stop();
|
|
10807
11084
|
const resumeGuard = this.disposeResumeGuard;
|
|
10808
11085
|
this.disposeResumeGuard = void 0;
|
|
10809
11086
|
resumeGuard?.();
|
|
@@ -10814,10 +11091,68 @@ var MnemonSubagentCoordinator = class {
|
|
|
10814
11091
|
snapshot() {
|
|
10815
11092
|
return { ...this.counters };
|
|
10816
11093
|
}
|
|
11094
|
+
isFinishedTask(id, agent) {
|
|
11095
|
+
if (this.finishedChildren.has(id)) return true;
|
|
11096
|
+
if (agent === void 0 || agent.id !== id || !isLegacyMemoryTask(agent)) return false;
|
|
11097
|
+
this.finished(id);
|
|
11098
|
+
return true;
|
|
11099
|
+
}
|
|
11100
|
+
isUserContinuation(agent) {
|
|
11101
|
+
return this.continuationOwners.get(agent)?.ownsHumanTurn(agent) === true;
|
|
11102
|
+
}
|
|
11103
|
+
delegationLimit(parent) {
|
|
11104
|
+
if (!this.isUserContinuation(parent)) return 1;
|
|
11105
|
+
const depths = [parent.session.header?.delegationDepth ?? 0, parent.options?.subagentDepth ?? 0];
|
|
11106
|
+
if (depths.some((depth) => !Number.isSafeInteger(depth) || depth < 0 || Object.is(depth, -0) || depth === Number.MAX_SAFE_INTEGER)) throw new Error("Cannot determine a safe delegation depth for this continued task");
|
|
11107
|
+
return Math.max(...depths) + 1;
|
|
11108
|
+
}
|
|
11109
|
+
/** User continuation is a fresh scoped turn, never revival of a delegated run. */
|
|
11110
|
+
continueTask(agent) {
|
|
11111
|
+
if (this.continuations.has(agent) || this.disposed) return;
|
|
11112
|
+
if (typeof agent.ctx.effect !== "function" || this.resultRuntime?.agents?.get === void 0) {
|
|
11113
|
+
agent.ctx.tools?.guard?.((execution) => execution.name?.startsWith("mnemon_") ? FINISHED_TASK_REFUSAL : void 0);
|
|
11114
|
+
return;
|
|
11115
|
+
}
|
|
11116
|
+
const continuation = new TaskContinuation(agent, this.runtimeSource, (id) => this.resultRuntime?.agents?.get?.(id));
|
|
11117
|
+
let dispose;
|
|
11118
|
+
dispose = agent.ctx.effect(() => {
|
|
11119
|
+
const stop = continuation.start();
|
|
11120
|
+
this.continuationOwners.set(agent, continuation);
|
|
11121
|
+
return () => {
|
|
11122
|
+
try {
|
|
11123
|
+
stop();
|
|
11124
|
+
} finally {
|
|
11125
|
+
if (this.continuations.get(agent) === dispose) this.continuations.delete(agent);
|
|
11126
|
+
this.continuationOwners.delete(agent);
|
|
11127
|
+
}
|
|
11128
|
+
};
|
|
11129
|
+
}, "dsh-mnemon.task-continuation()");
|
|
11130
|
+
this.continuations.set(agent, dispose);
|
|
11131
|
+
}
|
|
11132
|
+
/** Spawn may use an independent tool scope, so transfer the turn guard explicitly. */
|
|
11133
|
+
inheritTaskContinuation(parent, child) {
|
|
11134
|
+
const owner = this.continuationOwners.get(parent);
|
|
11135
|
+
if (owner === void 0 || this.continuations.has(child)) return;
|
|
11136
|
+
let dispose;
|
|
11137
|
+
dispose = child.ctx.effect(() => {
|
|
11138
|
+
const stop = child.ctx.tools?.guard?.((execution) => owner.guard(execution));
|
|
11139
|
+
if (typeof stop !== "function") throw new Error("A continued task child requires a scoped memory tool guard");
|
|
11140
|
+
this.continuationOwners.set(child, owner);
|
|
11141
|
+
return () => {
|
|
11142
|
+
try {
|
|
11143
|
+
stop();
|
|
11144
|
+
} finally {
|
|
11145
|
+
if (this.continuations.get(child) === dispose) this.continuations.delete(child);
|
|
11146
|
+
this.continuationOwners.delete(child);
|
|
11147
|
+
}
|
|
11148
|
+
};
|
|
11149
|
+
}, "dsh-mnemon.task-delegation()");
|
|
11150
|
+
this.continuations.set(child, dispose);
|
|
11151
|
+
}
|
|
10817
11152
|
/**
|
|
10818
11153
|
* DSH 0.2.1 can resume a finished child from its saved state when another Agent sends it a
|
|
10819
|
-
* message: with its persona and tools, but without the guard its run held.
|
|
10820
|
-
*
|
|
11154
|
+
* message: with its persona and tools, but without the guard its run held. Only a fresh
|
|
11155
|
+
* human turn may acquire new authority; automatic continuations remain denied (#387).
|
|
10821
11156
|
*/
|
|
10822
11157
|
finished(id) {
|
|
10823
11158
|
this.finishedChildren.delete(id);
|
|
@@ -10826,9 +11161,7 @@ var MnemonSubagentCoordinator = class {
|
|
|
10826
11161
|
if (this.disposeResumeGuard !== void 0 || this.disposed || this.resultRuntime === void 0) return;
|
|
10827
11162
|
const resumed = this.resultRuntime.on("agent/created", (({ agent }) => {
|
|
10828
11163
|
if (!this.finishedChildren.has(agent.id)) return;
|
|
10829
|
-
|
|
10830
|
-
agent.ctx?.tools?.guard?.((execution) => execution.name?.startsWith("mnemon_") === true ? FINISHED_CHILD_REFUSAL : void 0);
|
|
10831
|
-
} catch {}
|
|
11164
|
+
this.continueTask(agent);
|
|
10832
11165
|
}));
|
|
10833
11166
|
if (typeof resumed === "function") this.disposeResumeGuard = resumed;
|
|
10834
11167
|
}
|
|
@@ -11267,8 +11600,8 @@ var MnemonSubagentCoordinator = class {
|
|
|
11267
11600
|
* One tool-less structured run for skill evolution: a review, a draft, a
|
|
11268
11601
|
* backtest step or a case derivation. The child sees only the prompt.
|
|
11269
11602
|
*/
|
|
11270
|
-
async skillTask(parent, label, prompt, schema, persona, signal, route) {
|
|
11271
|
-
const { provider, runId, result } = await this.delegate(parent, "skill", label, prompt, [], schema, signal, "spawn", persona, void 0, void 0, route);
|
|
11603
|
+
async skillTask(parent, label, prompt, schema, persona, signal, route, maxTokens) {
|
|
11604
|
+
const { provider, runId, result } = await this.delegate(parent, "skill", label, prompt, [], schema, signal, "spawn", persona, void 0, void 0, route, void 0, maxTokens);
|
|
11272
11605
|
return {
|
|
11273
11606
|
provider,
|
|
11274
11607
|
runId,
|
|
@@ -11429,9 +11762,9 @@ ${naturalRequest(request, target === void 0 ? REQUEST_LABELS : TARGETED_WRITE_LA
|
|
|
11429
11762
|
execution.release();
|
|
11430
11763
|
}
|
|
11431
11764
|
}
|
|
11432
|
-
async delegate(parent, operation, label, prompt, tools, outputSchema, signal, preferredProvider = "spawn", persona = WRITE_PERSONA, recovery, guard, route, admission) {
|
|
11765
|
+
async delegate(parent, operation, label, prompt, tools, outputSchema, signal, preferredProvider = "spawn", persona = WRITE_PERSONA, recovery, guard, route, admission, skillMaxTokens) {
|
|
11433
11766
|
if (this.disposed) throw new Error("dsh-mnemon subagent coordinator is disposed");
|
|
11434
|
-
const provider = this.provider(preferredProvider);
|
|
11767
|
+
const provider = this.provider(preferredProvider, this.runtimeSource.forAgent(parent).config.subagentProviderNames);
|
|
11435
11768
|
assertDshOutputSchema(outputSchema);
|
|
11436
11769
|
if (this.resultRuntime === void 0) throw new Error("dsh-mnemon subagent result tool runtime is unavailable");
|
|
11437
11770
|
const resultToolName = RESULT_TOOL_NAME;
|
|
@@ -11537,7 +11870,7 @@ ${naturalRequest(request, target === void 0 ? REQUEST_LABELS : TARGETED_WRITE_LA
|
|
|
11537
11870
|
Completion protocol: call \`${resultToolName}\` exactly once with requestId \`${requestId}\` and result matching this JSON schema:
|
|
11538
11871
|
${JSON.stringify(outputSchema)}
|
|
11539
11872
|
This is the only completion channel for this run. Do not finish with a plain-text answer. The requestId expires when this run finishes or is cancelled.`;
|
|
11540
|
-
const perOpMaxTokens = operation === "migration" || operation === "compaction" || operation === "reconcile" ? this.runtimeMaintenanceMaxTokensResolver?.() ?? 8192 : operation === "document-archive" ? 8192 : operation === "metadata-maintenance" ? 4096 : operation === "review" ? this.runtimeSource.config.idleReview.maxTokens : operation === "skill" ? 16384 : void 0;
|
|
11873
|
+
const perOpMaxTokens = operation === "migration" || operation === "compaction" || operation === "reconcile" ? this.runtimeMaintenanceMaxTokensResolver?.() ?? 8192 : operation === "document-archive" ? 8192 : operation === "metadata-maintenance" ? 4096 : operation === "review" ? this.runtimeSource.config.idleReview.maxTokens : operation === "skill" ? skillMaxTokens ?? 16384 : void 0;
|
|
11541
11874
|
const fixed = route ?? this.taskAgentModelResolver?.();
|
|
11542
11875
|
const baseAgentOptions = perOpMaxTokens === void 0 ? void 0 : { maxTokens: perOpMaxTokens };
|
|
11543
11876
|
const resolvedAgentOptions = fixed === void 0 ? baseAgentOptions : {
|
|
@@ -11560,7 +11893,7 @@ This is the only completion channel for this run. Do not finish with a plain-tex
|
|
|
11560
11893
|
parent,
|
|
11561
11894
|
signal,
|
|
11562
11895
|
...resolvedAgentOptions === void 0 ? {} : { agentOptions: resolvedAgentOptions },
|
|
11563
|
-
maxDepth:
|
|
11896
|
+
maxDepth: this.delegationLimit(parent),
|
|
11564
11897
|
toolFilter: { allow: [...this.availableTools(parent, tools), resultToolName] },
|
|
11565
11898
|
persona: completionPersona
|
|
11566
11899
|
}, host);
|
|
@@ -11576,11 +11909,11 @@ This is the only completion channel for this run. Do not finish with a plain-tex
|
|
|
11576
11909
|
if (captured !== void 0 && captured.agentId !== activeRun.id) throw new Error("Mnemon subagent result was recorded by a different child");
|
|
11577
11910
|
let structured = captured?.value ?? result.structured;
|
|
11578
11911
|
if (structured === void 0 && result.stopReason === "completed") structured = recoverStructuredResult(recovery, committedReceipts.filter((receipt) => receipt.agentId === activeRun.id));
|
|
11579
|
-
if (structured !== void 0) assertDshOutputValue(outputSchema, structured);
|
|
11580
11912
|
if (result.stopReason !== "completed") {
|
|
11581
11913
|
const detail = subagentFailureDetail(activeRun, result);
|
|
11582
|
-
throw new
|
|
11914
|
+
throw new SubagentStoppedError(result.stopReason, perOpMaxTokens, detail);
|
|
11583
11915
|
}
|
|
11916
|
+
if (structured !== void 0) assertDshOutputValue(outputSchema, structured);
|
|
11584
11917
|
if (structured === void 0) throw new Error("memory subagent completed without recording its result");
|
|
11585
11918
|
if (operation === "review" && [
|
|
11586
11919
|
"failed",
|
|
@@ -11644,8 +11977,12 @@ This is the only completion channel for this run. Do not finish with a plain-tex
|
|
|
11644
11977
|
this.counters.lastAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
11645
11978
|
return completed;
|
|
11646
11979
|
}
|
|
11647
|
-
provider(preferred) {
|
|
11648
|
-
const names = this.subagents.list()
|
|
11980
|
+
provider(preferred, explicitNames = []) {
|
|
11981
|
+
const names = this.subagents.list?.() ?? [.../* @__PURE__ */ new Set([
|
|
11982
|
+
...this.providerNames,
|
|
11983
|
+
...configuredProviderNames(this.resultRuntime),
|
|
11984
|
+
...explicitNames
|
|
11985
|
+
])].filter((name) => this.subagents.getProvider(name) !== void 0);
|
|
11649
11986
|
const compatible = (name) => {
|
|
11650
11987
|
const provider = this.subagents.getProvider(name);
|
|
11651
11988
|
return provider?.capabilities.depthLimit === true && childComposition(this.subagents, provider) !== void 0;
|
|
@@ -12765,7 +13102,7 @@ var MnemonLifecycle = class {
|
|
|
12765
13102
|
}
|
|
12766
13103
|
/** Model work for skill evolution under a fresh task Agent, outside any conversation. */
|
|
12767
13104
|
runSkillTask(workspaceRoot, signal, operation, route) {
|
|
12768
|
-
return this.runTaskAgent("", workspaceRoot, signal, operation, route);
|
|
13105
|
+
return this.runTaskAgent("", workspaceRoot, signal, operation, route, "Mnemon · Skills");
|
|
12769
13106
|
}
|
|
12770
13107
|
/**
|
|
12771
13108
|
* What one conversation did with skills, for the bars under its turns. A
|
|
@@ -12808,7 +13145,7 @@ var MnemonLifecycle = class {
|
|
|
12808
13145
|
const stopCreated = this.ctx.on("agent/created", (({ agent, source }) => {
|
|
12809
13146
|
this.install(agent, source);
|
|
12810
13147
|
}));
|
|
12811
|
-
for (const agent of this.ctx.agents.
|
|
13148
|
+
for (const agent of rootAgents(this.ctx.agents, this.ctx.subagents)) this.install(agent, "adopted");
|
|
12812
13149
|
return () => {
|
|
12813
13150
|
stopChanged?.();
|
|
12814
13151
|
stopCreated();
|
|
@@ -12988,7 +13325,7 @@ var MnemonLifecycle = class {
|
|
|
12988
13325
|
/** Synthesize a Web Agent Query without borrowing a conversation Agent or its history. */
|
|
12989
13326
|
answerTask(sessionId, query, evidence, workspaceRoot, signal = new AbortController().signal) {
|
|
12990
13327
|
const root = workspaceRoot?.trim() || this.workspaceRoot(sessionId);
|
|
12991
|
-
return this.runTaskAgent(sessionId, root, signal, (agent) => this.coordinator.answer(agent, query, evidence, signal));
|
|
13328
|
+
return this.runTaskAgent(sessionId, root, signal, (agent) => this.coordinator.answer(agent, query, evidence, signal), void 0, "Mnemon · Ask Agent");
|
|
12992
13329
|
}
|
|
12993
13330
|
/** A write the user sent from the page: a space they picked that is switched off comes back on (#387). */
|
|
12994
13331
|
remember(sessionId, request, signal = new AbortController().signal) {
|
|
@@ -13001,7 +13338,7 @@ var MnemonLifecycle = class {
|
|
|
13001
13338
|
return this.coordinator.manageSource(graph, request);
|
|
13002
13339
|
}
|
|
13003
13340
|
runRuntimeMaintenanceTask(scope, signal, operation) {
|
|
13004
|
-
return this.runTaskAgent(scope.sessionId ?? "", scope.workspaceId, signal, operation);
|
|
13341
|
+
return this.runTaskAgent(scope.sessionId ?? "", scope.workspaceId, signal, operation, void 0, "Mnemon · Memory maintenance");
|
|
13005
13342
|
}
|
|
13006
13343
|
/**
|
|
13007
13344
|
* Read the merged memory and let a model propose what a human should review.
|
|
@@ -13030,12 +13367,12 @@ var MnemonLifecycle = class {
|
|
|
13030
13367
|
mutateDocumentTask(sessionId, request, workspaceRoot, signal = new AbortController().signal) {
|
|
13031
13368
|
const root = workspaceRoot?.trim() || this.workspaceRoot(sessionId);
|
|
13032
13369
|
if (root === void 0 || root.trim() === "") throw new Error("a selected DSH workspace is required to write a Mnemon Document");
|
|
13033
|
-
return this.runTaskAgent(sessionId, root, signal, (agent) => this.coordinator.document(agent, request, signal));
|
|
13370
|
+
return this.runTaskAgent(sessionId, root, signal, (agent) => this.coordinator.document(agent, request, signal), void 0, "Mnemon · Document");
|
|
13034
13371
|
}
|
|
13035
13372
|
archiveDocument(sessionId, id, workspaceRoot, signal = new AbortController().signal) {
|
|
13036
13373
|
const root = workspaceRoot?.trim() || this.workspaceRoot(sessionId);
|
|
13037
13374
|
if (root === void 0 || root.trim() === "") throw new Error("a selected DSH workspace is required to archive a Mnemon Document");
|
|
13038
|
-
return this.runTaskAgent(sessionId, root, signal, (agent) => this.coordinator.archiveDocument(agent, id, signal));
|
|
13375
|
+
return this.runTaskAgent(sessionId, root, signal, (agent) => this.coordinator.archiveDocument(agent, id, signal), void 0, "Mnemon · Archive Document");
|
|
13039
13376
|
}
|
|
13040
13377
|
mutate(sessionId, operation, request, signal = new AbortController().signal) {
|
|
13041
13378
|
return this.coordinator.write(this.liveAgent(sessionId), operation, request, signal);
|
|
@@ -13046,11 +13383,11 @@ var MnemonLifecycle = class {
|
|
|
13046
13383
|
/** Choose a new Memory Space's Provider under a fresh task Agent, as Ask Agent does without a loaded conversation Agent. */
|
|
13047
13384
|
placeProviderTask(sessionId, body, prepared, workspaceRoot, signal = new AbortController().signal) {
|
|
13048
13385
|
const root = workspaceRoot?.trim() || this.workspaceRoot(sessionId);
|
|
13049
|
-
return this.runTaskAgent(sessionId, root, signal, (agent) => this.coordinator.placeProvider(agent, body, prepared, signal));
|
|
13386
|
+
return this.runTaskAgent(sessionId, root, signal, (agent) => this.coordinator.placeProvider(agent, body, prepared, signal), void 0, "Mnemon · Choose memory provider");
|
|
13050
13387
|
}
|
|
13051
13388
|
maintainMetadata(sessionId, memoryBodyIds, workspaceRoot, signal = new AbortController().signal) {
|
|
13052
13389
|
const root = workspaceRoot?.trim() || this.workspaceRoot(sessionId);
|
|
13053
|
-
return this.runTaskAgent(sessionId, root, signal, (agent) => this.coordinator.maintainMetadata(agent, memoryBodyIds, signal));
|
|
13390
|
+
return this.runTaskAgent(sessionId, root, signal, (agent) => this.coordinator.maintainMetadata(agent, memoryBodyIds, signal), void 0, "Mnemon · Memory metadata");
|
|
13054
13391
|
}
|
|
13055
13392
|
async supervise(sessionId, content, idempotencyKey, signal = new AbortController().signal) {
|
|
13056
13393
|
const normalizedSessionId = sessionId.trim();
|
|
@@ -13062,7 +13399,7 @@ var MnemonLifecycle = class {
|
|
|
13062
13399
|
const normalizedSessionId = sessionId.trim();
|
|
13063
13400
|
const root = workspaceRoot?.trim() || this.workspaceRoot(normalizedSessionId);
|
|
13064
13401
|
const scopeKey = root === void 0 ? `task:${normalizedSessionId || "global"}` : `task:${resolve(root)}`;
|
|
13065
|
-
return this.superviseResolved(scopeKey, normalizedSessionId, content, idempotencyKey, signal, (operation) => this.runTaskAgent(normalizedSessionId, root, signal, operation));
|
|
13402
|
+
return this.superviseResolved(scopeKey, normalizedSessionId, content, idempotencyKey, signal, (operation) => this.runTaskAgent(normalizedSessionId, root, signal, operation, void 0, "Mnemon · Save to memory"));
|
|
13066
13403
|
}
|
|
13067
13404
|
async superviseResolved(replayScope, responseSessionId, content, idempotencyKey, signal, withAgent) {
|
|
13068
13405
|
if (!this.config.writeEnabled) throw new Error("dsh-mnemon is configured read-only (writeEnabled: false)");
|
|
@@ -13116,8 +13453,9 @@ var MnemonLifecycle = class {
|
|
|
13116
13453
|
* is the explicit Web workbench scope, so LiveMnemonRuntime resolves the same
|
|
13117
13454
|
* workspace graph without borrowing conversation history or ownership.
|
|
13118
13455
|
*/
|
|
13119
|
-
async runTaskAgent(fallbackSessionId, workspaceRoot, signal, operation, route) {
|
|
13120
|
-
const
|
|
13456
|
+
async runTaskAgent(fallbackSessionId, workspaceRoot, signal, operation, route, title = "Mnemon · Background task") {
|
|
13457
|
+
const modern = activationOwned(this.ctx.subagents);
|
|
13458
|
+
const sessionId = `mnemon-task-v1-${randomUUID()}`;
|
|
13121
13459
|
this.taskAgentIds.add(sessionId);
|
|
13122
13460
|
let handle;
|
|
13123
13461
|
let failure;
|
|
@@ -13128,6 +13466,7 @@ var MnemonLifecycle = class {
|
|
|
13128
13466
|
...creation,
|
|
13129
13467
|
signal
|
|
13130
13468
|
});
|
|
13469
|
+
if (modern) titleTask(handle.agent, title);
|
|
13131
13470
|
if (route !== void 0) try {
|
|
13132
13471
|
handle.agent[TASK_ROUTE] = route;
|
|
13133
13472
|
} catch {}
|
|
@@ -13153,7 +13492,9 @@ var MnemonLifecycle = class {
|
|
|
13153
13492
|
* a turn only while DSH's projection cache holds a record of it, so a finished task
|
|
13154
13493
|
* could stay listed as an untitled Ungrouped conversation (#435). No `parentSession`
|
|
13155
13494
|
* or `delegationDepth`: the task belongs to no conversation, and its children stay
|
|
13156
|
-
* one level deep.
|
|
13495
|
+
* one level deep. Activation-owned master requires an ordinary root instead;
|
|
13496
|
+
* its persistent task ID and title identify the visible record without enrolling
|
|
13497
|
+
* it in conversation automation. Official rc.1 retains the hidden metadata.
|
|
13157
13498
|
*/
|
|
13158
13499
|
async taskAgentCreation(fallbackSessionId, workspaceRoot, signal, route) {
|
|
13159
13500
|
const baseOptions = this.taskAgentModelOptions(fallbackSessionId, workspaceRoot);
|
|
@@ -13171,7 +13512,7 @@ var MnemonLifecycle = class {
|
|
|
13171
13512
|
const workingDirectory = workFrom === void 0 ? void 0 : this.ctx.get("workingDirectory");
|
|
13172
13513
|
const meta = {
|
|
13173
13514
|
cwd,
|
|
13174
|
-
origin: "subagent",
|
|
13515
|
+
...activationOwned(this.ctx.subagents) ? {} : { origin: "subagent" },
|
|
13175
13516
|
...presetId === void 0 ? {} : { agentPreset: presetId }
|
|
13176
13517
|
};
|
|
13177
13518
|
if (presets === void 0 && typeof workingDirectory?.set !== "function") return {
|
|
@@ -13309,11 +13650,15 @@ var MnemonLifecycle = class {
|
|
|
13309
13650
|
}
|
|
13310
13651
|
install(agent, source) {
|
|
13311
13652
|
if (this.taskAgentIds.has(agent.id) || this.owners.has(agent) || this.children.has(agent)) return;
|
|
13653
|
+
if ((isTaskRecord(agent.id) || this.coordinator.isFinishedTask(agent.id, agent)) && !isCreatingChild(this.ctx.agents, agent)) {
|
|
13654
|
+
this.coordinator.continueTask(agent);
|
|
13655
|
+
return;
|
|
13656
|
+
}
|
|
13312
13657
|
if (agent.session.header?.origin === "subagent") {
|
|
13313
13658
|
this.installChild(agent);
|
|
13314
13659
|
return;
|
|
13315
13660
|
}
|
|
13316
|
-
if (!this.ctx.agents.
|
|
13661
|
+
if (!isRootAgent(this.ctx.agents, this.ctx.subagents, agent)) return;
|
|
13317
13662
|
const memoryTurn = this.runtimeSource === void 0 ? void 0 : new AgentMemoryTurn(agent, this.runtimeSource);
|
|
13318
13663
|
const lifecycle = new MnemonAgentLifecycle(agent, this.coordinator, this.config, this.counters, source, memoryTurn, () => this.runtimeSource?.forAgent(agent).directory);
|
|
13319
13664
|
let dispose;
|
|
@@ -13343,6 +13688,7 @@ var MnemonLifecycle = class {
|
|
|
13343
13688
|
const parentId = agent.session.header?.parentSession?.trim();
|
|
13344
13689
|
const parent = parentId === void 0 || parentId === "" ? void 0 : this.ctx.agents.get(parentId);
|
|
13345
13690
|
if (runtime === void 0 || parent === void 0 || parent === agent) return;
|
|
13691
|
+
this.coordinator.inheritTaskContinuation(parent, agent);
|
|
13346
13692
|
const parentMemory = this.memoryTurns.get(parent);
|
|
13347
13693
|
let delegation;
|
|
13348
13694
|
if (parentMemory !== void 0) delegation = parentMemory.delegate();
|
|
@@ -14606,10 +14952,30 @@ var SkillEvolution = class {
|
|
|
14606
14952
|
const settings = this.host.settings();
|
|
14607
14953
|
const { pack, targetRoot, guidance } = prepared;
|
|
14608
14954
|
let prompt = skillDraftPrompt(pack, guidance, targetRoot);
|
|
14955
|
+
let maxTokens = settings.draftMaxTokens;
|
|
14956
|
+
const attemptedBudgets = [];
|
|
14609
14957
|
let draft;
|
|
14610
14958
|
for (let attempt = 0; draft === void 0; attempt++) {
|
|
14611
|
-
|
|
14959
|
+
signal.throwIfAborted();
|
|
14960
|
+
attemptedBudgets.push(maxTokens);
|
|
14961
|
+
let answer;
|
|
14962
|
+
try {
|
|
14963
|
+
answer = await this.host.runTask(workspace, signal, (task) => this.host.skillTask(task, "Mnemon skill draft", prompt, SKILL_DRAFT_SCHEMA, SKILL_DRAFT_PERSONA, signal, input.route, maxTokens), input.route);
|
|
14964
|
+
signal.throwIfAborted();
|
|
14965
|
+
} catch (error) {
|
|
14966
|
+
signal.throwIfAborted();
|
|
14967
|
+
if (error instanceof SubagentStoppedError && error.maxTokens !== void 0) attemptedBudgets[attemptedBudgets.length - 1] = error.maxTokens;
|
|
14968
|
+
if (error instanceof SubagentStoppedError && error.stopReason === "max-tokens" && attempt === 0 && settings.draftRetryMaxTokens > maxTokens) {
|
|
14969
|
+
maxTokens = settings.draftRetryMaxTokens;
|
|
14970
|
+
prompt += "\n\nThe previous attempt exhausted its output budget and was discarded. Return a complete SKILL.md from the beginning; keep notes and changes concise.";
|
|
14971
|
+
continue;
|
|
14972
|
+
}
|
|
14973
|
+
const bytes = Buffer.byteLength(pack.skill?.content ?? "", "utf8");
|
|
14974
|
+
throw new Error(`Skill draft failed. Attempted budgets: ${attemptedBudgets.join(", ")} tokens; source SKILL.md: ${bytes} bytes (UTF-8). Adjust skills.draftMaxTokens / skills.draftRetryMaxTokens in Plugins → dsh-mnemon → Skills → Draft generation. Stay within provider/model caps: lower rejected budgets, shorten the skill or use a model with a higher output cap. Reason: ${message(error).slice(0, 100)}`, { cause: error });
|
|
14975
|
+
}
|
|
14976
|
+
const parsed = parseSkillDraft(answer.structured);
|
|
14612
14977
|
try {
|
|
14978
|
+
signal.throwIfAborted();
|
|
14613
14979
|
draft = await source.mutate("draft-record", {
|
|
14614
14980
|
...input.suggestionId === void 0 ? {} : { suggestionId: input.suggestionId },
|
|
14615
14981
|
skillName: pack.skillName,
|
|
@@ -14620,6 +14986,7 @@ var SkillEvolution = class {
|
|
|
14620
14986
|
...pack.action === "create" ? { targetRoot } : {}
|
|
14621
14987
|
}, signal);
|
|
14622
14988
|
} catch (error) {
|
|
14989
|
+
signal.throwIfAborted();
|
|
14623
14990
|
if (attempt > 0) throw error;
|
|
14624
14991
|
prompt += `\n\nYour previous SKILL.md was rejected: ${message(error)}. Return a corrected complete file.`;
|
|
14625
14992
|
}
|
|
@@ -16415,7 +16782,7 @@ function registerDocumentTools(ctx, { requireSource, config, sourceAction }, coo
|
|
|
16415
16782
|
const agent = requireAgent(exec);
|
|
16416
16783
|
if (args.action === "archive") {
|
|
16417
16784
|
requireSource(exec, "documents", "archive");
|
|
16418
|
-
if (isSubagent(agent)) throw new Error("idle document workers cannot cold-archive directly");
|
|
16785
|
+
if (isSubagent(agent) && !coordinator.isUserContinuation(agent)) throw new Error("idle document workers cannot cold-archive directly");
|
|
16419
16786
|
if (args.id === void 0) throw new Error("document id is required for archive");
|
|
16420
16787
|
return Promise.resolve(coordinator.archiveDocument(agent, args.id, exec.signal)).then(documentReceipt);
|
|
16421
16788
|
}
|
|
@@ -18885,7 +19252,7 @@ function apply(rawContext, rawConfig = {}) {
|
|
|
18885
19252
|
settings: () => skillSettings.get(),
|
|
18886
19253
|
source: (agent) => skillsSourceFor(runtime, agent),
|
|
18887
19254
|
runTask: (workspaceRoot, signal, operation, route) => lifecycle.runSkillTask(workspaceRoot, signal, operation, route),
|
|
18888
|
-
skillTask: (parent, label, prompt, schema, persona, signal) => coordinator.skillTask(parent, label, prompt, schema, persona, signal, taskRoute(parent))
|
|
19255
|
+
skillTask: (parent, label, prompt, schema, persona, signal, _route, maxTokens) => coordinator.skillTask(parent, label, prompt, schema, persona, signal, taskRoute(parent), maxTokens)
|
|
18889
19256
|
});
|
|
18890
19257
|
lifecycle.useSkillEvolution(skills);
|
|
18891
19258
|
ctx.effect(() => {
|
|
@@ -17,7 +17,7 @@ var dependencies = {
|
|
|
17
17
|
"dsh-mnemon-source-documents": "0.5.13",
|
|
18
18
|
"dsh-mnemon-source-memory-spaces": "0.5.25",
|
|
19
19
|
"dsh-mnemon-source-runtime": "0.5.17",
|
|
20
|
-
"dsh-mnemon-source-skills": "0.5.
|
|
20
|
+
"dsh-mnemon-source-skills": "0.5.8",
|
|
21
21
|
"dsh-mnemon-strategy-auto-capture": "0.5.5",
|
|
22
22
|
"dsh-mnemon-strategy-default-three-tier": "0.5.12",
|
|
23
23
|
"dsh-mnemon-strategy-general": "0.5.1",
|
package/lib/starter.js
CHANGED
|
@@ -793,6 +793,10 @@ export declare const zh: {
|
|
|
793
793
|
'skills.autoBacktest': string;
|
|
794
794
|
'skills.autoBacktestHint': string;
|
|
795
795
|
'skills.parameters': string;
|
|
796
|
+
'skills.draftGeneration': string;
|
|
797
|
+
'skills.draftMaxTokens': string;
|
|
798
|
+
'skills.draftRetryMaxTokens': string;
|
|
799
|
+
'skills.draftBudgetHint': string;
|
|
796
800
|
'skills.reviewThreshold': string;
|
|
797
801
|
'skills.idleSeconds': string;
|
|
798
802
|
'skills.cooldownSeconds': string;
|
|
@@ -307,6 +307,8 @@ export interface Config {
|
|
|
307
307
|
persistenceStrategy?: MemoryPersistenceStrategy;
|
|
308
308
|
/** Model route used by clean, session-independent maintenance Agents. */
|
|
309
309
|
taskAgentModel?: TaskAgentModelConfig;
|
|
310
|
+
/** Additional provider names for Hosts without enumeration and opaque provider plugins. */
|
|
311
|
+
subagentProviderNames?: string[];
|
|
310
312
|
/**
|
|
311
313
|
* Whether this profile runs Git repository sync at all. It lives here rather than
|
|
312
314
|
* in the data directory because the settings page has to draw the block without
|
|
@@ -367,6 +369,7 @@ export interface ResolvedConfig {
|
|
|
367
369
|
};
|
|
368
370
|
persistenceStrategy: ResolvedMemoryPersistenceStrategy;
|
|
369
371
|
taskAgentModel: ResolvedTaskAgentModelConfig;
|
|
372
|
+
subagentProviderNames: string[];
|
|
370
373
|
syncEnabled: boolean;
|
|
371
374
|
}
|
|
372
375
|
export interface ResolvedInteractionConfig {
|
|
@@ -386,6 +389,10 @@ export interface ResolvedSkillsConfig {
|
|
|
386
389
|
targetScope: 'storage' | 'user' | 'project';
|
|
387
390
|
/** Backtest a draft against the current version as soon as it is written. */
|
|
388
391
|
autoBacktest: boolean;
|
|
392
|
+
/** Output budget for a complete skill draft, including model reasoning. */
|
|
393
|
+
draftMaxTokens: number;
|
|
394
|
+
/** One fresh attempt after truncation, only when larger than draftMaxTokens. */
|
|
395
|
+
draftRetryMaxTokens: number;
|
|
389
396
|
/** The one-line skills bar under a finished turn. */
|
|
390
397
|
hints: boolean;
|
|
391
398
|
/** 技能管理 as a sidebar entry of its own instead of a Memory System page. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-mnemon",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.41",
|
|
4
4
|
"description": "Composable, view-based context for DeepSeek Harness. Pluggable sources and strategies, with layered memory and self-evolving skills out of the box.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"deepseek-harness",
|
|
@@ -167,7 +167,7 @@
|
|
|
167
167
|
"dsh-mnemon-source-documents": "0.5.13",
|
|
168
168
|
"dsh-mnemon-source-memory-spaces": "0.5.25",
|
|
169
169
|
"dsh-mnemon-source-runtime": "0.5.17",
|
|
170
|
-
"dsh-mnemon-source-skills": "0.5.
|
|
170
|
+
"dsh-mnemon-source-skills": "0.5.8",
|
|
171
171
|
"dsh-mnemon-strategy-auto-capture": "0.5.5",
|
|
172
172
|
"dsh-mnemon-strategy-default-three-tier": "0.5.12",
|
|
173
173
|
"dsh-mnemon-strategy-general": "0.5.1",
|