dsh-plugin-prompt-tool 3.1.1 → 3.1.2
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/engine/layers.mjs +108 -13
- package/engine/rule-runtime.d.mts +6 -0
- package/engine/rule-runtime.mjs +233 -95
- package/lib/client.js.map +1 -1
- package/lib/index.mjs +884 -329
- package/package.json +1 -1
package/lib/index.mjs
CHANGED
|
@@ -10475,7 +10475,7 @@ function officialAliasOf(name) {
|
|
|
10475
10475
|
* 非法官方名(中文/大写/连字符)改写成确定性别名并改写文本引用;注册失败的名字退回静态解析。
|
|
10476
10476
|
* @returns 各配置独立的引用白名单与别名;同一作用域内等价绑定只注册一次。
|
|
10477
10477
|
*/
|
|
10478
|
-
function registerOfficialVariables(ctx, configs, warnOnce, keep) {
|
|
10478
|
+
function registerOfficialVariables(ctx, configs, warnOnce, keep, shared) {
|
|
10479
10479
|
const registries = new Map(configs.map((config) => [config, {
|
|
10480
10480
|
protect: /* @__PURE__ */ new Set(),
|
|
10481
10481
|
alias: /* @__PURE__ */ new Map(),
|
|
@@ -10497,8 +10497,9 @@ function registerOfficialVariables(ctx, configs, warnOnce, keep) {
|
|
|
10497
10497
|
}
|
|
10498
10498
|
}
|
|
10499
10499
|
for (const fact of facts) reserved.add(fact);
|
|
10500
|
-
const bindings = /* @__PURE__ */ new Map();
|
|
10501
|
-
const usedNames = /* @__PURE__ */ new Set();
|
|
10500
|
+
const bindings = shared?.bindings ?? /* @__PURE__ */ new Map();
|
|
10501
|
+
const usedNames = shared?.usedNames ?? /* @__PURE__ */ new Set();
|
|
10502
|
+
const retained = /* @__PURE__ */ new Set();
|
|
10502
10503
|
for (const [config, referenced] of references) {
|
|
10503
10504
|
const registry = registries.get(config);
|
|
10504
10505
|
for (const name of referenced) {
|
|
@@ -10522,20 +10523,34 @@ function registerOfficialVariables(ctx, configs, warnOnce, keep) {
|
|
|
10522
10523
|
usedNames.add(official);
|
|
10523
10524
|
const source = isFact ? name.toLowerCase() : name;
|
|
10524
10525
|
const variablesDisabled = config[SESSION_VARIABLES_DISABLED] === true;
|
|
10525
|
-
|
|
10526
|
+
const release = systemPrompt.variable(official, (context) => {
|
|
10526
10527
|
const session = context?.agent?.session;
|
|
10527
10528
|
const variables = variablesDisabled ? {} : config.variableStore?.read(config.sourceModuleId).effective ?? config.variables;
|
|
10528
10529
|
return officialChannelText(interpolateVariables(Object.hasOwn(variables, source) ? String(variables[source]) : runtimeFactValue(source, session) ?? "", variables, session, void 0, `variable:${config.sourceModuleId}:${config.id}:${name}`), `variable ${official}`, {
|
|
10529
10530
|
alias: /* @__PURE__ */ new Map(),
|
|
10530
10531
|
registered: /* @__PURE__ */ new Set()
|
|
10531
10532
|
}, warnOnce);
|
|
10532
|
-
})
|
|
10533
|
-
binding =
|
|
10533
|
+
});
|
|
10534
|
+
binding = {
|
|
10535
|
+
name: official,
|
|
10536
|
+
release,
|
|
10537
|
+
refs: 0
|
|
10538
|
+
};
|
|
10534
10539
|
bindings.set(signature, binding);
|
|
10535
10540
|
}
|
|
10536
|
-
|
|
10541
|
+
if (!retained.has(signature)) {
|
|
10542
|
+
retained.add(signature);
|
|
10543
|
+
binding.refs++;
|
|
10544
|
+
keep(() => {
|
|
10545
|
+
if (--binding.refs > 0) return;
|
|
10546
|
+
bindings.delete(signature);
|
|
10547
|
+
usedNames.delete(binding.name);
|
|
10548
|
+
binding.release?.();
|
|
10549
|
+
}, `${name}: official prompt variable ${binding.name}`);
|
|
10550
|
+
}
|
|
10551
|
+
registry.registered.add(binding.name);
|
|
10537
10552
|
registry.protect.add(name);
|
|
10538
|
-
if (binding !== name) registry.alias.set(name, binding);
|
|
10553
|
+
if (binding.name !== name) registry.alias.set(name, binding.name);
|
|
10539
10554
|
} catch (error) {
|
|
10540
10555
|
warnOnce(`${name}: 官方 prompt 变量 ${official} 注册失败,该引用退回静态解析:${String(error?.message ?? error)}`);
|
|
10541
10556
|
}
|
|
@@ -10575,7 +10590,7 @@ function textLayerGroups(configs) {
|
|
|
10575
10590
|
for (const config of sorted) {
|
|
10576
10591
|
const previous = groups.at(-1);
|
|
10577
10592
|
const base = previous?.[0];
|
|
10578
|
-
if (config.mergeMode === "merged" && base?.mergeMode === "merged" && config.sourceModuleId === base.sourceModuleId && config.params?.complete === true === (base.params?.complete === true) && config.params?.suppressRuntimeContext === true === (base.params?.suppressRuntimeContext === true) && config.position === base.position && config.order === base.order) previous.push(config);
|
|
10593
|
+
if (config.mergeMode === "merged" && base?.mergeMode === "merged" && config.sourceModuleId === base.sourceModuleId && config.params?.complete === true === (base.params?.complete === true) && config.params?.suppressRuntimeContext === true === (base.params?.suppressRuntimeContext === true) && config.runtimePoint?.waterfallPosition === base.runtimePoint?.waterfallPosition && config.position === base.position && config.order === base.order) previous.push(config);
|
|
10579
10594
|
else groups.push([config]);
|
|
10580
10595
|
}
|
|
10581
10596
|
return groups;
|
|
@@ -11059,9 +11074,9 @@ function orderedNamesOf(entries) {
|
|
|
11059
11074
|
* 回填到它们原来的槽位。只换本插件段之间的位置:平台段与其他插件段占住的槽位不动。
|
|
11060
11075
|
*/
|
|
11061
11076
|
function registerDeliveryOrder(ctx, keep, collection, names) {
|
|
11062
|
-
if (names.length < 2) return;
|
|
11063
|
-
const rank = new Map(names.map((entryName, index) => [entryName, index]));
|
|
11077
|
+
if (typeof names !== "function" && names.length < 2) return;
|
|
11064
11078
|
keep(ctx.on("system-prompt/assemble", async (assembly, context, next) => {
|
|
11079
|
+
const rank = new Map((typeof names === "function" ? names() : names).map((entryName, index) => [entryName, index]));
|
|
11065
11080
|
const result = await next();
|
|
11066
11081
|
const list = result?.[collection];
|
|
11067
11082
|
if (!Array.isArray(list)) return result;
|
|
@@ -11117,11 +11132,11 @@ function wireLayers(ctx, configs, warnOnce, options = {}) {
|
|
|
11117
11132
|
};
|
|
11118
11133
|
try {
|
|
11119
11134
|
/** 实际注册名与序号:重排器只认这里,不从 configs 反推。 */
|
|
11120
|
-
const ordered = {
|
|
11135
|
+
const ordered = options.ordered ?? {
|
|
11121
11136
|
sections: [],
|
|
11122
11137
|
contexts: []
|
|
11123
11138
|
};
|
|
11124
|
-
const registry = registerOfficialVariables(ctx, configs.filter((config) => config.layer === "system-section" || config.layer === "runtime-context"), warnOnce, keep);
|
|
11139
|
+
const registry = registerOfficialVariables(ctx, configs.filter((config) => config.layer === "system-section" || config.layer === "runtime-context"), warnOnce, keep, options.sharedVariables);
|
|
11125
11140
|
const conditional = configs.filter((config) => ["system-section", "runtime-context"].includes(config.layer) && (typeof config.rule?.when === "function" || typeof config.actionWhen === "function" || (config.rule !== void 0 || config.params?.templateEvaluation === true) && config.params?.complete !== true && config.params?.suppressRuntimeContext !== true));
|
|
11126
11141
|
const regular = configs.filter((config) => !conditional.includes(config));
|
|
11127
11142
|
wireSystemSections(ctx, regular.filter((config) => config.layer === "system-section"), registry, warnOnce, keep, ordered, options.sourceError);
|
|
@@ -11129,13 +11144,113 @@ function wireLayers(ctx, configs, warnOnce, options = {}) {
|
|
|
11129
11144
|
wireRuleTextContributions(ctx, conditional, registry, warnOnce, keep, on, ordered, options.sourceError);
|
|
11130
11145
|
wireTurnStops(ctx, configs.filter((config) => config.layer === "turn-stop"), warnOnce, on, options.turnStopBudgets);
|
|
11131
11146
|
wireSubagentEvents(ctx, configs.filter((config) => config.layer === "subagent-start" || config.layer === "subagent-end"), warnOnce, on);
|
|
11132
|
-
for (const collection of ["sections", "contexts"]) registerDeliveryOrder(ctx, keep, collection, orderedNamesOf(ordered[collection]));
|
|
11147
|
+
for (const collection of options.deliveryOrder === false ? [] : ["sections", "contexts"]) registerDeliveryOrder(ctx, keep, collection, orderedNamesOf(ordered[collection]));
|
|
11133
11148
|
return dispose;
|
|
11134
11149
|
} catch (error) {
|
|
11135
11150
|
dispose();
|
|
11136
11151
|
throw error;
|
|
11137
11152
|
}
|
|
11138
11153
|
}
|
|
11154
|
+
/** 按实际文本组保留注册;共享排序投影变化不撤销未变化组的 provider。 */
|
|
11155
|
+
function createLayerRuntime(ctx, warnOnce, options = {}) {
|
|
11156
|
+
let records = [];
|
|
11157
|
+
let active = true;
|
|
11158
|
+
const listeners = [];
|
|
11159
|
+
const sharedVariables = {
|
|
11160
|
+
bindings: /* @__PURE__ */ new Map(),
|
|
11161
|
+
usedNames: /* @__PURE__ */ new Set()
|
|
11162
|
+
};
|
|
11163
|
+
const keep = (release) => {
|
|
11164
|
+
listeners.push(release);
|
|
11165
|
+
};
|
|
11166
|
+
try {
|
|
11167
|
+
for (const collection of ["sections", "contexts"]) registerDeliveryOrder(ctx, keep, collection, () => orderedNamesOf(records.flatMap((record) => record.ordered[collection])));
|
|
11168
|
+
} catch (error) {
|
|
11169
|
+
for (const release of listeners.reverse()) release();
|
|
11170
|
+
throw error;
|
|
11171
|
+
}
|
|
11172
|
+
const groupsOf = (configs) => {
|
|
11173
|
+
const groups = [];
|
|
11174
|
+
for (const layer of ["system-section", "runtime-context"]) {
|
|
11175
|
+
const selected = configs.filter((config) => config.layer === layer);
|
|
11176
|
+
const conditional = selected.filter((config) => typeof config.rule?.when === "function" || typeof config.actionWhen === "function" || (config.rule !== void 0 || config.params?.templateEvaluation === true) && config.params?.complete !== true && config.params?.suppressRuntimeContext !== true);
|
|
11177
|
+
const conditionalSet = new Set(conditional);
|
|
11178
|
+
const regular = selected.filter((config) => !conditionalSet.has(config));
|
|
11179
|
+
groups.push(...textLayerGroups(conditional));
|
|
11180
|
+
if (layer === "system-section") groups.push(...textLayerGroups(regular));
|
|
11181
|
+
else {
|
|
11182
|
+
const resolver = regular.filter((config) => config.strategy === "placeholder" || !KNOWN_STRATEGIES.has(config.strategy));
|
|
11183
|
+
const resolverSet = new Set(resolver);
|
|
11184
|
+
groups.push(...textLayerGroups(regular.filter((config) => !resolverSet.has(config))), ...resolver.map((config) => [config]));
|
|
11185
|
+
}
|
|
11186
|
+
}
|
|
11187
|
+
const other = configs.filter((config) => !["system-section", "runtime-context"].includes(config.layer));
|
|
11188
|
+
return [...groups, ...other.map((config) => [config])];
|
|
11189
|
+
};
|
|
11190
|
+
const mount = (configs) => {
|
|
11191
|
+
const ordered = {
|
|
11192
|
+
sections: [],
|
|
11193
|
+
contexts: []
|
|
11194
|
+
};
|
|
11195
|
+
const handlers = [];
|
|
11196
|
+
return {
|
|
11197
|
+
configs,
|
|
11198
|
+
ordered,
|
|
11199
|
+
handlers,
|
|
11200
|
+
dispose: wireLayers(ctx, configs, warnOnce, {
|
|
11201
|
+
...options,
|
|
11202
|
+
sharedVariables,
|
|
11203
|
+
ordered,
|
|
11204
|
+
deliveryOrder: false,
|
|
11205
|
+
on(channel, handler) {
|
|
11206
|
+
handlers.push({
|
|
11207
|
+
channel,
|
|
11208
|
+
handler,
|
|
11209
|
+
config: configs[0]
|
|
11210
|
+
});
|
|
11211
|
+
return () => {};
|
|
11212
|
+
}
|
|
11213
|
+
})
|
|
11214
|
+
};
|
|
11215
|
+
};
|
|
11216
|
+
return {
|
|
11217
|
+
replace(configs) {
|
|
11218
|
+
if (!active) throw new Error("rule text runtime disposed");
|
|
11219
|
+
const groups = groupsOf(configs);
|
|
11220
|
+
const byFirst = new Map(records.map((record) => [record.configs[0], record]));
|
|
11221
|
+
const retained = groups.map((group) => {
|
|
11222
|
+
const record = byFirst.get(group[0]);
|
|
11223
|
+
return record?.configs.length === group.length && group.every((config, index) => record.configs[index] === config) ? record : void 0;
|
|
11224
|
+
});
|
|
11225
|
+
const retainedSet = new Set(retained);
|
|
11226
|
+
const removed = records.filter((record) => !retainedSet.has(record));
|
|
11227
|
+
for (const record of removed) record.dispose();
|
|
11228
|
+
const created = [];
|
|
11229
|
+
try {
|
|
11230
|
+
records = groups.map((group, index) => {
|
|
11231
|
+
if (retained[index] !== void 0) return retained[index];
|
|
11232
|
+
const record = mount(group);
|
|
11233
|
+
created.push(record);
|
|
11234
|
+
return record;
|
|
11235
|
+
});
|
|
11236
|
+
const owners = new Set(configs.map((config) => config.sourceModuleId ?? ""));
|
|
11237
|
+
for (const owner of options.turnStopBudgets?.keys() ?? []) if (!owners.has(owner)) options.turnStopBudgets.delete(owner);
|
|
11238
|
+
} catch (error) {
|
|
11239
|
+
for (const record of created.reverse()) record.dispose();
|
|
11240
|
+
records = records.filter((record) => !removed.includes(record));
|
|
11241
|
+
for (const record of removed) records.push(mount(record.configs));
|
|
11242
|
+
throw error;
|
|
11243
|
+
}
|
|
11244
|
+
},
|
|
11245
|
+
entries: () => records.flatMap((record) => record.handlers),
|
|
11246
|
+
dispose() {
|
|
11247
|
+
if (!active) return;
|
|
11248
|
+
active = false;
|
|
11249
|
+
for (const record of records.splice(0).reverse()) record.dispose();
|
|
11250
|
+
for (const release of listeners.splice(0).reverse()) release();
|
|
11251
|
+
}
|
|
11252
|
+
};
|
|
11253
|
+
}
|
|
11139
11254
|
//#endregion
|
|
11140
11255
|
//#region engine/anchor-match.mjs
|
|
11141
11256
|
/**
|
|
@@ -20017,6 +20132,14 @@ function createBridgeRuntime(options) {
|
|
|
20017
20132
|
};
|
|
20018
20133
|
const runOverridesChange = (moduleId) => finishModuleChange(() => deps.overridesChanged?.(moduleId));
|
|
20019
20134
|
const refreshModuleList = () => finishModuleChange(() => deps.moduleListChanged?.());
|
|
20135
|
+
const schedulePublication = async (moduleId, reason) => {
|
|
20136
|
+
const schedule = deps.schedulePublication;
|
|
20137
|
+
if (schedule !== void 0) {
|
|
20138
|
+
const result = await finishModuleChange(() => schedule(moduleId, reason));
|
|
20139
|
+
return result.publicationPending ? result : { persisted: true };
|
|
20140
|
+
}
|
|
20141
|
+
return reason === "installed" ? finishModuleChange(() => deps.moduleInstalled?.(moduleId)) : reason === "capability" ? finishModuleChange(() => deps.capabilityChanged?.(moduleId)) : reason === "list" ? refreshModuleList() : runOverridesChange(moduleId);
|
|
20142
|
+
};
|
|
20020
20143
|
const writeModuleOrderError = (write, error) => {
|
|
20021
20144
|
write(error instanceof ModuleConfigOrderError ? error.status : 500, {
|
|
20022
20145
|
ok: false,
|
|
@@ -20121,6 +20244,8 @@ function createBridgeRuntime(options) {
|
|
|
20121
20244
|
const globalLayerError = readGlobalLayerSettingsSafe(userModulesDir()).error;
|
|
20122
20245
|
if (globalLayerError !== void 0) warnings.push(`全局层 layerSettings 解析失败,已按「无全局层」继续(指令卡的全局开关暂不可用):${globalLayerError}`);
|
|
20123
20246
|
if (warnings.length > 0) meta.moduleWarnings = warnings;
|
|
20247
|
+
const publicationFailures = deps.publicationFailures?.();
|
|
20248
|
+
if (publicationFailures !== void 0 && publicationFailures.length > 0) meta.publicationFailures = publicationFailures;
|
|
20124
20249
|
meta.editorGroups = ENGINE_EDITOR_GROUP_MAP.map(({ id, displayLayer, relatedLayers, hook }) => ({
|
|
20125
20250
|
id,
|
|
20126
20251
|
displayLayer,
|
|
@@ -20258,7 +20383,7 @@ function createBridgeRuntime(options) {
|
|
|
20258
20383
|
...pendingVariableSettings.has(dir) ? { publicationError: pendingVariableSettings.get(dir) } : {}
|
|
20259
20384
|
});
|
|
20260
20385
|
const refreshVariableSettings = async (dir) => {
|
|
20261
|
-
if (!pendingVariableSettings.has(dir)) return;
|
|
20386
|
+
if (!pendingVariableSettings.has(dir) && deps.schedulePublication === void 0) return;
|
|
20262
20387
|
try {
|
|
20263
20388
|
await deps.overridesChanged?.(basename(dir));
|
|
20264
20389
|
pendingVariableSettings.delete(dir);
|
|
@@ -20274,6 +20399,15 @@ function createBridgeRuntime(options) {
|
|
|
20274
20399
|
...committed,
|
|
20275
20400
|
...published(committed.publicationError ?? "变量已保存,等待运行发布")
|
|
20276
20401
|
};
|
|
20402
|
+
if (settingsChanged && deps.schedulePublication !== void 0) {
|
|
20403
|
+
const publication = await schedulePublication(basename(dir));
|
|
20404
|
+
if (publication.publicationPending) pendingVariableSettings.set(dir, publication.publicationError ?? "变量开关已保存,等待运行发布");
|
|
20405
|
+
else pendingVariableSettings.delete(dir);
|
|
20406
|
+
return {
|
|
20407
|
+
...committed,
|
|
20408
|
+
...publication
|
|
20409
|
+
};
|
|
20410
|
+
}
|
|
20277
20411
|
if (settingsChanged) await refreshVariableSettings(dir);
|
|
20278
20412
|
return {
|
|
20279
20413
|
...committed,
|
|
@@ -20314,6 +20448,7 @@ function createBridgeRuntime(options) {
|
|
|
20314
20448
|
finishModuleChange,
|
|
20315
20449
|
runOverridesChange,
|
|
20316
20450
|
refreshModuleList,
|
|
20451
|
+
schedulePublication,
|
|
20317
20452
|
writeModuleOrderError,
|
|
20318
20453
|
loadEngineMeta,
|
|
20319
20454
|
collectSkills,
|
|
@@ -20727,7 +20862,7 @@ function registerDefinitions(runtime) {
|
|
|
20727
20862
|
appendModuleCapabilities(doc, customToolModules(customTools));
|
|
20728
20863
|
}
|
|
20729
20864
|
}, { owns: ["customTools", "modules"] });
|
|
20730
|
-
const publication = await runtime.
|
|
20865
|
+
const publication = await runtime.schedulePublication(basename(dir));
|
|
20731
20866
|
tx.write(200, {
|
|
20732
20867
|
ok: true,
|
|
20733
20868
|
value: {
|
|
@@ -20787,7 +20922,7 @@ function registerDefinitions(runtime) {
|
|
|
20787
20922
|
if (!creating && (typeof record.expectedRevision !== "string" || !SHA256_HEX_RE.test(record.expectedRevision))) throw new TypeError("保存人设必须提供读取时的 expectedRevision");
|
|
20788
20923
|
saved = saveModulePersona(root, id, persona, creating ? readModulePersona(dir).revision : record.expectedRevision);
|
|
20789
20924
|
}
|
|
20790
|
-
const publication = await runtime.runOverridesChange(basename(dir));
|
|
20925
|
+
const publication = record.refreshOnly === true ? await runtime.runOverridesChange(basename(dir)) : await runtime.schedulePublication(basename(dir));
|
|
20791
20926
|
tx.write(200, {
|
|
20792
20927
|
ok: true,
|
|
20793
20928
|
value: {
|
|
@@ -20836,7 +20971,7 @@ function registerDefinitions(runtime) {
|
|
|
20836
20971
|
}
|
|
20837
20972
|
if (record.refreshOnly !== true && record.expectedRevision !== null && (typeof record.expectedRevision !== "string" || !SHA256_HEX_RE.test(record.expectedRevision))) throw new TypeError("保存人设来源必须提供读取时的 expectedRevision");
|
|
20838
20973
|
const saved = record.refreshOnly === true ? readPersonaSources(root) : writePersonaSources(root, record.sources, record.expectedRevision);
|
|
20839
|
-
const publication = await runtime.runOverridesChange();
|
|
20974
|
+
const publication = record.refreshOnly === true ? await runtime.runOverridesChange() : await runtime.schedulePublication();
|
|
20840
20975
|
tx.write(200, {
|
|
20841
20976
|
ok: true,
|
|
20842
20977
|
value: {
|
|
@@ -20921,7 +21056,7 @@ function registerDefinitions(runtime) {
|
|
|
20921
21056
|
action: "create-recipe",
|
|
20922
21057
|
recipeId: id.trim()
|
|
20923
21058
|
});
|
|
20924
|
-
const publication = result.changed ? await runtime.
|
|
21059
|
+
const publication = result.changed ? await runtime.schedulePublication(basename(dir), "capability") : published();
|
|
20925
21060
|
tx.write(200, {
|
|
20926
21061
|
ok: true,
|
|
20927
21062
|
value: {
|
|
@@ -22013,9 +22148,8 @@ function registerInstructions(runtime) {
|
|
|
22013
22148
|
...record.activateRuleId === void 0 ? {} : { activateRuleId: record.activateRuleId },
|
|
22014
22149
|
...record.validateOnly === void 0 ? {} : { validateOnly: record.validateOnly }
|
|
22015
22150
|
}) : isEditableModuleDir(dir) ? readModuleRules(dir) : ensureModuleSlices(dir, { writable: false });
|
|
22016
|
-
|
|
22017
|
-
|
|
22018
|
-
} catch (error) {
|
|
22151
|
+
const publication = writing ? await runtime.schedulePublication(basename(dir)) : void 0;
|
|
22152
|
+
if (publication?.publicationPending) {
|
|
22019
22153
|
tx.write(200, {
|
|
22020
22154
|
ok: true,
|
|
22021
22155
|
value: {
|
|
@@ -22023,7 +22157,7 @@ function registerInstructions(runtime) {
|
|
|
22023
22157
|
revisions: candidate.revisions,
|
|
22024
22158
|
meta: await ruleEditorMeta(),
|
|
22025
22159
|
...createdRuleId === void 0 ? {} : { createdRuleId },
|
|
22026
|
-
...
|
|
22160
|
+
...publication
|
|
22027
22161
|
}
|
|
22028
22162
|
});
|
|
22029
22163
|
return;
|
|
@@ -22044,7 +22178,7 @@ function registerInstructions(runtime) {
|
|
|
22044
22178
|
revisions: result.revisions,
|
|
22045
22179
|
meta: await ruleEditorMeta(),
|
|
22046
22180
|
...createdRuleId === void 0 ? {} : { createdRuleId },
|
|
22047
|
-
...
|
|
22181
|
+
...publication
|
|
22048
22182
|
}
|
|
22049
22183
|
});
|
|
22050
22184
|
} catch (error) {
|
|
@@ -22167,7 +22301,7 @@ function registerLifecycle(runtime) {
|
|
|
22167
22301
|
});
|
|
22168
22302
|
return;
|
|
22169
22303
|
}
|
|
22170
|
-
const publication = await runtime.
|
|
22304
|
+
const publication = await runtime.schedulePublication(void 0, "list");
|
|
22171
22305
|
if (publication.publicationPending) runtime.deps.warn?.(`删除模块 ${id} 后刷新运行实例失败:${publication.publicationError}`);
|
|
22172
22306
|
tx.write(200, {
|
|
22173
22307
|
ok: true,
|
|
@@ -22217,7 +22351,7 @@ function registerLifecycle(runtime) {
|
|
|
22217
22351
|
});
|
|
22218
22352
|
return;
|
|
22219
22353
|
}
|
|
22220
|
-
const publication = await runtime.
|
|
22354
|
+
const publication = await runtime.schedulePublication(void 0, "list");
|
|
22221
22355
|
tx.write(200, {
|
|
22222
22356
|
ok: true,
|
|
22223
22357
|
value: {
|
|
@@ -22257,7 +22391,7 @@ function registerLifecycle(runtime) {
|
|
|
22257
22391
|
});
|
|
22258
22392
|
return;
|
|
22259
22393
|
}
|
|
22260
|
-
const publication = await runtime.
|
|
22394
|
+
const publication = await runtime.schedulePublication(void 0, "list");
|
|
22261
22395
|
tx.write(200, {
|
|
22262
22396
|
ok: true,
|
|
22263
22397
|
value: {
|
|
@@ -22320,7 +22454,7 @@ function registerLifecycle(runtime) {
|
|
|
22320
22454
|
}
|
|
22321
22455
|
if (record.expectedRevision === void 0 || record.expectedModuleId === void 0) throw new ModuleNameError("保存名称必须提供 expectedRevision 和 expectedModuleId");
|
|
22322
22456
|
const value = writeModuleName(dir, record);
|
|
22323
|
-
const publication = await runtime.
|
|
22457
|
+
const publication = await runtime.schedulePublication(basename(dir));
|
|
22324
22458
|
tx.write(200, {
|
|
22325
22459
|
ok: true,
|
|
22326
22460
|
value: {
|
|
@@ -22398,26 +22532,9 @@ function registerLifecycle(runtime) {
|
|
|
22398
22532
|
const enabled = record.enabled;
|
|
22399
22533
|
await runtime.moduleOrderQueue.run(async () => {
|
|
22400
22534
|
try {
|
|
22401
|
-
|
|
22402
|
-
if (enabled) {
|
|
22403
|
-
const changed = appendModuleConfigOrder(userModulesDir(), id);
|
|
22404
|
-
if (!changed.includes(id) && !enabledModuleIds(userModulesDir()).includes(id) && readModuleConfigOrder(userModulesDir(), id).entries.length > 0) changed.push(id);
|
|
22405
|
-
for (const changedId of changed) {
|
|
22406
|
-
publication = await runtime.runOverridesChange(changedId);
|
|
22407
|
-
if (publication.publicationPending) {
|
|
22408
|
-
tx.write(200, {
|
|
22409
|
-
ok: true,
|
|
22410
|
-
value: {
|
|
22411
|
-
enabled: enabledModuleIds(userModulesDir()),
|
|
22412
|
-
...publication
|
|
22413
|
-
}
|
|
22414
|
-
});
|
|
22415
|
-
return;
|
|
22416
|
-
}
|
|
22417
|
-
}
|
|
22418
|
-
}
|
|
22535
|
+
if (enabled) appendModuleConfigOrder(userModulesDir(), id);
|
|
22419
22536
|
setModuleEnabled(userModulesDir(), id, enabled);
|
|
22420
|
-
publication = await runtime.
|
|
22537
|
+
const publication = await runtime.schedulePublication();
|
|
22421
22538
|
tx.write(200, {
|
|
22422
22539
|
ok: true,
|
|
22423
22540
|
value: {
|
|
@@ -22478,7 +22595,7 @@ function registerLifecycle(runtime) {
|
|
|
22478
22595
|
if (writing) {
|
|
22479
22596
|
const changedIds = saveModuleConfigOrder(userModulesDir(), body.expectedRevision, body.entries, moduleId);
|
|
22480
22597
|
for (const id of changedIds) {
|
|
22481
|
-
publication = await runtime.
|
|
22598
|
+
publication = await runtime.schedulePublication(id);
|
|
22482
22599
|
if (publication.publicationPending) break;
|
|
22483
22600
|
}
|
|
22484
22601
|
}
|
|
@@ -22724,7 +22841,7 @@ function registerParams(runtime) {
|
|
|
22724
22841
|
try {
|
|
22725
22842
|
if (global) writeGlobalLayerSettings(userModulesDir(), rawOverrides ?? {});
|
|
22726
22843
|
else saveModuleParams(moduleRoot, templateName, rawOverrides, void 0);
|
|
22727
|
-
const publication = record.rebuild === false ? published() : await runtime.
|
|
22844
|
+
const publication = record.rebuild === false ? published() : await runtime.schedulePublication(global ? void 0 : basename(dir));
|
|
22728
22845
|
tx.write(200, {
|
|
22729
22846
|
ok: true,
|
|
22730
22847
|
value: {
|
|
@@ -25586,7 +25703,7 @@ function registerTransfer(runtime) {
|
|
|
25586
25703
|
}
|
|
25587
25704
|
const installed = await installModulePackage(userModulesDir(), files, request.params);
|
|
25588
25705
|
runtime.descriptor.invalidate();
|
|
25589
|
-
const publication = await runtime.
|
|
25706
|
+
const publication = await runtime.schedulePublication(installed.id, "installed");
|
|
25590
25707
|
tx.write(200, {
|
|
25591
25708
|
ok: true,
|
|
25592
25709
|
value: {
|
|
@@ -28702,6 +28819,110 @@ function createModuleInitialization(ctx) {
|
|
|
28702
28819
|
};
|
|
28703
28820
|
}
|
|
28704
28821
|
//#endregion
|
|
28822
|
+
//#region src/runtime/publication-queue.ts
|
|
28823
|
+
/** 保存防抖与请求前冲刷共用待发布集合;回调只消费当批快照。 */
|
|
28824
|
+
function createPublicationQueue(options) {
|
|
28825
|
+
const serial = createTargetQueue();
|
|
28826
|
+
const ids = /* @__PURE__ */ new Set();
|
|
28827
|
+
const retries = /* @__PURE__ */ new Set();
|
|
28828
|
+
const errors = /* @__PURE__ */ new Map();
|
|
28829
|
+
let all = false, retryAll = false, active = true;
|
|
28830
|
+
let timer;
|
|
28831
|
+
let timerDone;
|
|
28832
|
+
let resolveTimer;
|
|
28833
|
+
let running;
|
|
28834
|
+
const cancelTimer = () => {
|
|
28835
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
28836
|
+
timer = void 0;
|
|
28837
|
+
resolveTimer?.();
|
|
28838
|
+
resolveTimer = void 0;
|
|
28839
|
+
timerDone = void 0;
|
|
28840
|
+
};
|
|
28841
|
+
const assertActive = () => {
|
|
28842
|
+
if (!active) throw new Error("publication queue released");
|
|
28843
|
+
};
|
|
28844
|
+
const include = (id) => {
|
|
28845
|
+
if (id === void 0) {
|
|
28846
|
+
all = true;
|
|
28847
|
+
ids.clear();
|
|
28848
|
+
} else if (!all) ids.add(id);
|
|
28849
|
+
};
|
|
28850
|
+
const start = () => {
|
|
28851
|
+
cancelTimer();
|
|
28852
|
+
if (running !== void 0) return running.catch(() => {}).then(start);
|
|
28853
|
+
if (!active || !all && ids.size === 0) return Promise.resolve();
|
|
28854
|
+
const modules = all ? void 0 : [...ids];
|
|
28855
|
+
const retry = retryAll ? true : [...retries];
|
|
28856
|
+
all = false;
|
|
28857
|
+
retryAll = false;
|
|
28858
|
+
ids.clear();
|
|
28859
|
+
retries.clear();
|
|
28860
|
+
const task = serial.run("publication", async () => {
|
|
28861
|
+
try {
|
|
28862
|
+
const complete = await options.publish(modules, retry);
|
|
28863
|
+
if (modules === void 0 || complete === true) errors.clear();
|
|
28864
|
+
else for (const id of modules) errors.delete(id);
|
|
28865
|
+
} catch (error) {
|
|
28866
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
28867
|
+
const at = Date.now();
|
|
28868
|
+
for (const id of modules ?? [void 0]) errors.set(id ?? "", {
|
|
28869
|
+
...id === void 0 ? {} : { moduleId: id },
|
|
28870
|
+
message,
|
|
28871
|
+
at
|
|
28872
|
+
});
|
|
28873
|
+
try {
|
|
28874
|
+
options.warn(message);
|
|
28875
|
+
} catch {}
|
|
28876
|
+
throw error;
|
|
28877
|
+
}
|
|
28878
|
+
});
|
|
28879
|
+
running = task;
|
|
28880
|
+
const finished = () => {
|
|
28881
|
+
if (running === task) running = void 0;
|
|
28882
|
+
};
|
|
28883
|
+
task.then(finished, finished);
|
|
28884
|
+
return task;
|
|
28885
|
+
};
|
|
28886
|
+
return {
|
|
28887
|
+
schedule(moduleId) {
|
|
28888
|
+
assertActive();
|
|
28889
|
+
include(moduleId);
|
|
28890
|
+
cancelTimer();
|
|
28891
|
+
timerDone = new Promise((resolve) => {
|
|
28892
|
+
resolveTimer = resolve;
|
|
28893
|
+
});
|
|
28894
|
+
timer = setTimeout(() => {
|
|
28895
|
+
start().catch(() => {});
|
|
28896
|
+
}, 300);
|
|
28897
|
+
},
|
|
28898
|
+
flush(moduleId, retry = true) {
|
|
28899
|
+
assertActive();
|
|
28900
|
+
if (retry) {
|
|
28901
|
+
include(moduleId);
|
|
28902
|
+
if (moduleId === void 0) retryAll = true;
|
|
28903
|
+
else retries.add(moduleId);
|
|
28904
|
+
} else if (moduleId !== void 0) include(moduleId);
|
|
28905
|
+
return start();
|
|
28906
|
+
},
|
|
28907
|
+
async settled() {
|
|
28908
|
+
while (timerDone !== void 0 || running !== void 0) await Promise.all([timerDone, running?.catch(() => {})]);
|
|
28909
|
+
},
|
|
28910
|
+
failures() {
|
|
28911
|
+
return active ? [...errors.values()].map((error) => ({ ...error })) : [];
|
|
28912
|
+
},
|
|
28913
|
+
async dispose() {
|
|
28914
|
+
active = false;
|
|
28915
|
+
cancelTimer();
|
|
28916
|
+
all = false;
|
|
28917
|
+
retryAll = false;
|
|
28918
|
+
ids.clear();
|
|
28919
|
+
retries.clear();
|
|
28920
|
+
errors.clear();
|
|
28921
|
+
await running?.catch(() => {});
|
|
28922
|
+
}
|
|
28923
|
+
};
|
|
28924
|
+
}
|
|
28925
|
+
//#endregion
|
|
28705
28926
|
//#region src/host/generation-recovery-state.ts
|
|
28706
28927
|
/** 会话恢复额度的唯一持久owner,重挂不重置,先扣额再允许唤醒。 */
|
|
28707
28928
|
function createGenerationRecoveryState(root = join(storageRoot(), "generation-recovery")) {
|
|
@@ -28793,37 +29014,74 @@ const noNext = /* @__PURE__ */ new Set([
|
|
|
28793
29014
|
]);
|
|
28794
29015
|
const compare = (a, b) => a.action.channelOrder - b.action.channelOrder || a.moduleId.localeCompare(b.moduleId) || a.ruleIndex - b.ruleIndex || a.action.actionIndex - b.action.actionIndex;
|
|
28795
29016
|
const sourceError = (error, moduleId) => Object.assign(new Error(String(error?.message ?? error), { cause: error }), { sourceModuleId: moduleId });
|
|
29017
|
+
const pointKey = (point) => `${point.channel}:${point.phase}:${point.waterfallPosition}`;
|
|
29018
|
+
const compareEntries = (a, b) => a.sequence - b.sequence || a.sourceModuleId.localeCompare(b.sourceModuleId) || a.ruleIndex - b.ruleIndex || a.ruleActionIndex - b.ruleActionIndex;
|
|
29019
|
+
function pointHandler(ctx, point, snapshot, warnOnce, report, isActive) {
|
|
29020
|
+
return (...args) => {
|
|
29021
|
+
const handlers = snapshot();
|
|
29022
|
+
const free = noNext.has(point.channel);
|
|
29023
|
+
const payload = free ? args : args.slice(0, -1);
|
|
29024
|
+
const next = free ? () => void 0 : args.at(-1);
|
|
29025
|
+
if (!isActive()) return next();
|
|
29026
|
+
let frame;
|
|
29027
|
+
try {
|
|
29028
|
+
frame = ruleFrame(point.channel, payload, warnOnce, ctx, report);
|
|
29029
|
+
} catch (error) {
|
|
29030
|
+
warnOnce(`rule engine: frame construction failed on ${point.channel}: ${String(error?.message ?? error)}`);
|
|
29031
|
+
return next();
|
|
29032
|
+
}
|
|
29033
|
+
if (free) {
|
|
29034
|
+
let pending;
|
|
29035
|
+
for (const entry of handlers) {
|
|
29036
|
+
const invoke = () => {
|
|
29037
|
+
if (!isActive()) return void 0;
|
|
29038
|
+
if (!actionMatches(entry, frame)) {
|
|
29039
|
+
entry.miss?.(frame);
|
|
29040
|
+
return;
|
|
29041
|
+
}
|
|
29042
|
+
return entry.handler(...payload, void 0, frame);
|
|
29043
|
+
};
|
|
29044
|
+
pending = pending?.then ? pending.then(invoke) : invoke();
|
|
29045
|
+
}
|
|
29046
|
+
return pending;
|
|
29047
|
+
}
|
|
29048
|
+
if (point.phase === "after-next") return Promise.resolve(next()).then(async (initial) => {
|
|
29049
|
+
let result = initial;
|
|
29050
|
+
for (const entry of handlers) {
|
|
29051
|
+
if (!isActive()) continue;
|
|
29052
|
+
if (!actionMatches(entry, frame)) {
|
|
29053
|
+
entry.miss?.(frame);
|
|
29054
|
+
continue;
|
|
29055
|
+
}
|
|
29056
|
+
result = await entry.handler(...payload, () => result, frame);
|
|
29057
|
+
}
|
|
29058
|
+
return result;
|
|
29059
|
+
});
|
|
29060
|
+
const invoke = (index) => {
|
|
29061
|
+
if (!isActive() || index === handlers.length) return next();
|
|
29062
|
+
const entry = handlers[index];
|
|
29063
|
+
if (!actionMatches(entry, frame)) {
|
|
29064
|
+
entry.miss?.(frame);
|
|
29065
|
+
return invoke(index + 1);
|
|
29066
|
+
}
|
|
29067
|
+
return entry.handler(...payload, () => invoke(index + 1), frame);
|
|
29068
|
+
};
|
|
29069
|
+
return invoke(0);
|
|
29070
|
+
};
|
|
29071
|
+
}
|
|
28796
29072
|
/** 所有来源只进入这个装配入口;受众限定固定效果要求 ctx 属于 options.agent 的 scope。 */
|
|
28797
|
-
function
|
|
29073
|
+
function mountSources(ctx, sources, options = {}) {
|
|
28798
29074
|
validateDeliverySources(sources);
|
|
28799
|
-
const
|
|
28800
|
-
const service = getService(ctx, PRE_STEP_COORDINATOR_SERVICE);
|
|
28801
|
-
return service !== null && typeof service === "object" && typeof service.registerPreset === "function" ? service : void 0;
|
|
28802
|
-
})();
|
|
28803
|
-
const pool = options.promotionPool ?? coordinator?.promotionPool ?? createPromotionPool(ctx);
|
|
28804
|
-
const ownsPool = options.promotionPool === void 0 && coordinator?.promotionPool === void 0;
|
|
29075
|
+
const pool = options.promotionPool;
|
|
28805
29076
|
const warnOnce = options.warnOnce ?? createWarnOnce(ctx, options.plugin ?? "rule-engine");
|
|
28806
|
-
const report = options.onOutcome === void 0 ? void 0 : (() => {
|
|
28807
|
-
const moduleOfRule = /* @__PURE__ */ new Map();
|
|
28808
|
-
for (const source of sources) for (const rule of source.rules) if (!moduleOfRule.has(rule)) moduleOfRule.set(rule, source.moduleId);
|
|
28809
|
-
return (rule, channel, outcome) => options.onOutcome({
|
|
28810
|
-
moduleId: moduleOfRule.get(rule),
|
|
28811
|
-
ruleId: rule.id,
|
|
28812
|
-
channel,
|
|
28813
|
-
outcome
|
|
28814
|
-
});
|
|
28815
|
-
})();
|
|
28816
29077
|
const releases = [];
|
|
28817
|
-
if (ownsPool) releases.push(() => pool.dispose());
|
|
28818
29078
|
const points = /* @__PURE__ */ new Map();
|
|
28819
|
-
const turnStopBudgets = /* @__PURE__ */ new Map();
|
|
28820
29079
|
const injections = new Map(sources.map((source) => [source.moduleId, {
|
|
28821
29080
|
moduleId: source.moduleId,
|
|
28822
29081
|
sourceId: moduleSourceId(source.moduleId),
|
|
28823
29082
|
configs: [],
|
|
28824
29083
|
ruleActions: []
|
|
28825
29084
|
}]));
|
|
28826
|
-
let active = true;
|
|
28827
29085
|
const bind = (item, on) => prepareAction(item.action, {
|
|
28828
29086
|
plugin: options.plugin,
|
|
28829
29087
|
warnOnce,
|
|
@@ -28877,16 +29135,7 @@ function mountRuleSources(ctx, sources, options = {}) {
|
|
|
28877
29135
|
let textConfigs = [];
|
|
28878
29136
|
const flushLayers = () => {
|
|
28879
29137
|
if (!textConfigs.length) return;
|
|
28880
|
-
|
|
28881
|
-
agent: options.agent,
|
|
28882
|
-
turnStopBudgets,
|
|
28883
|
-
sourceError,
|
|
28884
|
-
on: (channel, handler) => {
|
|
28885
|
-
if (channel !== point.channel) throw new TypeError(`rule action registered outside ${point.channel}: ${channel}`);
|
|
28886
|
-
handlers.push({ handler });
|
|
28887
|
-
return () => {};
|
|
28888
|
-
}
|
|
28889
|
-
}));
|
|
29138
|
+
options.collectText(point, textConfigs);
|
|
28890
29139
|
textConfigs = [];
|
|
28891
29140
|
};
|
|
28892
29141
|
for (const item of point.items) {
|
|
@@ -28901,7 +29150,9 @@ function mountRuleSources(ctx, sources, options = {}) {
|
|
|
28901
29150
|
exclusive: false,
|
|
28902
29151
|
enabled: true,
|
|
28903
29152
|
actionWhen: action.actionWhen,
|
|
28904
|
-
bypassRuleWhen: action.bypassRuleWhen
|
|
29153
|
+
bypassRuleWhen: action.bypassRuleWhen,
|
|
29154
|
+
runtimeOrder: action.channelOrder,
|
|
29155
|
+
runtimeRuleIndex: item.ruleIndex
|
|
28905
29156
|
};
|
|
28906
29157
|
if (config.layer === "pre-step") injections.get(moduleId).configs.push(config);
|
|
28907
29158
|
else textConfigs.push(config);
|
|
@@ -28917,6 +29168,7 @@ function mountRuleSources(ctx, sources, options = {}) {
|
|
|
28917
29168
|
sequence: action.channelOrder,
|
|
28918
29169
|
sourceModuleId: moduleId,
|
|
28919
29170
|
ruleId: rule.id,
|
|
29171
|
+
ruleIndex: item.ruleIndex,
|
|
28920
29172
|
ruleActionIndex: action.actionIndex,
|
|
28921
29173
|
id: action.id,
|
|
28922
29174
|
actionWhen: action.actionWhen,
|
|
@@ -28938,61 +29190,9 @@ function mountRuleSources(ctx, sources, options = {}) {
|
|
|
28938
29190
|
}
|
|
28939
29191
|
flushLayers();
|
|
28940
29192
|
if (!handlers.length) continue;
|
|
28941
|
-
|
|
28942
|
-
const free = noNext.has(point.channel);
|
|
28943
|
-
const payload = free ? args : args.slice(0, -1);
|
|
28944
|
-
const next = free ? () => void 0 : args[args.length - 1];
|
|
28945
|
-
if (!active) return next();
|
|
28946
|
-
let frame;
|
|
28947
|
-
try {
|
|
28948
|
-
frame = ruleFrame(point.channel, payload, warnOnce, ctx, report);
|
|
28949
|
-
} catch (error) {
|
|
28950
|
-
warnOnce(`rule engine: frame construction failed on ${point.channel}: ${String(error?.message ?? error)}`);
|
|
28951
|
-
return next();
|
|
28952
|
-
}
|
|
28953
|
-
if (free) {
|
|
28954
|
-
let pending;
|
|
28955
|
-
for (const entry of handlers) {
|
|
28956
|
-
const invoke = () => {
|
|
28957
|
-
if (!active) return void 0;
|
|
28958
|
-
if (!actionMatches(entry, frame)) {
|
|
28959
|
-
entry.miss?.(frame);
|
|
28960
|
-
return;
|
|
28961
|
-
}
|
|
28962
|
-
return entry.handler(...payload, void 0, frame);
|
|
28963
|
-
};
|
|
28964
|
-
pending = pending?.then ? pending.then(invoke) : invoke();
|
|
28965
|
-
}
|
|
28966
|
-
return pending;
|
|
28967
|
-
}
|
|
28968
|
-
if (point.phase === "after-next") return Promise.resolve(next()).then(async (initial) => {
|
|
28969
|
-
let result = initial;
|
|
28970
|
-
for (const entry of handlers) {
|
|
28971
|
-
if (!active) continue;
|
|
28972
|
-
if (!actionMatches(entry, frame)) {
|
|
28973
|
-
entry.miss?.(frame);
|
|
28974
|
-
continue;
|
|
28975
|
-
}
|
|
28976
|
-
result = await entry.handler(...payload, () => result, frame);
|
|
28977
|
-
}
|
|
28978
|
-
return result;
|
|
28979
|
-
});
|
|
28980
|
-
const invoke = (index) => {
|
|
28981
|
-
if (!active || index === handlers.length) return next();
|
|
28982
|
-
const entry = handlers[index];
|
|
28983
|
-
if (!actionMatches(entry, frame)) {
|
|
28984
|
-
entry.miss?.(frame);
|
|
28985
|
-
return invoke(index + 1);
|
|
28986
|
-
}
|
|
28987
|
-
return entry.handler(...payload, () => invoke(index + 1), frame);
|
|
28988
|
-
};
|
|
28989
|
-
return invoke(0);
|
|
28990
|
-
}, point.waterfallPosition === "outermost" ? { prepend: true } : void 0));
|
|
29193
|
+
options.collectPoint(point, handlers);
|
|
28991
29194
|
}
|
|
28992
|
-
const promotion = options.promotion
|
|
28993
|
-
main: pool.tracker(PROMOTE_EVENTS.either, { includeSubagents: false }),
|
|
28994
|
-
withSubagents: pool.tracker(PROMOTE_EVENTS.either, { includeSubagents: true })
|
|
28995
|
-
};
|
|
29195
|
+
const promotion = options.promotion;
|
|
28996
29196
|
const preStep = [...injections.values()].filter((source) => source.configs.length || source.ruleActions.length).map((source) => createPreStepSource({
|
|
28997
29197
|
sourceId: source.sourceId,
|
|
28998
29198
|
ctx,
|
|
@@ -29004,21 +29204,233 @@ function mountRuleSources(ctx, sources, options = {}) {
|
|
|
29004
29204
|
}),
|
|
29005
29205
|
promotion
|
|
29006
29206
|
}));
|
|
29007
|
-
if (preStep.length) releases.push(
|
|
29207
|
+
if (preStep.length) releases.push(options.registerPreStep(preStep));
|
|
29008
29208
|
} catch (error) {
|
|
29009
|
-
active = false;
|
|
29010
29209
|
for (const dispose of releases.reverse()) try {
|
|
29011
29210
|
dispose?.();
|
|
29012
29211
|
} catch {}
|
|
29013
29212
|
throw error;
|
|
29014
29213
|
}
|
|
29015
29214
|
return () => {
|
|
29016
|
-
active = false;
|
|
29017
29215
|
for (const dispose of releases.splice(0).reverse()) try {
|
|
29018
29216
|
dispose?.();
|
|
29019
29217
|
} catch {}
|
|
29020
29218
|
};
|
|
29021
29219
|
}
|
|
29220
|
+
/** 稳定执行点持有有序快照;来源仅在规则实例改变时重新绑定和注册。 */
|
|
29221
|
+
function createRuleRuntime(ctx, options = {}) {
|
|
29222
|
+
const warnOnce = options.warnOnce ?? createWarnOnce(ctx, options.plugin ?? "rule-engine");
|
|
29223
|
+
const coordinatorOf = () => {
|
|
29224
|
+
const value = getService(ctx, PRE_STEP_COORDINATOR_SERVICE);
|
|
29225
|
+
return typeof value?.registerPreset === "function" ? value : void 0;
|
|
29226
|
+
};
|
|
29227
|
+
const initialCoordinator = coordinatorOf();
|
|
29228
|
+
const pool = options.promotionPool ?? initialCoordinator?.promotionPool ?? createPromotionPool(ctx);
|
|
29229
|
+
const ownsPool = options.promotionPool === void 0 && initialCoordinator?.promotionPool === void 0;
|
|
29230
|
+
const promotion = options.promotion ?? initialCoordinator?.promotion ?? {
|
|
29231
|
+
main: pool.tracker(PROMOTE_EVENTS.either, { includeSubagents: false }),
|
|
29232
|
+
withSubagents: pool.tracker(PROMOTE_EVENTS.either, { includeSubagents: true })
|
|
29233
|
+
};
|
|
29234
|
+
const standalone = /* @__PURE__ */ new Map();
|
|
29235
|
+
const registrations = /* @__PURE__ */ new Map();
|
|
29236
|
+
let registeredCoordinator = initialCoordinator;
|
|
29237
|
+
let active = true;
|
|
29238
|
+
let records = /* @__PURE__ */ new Map();
|
|
29239
|
+
let points = /* @__PURE__ */ new Map();
|
|
29240
|
+
const listeners = /* @__PURE__ */ new Map();
|
|
29241
|
+
const ruleOwners = /* @__PURE__ */ new WeakMap();
|
|
29242
|
+
const memo = /* @__PURE__ */ new Map();
|
|
29243
|
+
const report = options.onOutcome === void 0 ? void 0 : (rule, channel, outcome) => options.onOutcome({
|
|
29244
|
+
moduleId: ruleOwners.get(rule),
|
|
29245
|
+
ruleId: rule.id,
|
|
29246
|
+
channel,
|
|
29247
|
+
outcome
|
|
29248
|
+
});
|
|
29249
|
+
let layers;
|
|
29250
|
+
let releaseMemo, releaseFallback;
|
|
29251
|
+
const register = (coordinator, source) => {
|
|
29252
|
+
if (coordinator.promotion === void 0) throw new TypeError("prompt-tool: pre-step coordinator v2 must expose a promotion owner");
|
|
29253
|
+
return coordinator.registerPreset(source.sourceId, {
|
|
29254
|
+
...source,
|
|
29255
|
+
promotion: coordinator.promotion
|
|
29256
|
+
}) ?? (() => {});
|
|
29257
|
+
};
|
|
29258
|
+
const ensureFallback = () => {
|
|
29259
|
+
if (releaseFallback !== void 0) return;
|
|
29260
|
+
releaseMemo = ctx.on("session/event", (session, event) => confirmDelivered(memo, session, event));
|
|
29261
|
+
try {
|
|
29262
|
+
releaseFallback = ctx.on("agent/pre-step", async (payload, next) => {
|
|
29263
|
+
const coordinator = coordinatorOf();
|
|
29264
|
+
if (coordinator !== registeredCoordinator) {
|
|
29265
|
+
for (const release of registrations.values()) release();
|
|
29266
|
+
registrations.clear();
|
|
29267
|
+
registeredCoordinator = coordinator;
|
|
29268
|
+
if (coordinator !== void 0) for (const source of standalone.values()) registrations.set(source.sourceId, register(coordinator, source));
|
|
29269
|
+
}
|
|
29270
|
+
const sources = [...standalone.values()];
|
|
29271
|
+
const decision = await next();
|
|
29272
|
+
if (!active || coordinator !== void 0 || sources.length === 0) return decision;
|
|
29273
|
+
return runPreStepBatch({
|
|
29274
|
+
sources,
|
|
29275
|
+
ctx,
|
|
29276
|
+
payload,
|
|
29277
|
+
agent: payload?.agent,
|
|
29278
|
+
decision,
|
|
29279
|
+
memo,
|
|
29280
|
+
warnOnce
|
|
29281
|
+
});
|
|
29282
|
+
}, { prepend: true });
|
|
29283
|
+
} catch (error) {
|
|
29284
|
+
releaseMemo();
|
|
29285
|
+
releaseMemo = void 0;
|
|
29286
|
+
throw error;
|
|
29287
|
+
}
|
|
29288
|
+
};
|
|
29289
|
+
const mount = (source) => {
|
|
29290
|
+
const record = {
|
|
29291
|
+
source,
|
|
29292
|
+
points: [],
|
|
29293
|
+
text: [],
|
|
29294
|
+
dispose: void 0
|
|
29295
|
+
};
|
|
29296
|
+
for (const rule of source.rules) ruleOwners.set(rule, source.moduleId);
|
|
29297
|
+
record.dispose = mountSources(ctx, [source], {
|
|
29298
|
+
...options,
|
|
29299
|
+
warnOnce,
|
|
29300
|
+
promotionPool: pool,
|
|
29301
|
+
promotion,
|
|
29302
|
+
registerPreStep(sources) {
|
|
29303
|
+
const installed = [];
|
|
29304
|
+
const dispose = () => {
|
|
29305
|
+
for (const item of installed) if (standalone.get(item.sourceId) === item) {
|
|
29306
|
+
standalone.delete(item.sourceId);
|
|
29307
|
+
registrations.get(item.sourceId)?.();
|
|
29308
|
+
registrations.delete(item.sourceId);
|
|
29309
|
+
}
|
|
29310
|
+
};
|
|
29311
|
+
try {
|
|
29312
|
+
ensureFallback();
|
|
29313
|
+
for (const item of sources) {
|
|
29314
|
+
if (standalone.has(item.sourceId)) throw new TypeError(`prompt-tool: duplicate pre-step source ${item.sourceId}`);
|
|
29315
|
+
standalone.set(item.sourceId, item);
|
|
29316
|
+
installed.push(item);
|
|
29317
|
+
const coordinator = coordinatorOf();
|
|
29318
|
+
if (coordinator !== void 0) try {
|
|
29319
|
+
registrations.set(item.sourceId, register(coordinator, item));
|
|
29320
|
+
} catch (error) {
|
|
29321
|
+
throw sourceError(error, source.moduleId);
|
|
29322
|
+
}
|
|
29323
|
+
}
|
|
29324
|
+
return dispose;
|
|
29325
|
+
} catch (error) {
|
|
29326
|
+
dispose();
|
|
29327
|
+
throw error;
|
|
29328
|
+
}
|
|
29329
|
+
},
|
|
29330
|
+
collectPoint(point, handlers) {
|
|
29331
|
+
record.points.push({
|
|
29332
|
+
point,
|
|
29333
|
+
handlers
|
|
29334
|
+
});
|
|
29335
|
+
},
|
|
29336
|
+
collectText(point, configs) {
|
|
29337
|
+
for (const config of configs) {
|
|
29338
|
+
config.runtimePoint = point;
|
|
29339
|
+
record.text.push(config);
|
|
29340
|
+
}
|
|
29341
|
+
}
|
|
29342
|
+
});
|
|
29343
|
+
return record;
|
|
29344
|
+
};
|
|
29345
|
+
const publishPoints = () => {
|
|
29346
|
+
const next = /* @__PURE__ */ new Map();
|
|
29347
|
+
const add = (point, entry) => {
|
|
29348
|
+
const key = pointKey(point);
|
|
29349
|
+
const value = next.get(key) ?? {
|
|
29350
|
+
point,
|
|
29351
|
+
handlers: []
|
|
29352
|
+
};
|
|
29353
|
+
value.handlers.push(entry);
|
|
29354
|
+
next.set(key, value);
|
|
29355
|
+
};
|
|
29356
|
+
for (const record of records.values()) for (const { point, handlers } of record.points) for (const entry of handlers) add(point, entry);
|
|
29357
|
+
for (const { channel, handler, config } of layers?.entries() ?? []) add({
|
|
29358
|
+
...config.runtimePoint,
|
|
29359
|
+
channel
|
|
29360
|
+
}, {
|
|
29361
|
+
handler,
|
|
29362
|
+
sequence: config.runtimeOrder,
|
|
29363
|
+
sourceModuleId: config.sourceModuleId,
|
|
29364
|
+
ruleIndex: config.runtimeRuleIndex,
|
|
29365
|
+
ruleActionIndex: config.ruleActionIndex ?? 0
|
|
29366
|
+
});
|
|
29367
|
+
for (const [key, value] of next) {
|
|
29368
|
+
value.handlers.sort(compareEntries);
|
|
29369
|
+
if (!listeners.has(key)) listeners.set(key, ctx.on(value.point.channel, pointHandler(ctx, value.point, () => points.get(key)?.handlers ?? [], warnOnce, report, () => active), value.point.waterfallPosition === "outermost" ? { prepend: true } : void 0));
|
|
29370
|
+
}
|
|
29371
|
+
points = next;
|
|
29372
|
+
};
|
|
29373
|
+
return {
|
|
29374
|
+
replace(sources) {
|
|
29375
|
+
if (!active) throw new Error("rule runtime disposed");
|
|
29376
|
+
validateDeliverySources(sources);
|
|
29377
|
+
const desired = /* @__PURE__ */ new Map();
|
|
29378
|
+
for (const source of sources) {
|
|
29379
|
+
if (desired.has(source.moduleId)) throw sourceError(/* @__PURE__ */ new TypeError(`duplicate rule source ${source.moduleId}`), source.moduleId);
|
|
29380
|
+
desired.set(source.moduleId, source);
|
|
29381
|
+
}
|
|
29382
|
+
const old = records;
|
|
29383
|
+
const changed = [...old.values()].filter((record) => desired.get(record.source.moduleId)?.rules !== record.source.rules);
|
|
29384
|
+
if (changed.length === 0 && sources.length === old.size) return;
|
|
29385
|
+
for (const record of changed) record.dispose();
|
|
29386
|
+
const created = [];
|
|
29387
|
+
try {
|
|
29388
|
+
const next = /* @__PURE__ */ new Map();
|
|
29389
|
+
for (const source of sources) {
|
|
29390
|
+
let record = old.get(source.moduleId);
|
|
29391
|
+
if (record?.source.rules !== source.rules) {
|
|
29392
|
+
record = mount(source);
|
|
29393
|
+
created.push(record);
|
|
29394
|
+
}
|
|
29395
|
+
next.set(source.moduleId, record);
|
|
29396
|
+
}
|
|
29397
|
+
records = next;
|
|
29398
|
+
const text = [...records.values()].flatMap((record) => record.text);
|
|
29399
|
+
if (text.length > 0) layers ??= createLayerRuntime(ctx, warnOnce, {
|
|
29400
|
+
agent: options.agent,
|
|
29401
|
+
turnStopBudgets: /* @__PURE__ */ new Map(),
|
|
29402
|
+
sourceError
|
|
29403
|
+
});
|
|
29404
|
+
layers?.replace(text);
|
|
29405
|
+
publishPoints();
|
|
29406
|
+
} catch (error) {
|
|
29407
|
+
for (const record of created.reverse()) record.dispose();
|
|
29408
|
+
records = new Map(old);
|
|
29409
|
+
try {
|
|
29410
|
+
for (const record of changed) records.set(record.source.moduleId, mount(record.source));
|
|
29411
|
+
layers?.replace([...records.values()].flatMap((record) => record.text));
|
|
29412
|
+
publishPoints();
|
|
29413
|
+
} catch (restoreError) {
|
|
29414
|
+
throw Object.assign(new AggregateError([error, restoreError], `rule source replacement and recovery failed: ${String(error.message)}; ${String(restoreError.message)}`), { sourceModuleId: error.sourceModuleId });
|
|
29415
|
+
}
|
|
29416
|
+
throw error;
|
|
29417
|
+
}
|
|
29418
|
+
},
|
|
29419
|
+
dispose() {
|
|
29420
|
+
if (!active) return;
|
|
29421
|
+
active = false;
|
|
29422
|
+
for (const record of records.values()) record.dispose();
|
|
29423
|
+
records.clear();
|
|
29424
|
+
layers?.dispose();
|
|
29425
|
+
for (const release of listeners.values()) release();
|
|
29426
|
+
listeners.clear();
|
|
29427
|
+
points.clear();
|
|
29428
|
+
releaseFallback?.();
|
|
29429
|
+
releaseMemo?.();
|
|
29430
|
+
if (ownsPool) pool.dispose();
|
|
29431
|
+
}
|
|
29432
|
+
};
|
|
29433
|
+
}
|
|
29022
29434
|
//#endregion
|
|
29023
29435
|
//#region src/runtime/agent-assembly.ts
|
|
29024
29436
|
/**
|
|
@@ -29238,6 +29650,7 @@ function createAgentAssembly(ctx, options) {
|
|
|
29238
29650
|
const watched = /* @__PURE__ */ new Map();
|
|
29239
29651
|
const disposed = /* @__PURE__ */ new WeakSet();
|
|
29240
29652
|
let pending = Promise.resolve();
|
|
29653
|
+
let publishingContent;
|
|
29241
29654
|
const serialQueue = createTargetQueue();
|
|
29242
29655
|
let active = true;
|
|
29243
29656
|
const warn = (error) => {
|
|
@@ -29323,7 +29736,7 @@ function createAgentAssembly(ctx, options) {
|
|
|
29323
29736
|
mounts.delete(sessionId);
|
|
29324
29737
|
await current.fiber.dispose();
|
|
29325
29738
|
};
|
|
29326
|
-
const reject = (agent, item) => {
|
|
29739
|
+
const reject = (agent, item, error) => {
|
|
29327
29740
|
let rejected = rejectedVersions.get(agent);
|
|
29328
29741
|
if (rejected === void 0) {
|
|
29329
29742
|
rejected = /* @__PURE__ */ new Map();
|
|
@@ -29331,186 +29744,255 @@ function createAgentAssembly(ctx, options) {
|
|
|
29331
29744
|
}
|
|
29332
29745
|
let versions = rejected.get(item.moduleId);
|
|
29333
29746
|
if (versions === void 0) {
|
|
29334
|
-
versions = /* @__PURE__ */ new
|
|
29747
|
+
versions = /* @__PURE__ */ new Map();
|
|
29335
29748
|
rejected.set(item.moduleId, versions);
|
|
29336
29749
|
}
|
|
29337
|
-
versions.
|
|
29750
|
+
versions.set(sourceVersions.get(item) ?? "", failureReason(error));
|
|
29338
29751
|
if (lastGood.get(agent)?.get(item.moduleId) === item) lastGood.get(agent)?.delete(item.moduleId);
|
|
29339
29752
|
};
|
|
29340
|
-
const mount = async (agent, prepared, plan, duplicateIdentities = [], stamp = "", content = "") => {
|
|
29341
|
-
|
|
29342
|
-
|
|
29343
|
-
|
|
29344
|
-
|
|
29345
|
-
|
|
29753
|
+
const mount = async (agent, prepared, plan, duplicateIdentities = [], stamp = "", content = "", personaSignature = "") => {
|
|
29754
|
+
for (const item of prepared) for (const name of item.services) if (agent.ctx.get(name) === void 0) throw Object.assign(/* @__PURE__ */ new Error(`模块 ${item.moduleId} 挂载所需宿主能力不可用:${name}`), { sourceModuleId: item.moduleId });
|
|
29755
|
+
let current = mounts.get(agent.id);
|
|
29756
|
+
if (current === void 0) {
|
|
29757
|
+
let scope;
|
|
29758
|
+
const root = agent.ctx.plugin({
|
|
29759
|
+
name: "prompt-tool-assembly",
|
|
29760
|
+
apply: (scopeCtx) => {
|
|
29761
|
+
scope = scopeCtx;
|
|
29762
|
+
}
|
|
29763
|
+
});
|
|
29764
|
+
try {
|
|
29765
|
+
await root;
|
|
29766
|
+
} catch (error) {
|
|
29767
|
+
await root.dispose();
|
|
29768
|
+
throw error;
|
|
29769
|
+
}
|
|
29770
|
+
if (scope === void 0) {
|
|
29771
|
+
await root.dispose();
|
|
29772
|
+
throw new Error("运行时配装作用域未初始化");
|
|
29773
|
+
}
|
|
29774
|
+
let rules;
|
|
29775
|
+
try {
|
|
29776
|
+
rules = createRuleRuntime(scope, {
|
|
29777
|
+
agent,
|
|
29778
|
+
onOutcome: ruleDiagnostics.record,
|
|
29779
|
+
variableStore,
|
|
29780
|
+
standingMountFor: await loadStandingMountFor(),
|
|
29781
|
+
manifestCheck
|
|
29782
|
+
});
|
|
29783
|
+
} catch (error) {
|
|
29784
|
+
await root.dispose();
|
|
29785
|
+
throw error;
|
|
29786
|
+
}
|
|
29787
|
+
const record = {
|
|
29788
|
+
agent,
|
|
29789
|
+
scope,
|
|
29790
|
+
rules,
|
|
29791
|
+
modules: /* @__PURE__ */ new Map(),
|
|
29792
|
+
shared: /* @__PURE__ */ new Map(),
|
|
29793
|
+
prepared: [],
|
|
29794
|
+
moduleIds: [],
|
|
29795
|
+
stamp: "",
|
|
29796
|
+
content: "",
|
|
29797
|
+
personaSignature: "",
|
|
29798
|
+
plan: {
|
|
29799
|
+
sections: [],
|
|
29800
|
+
suppressRuntimeContext: false
|
|
29801
|
+
},
|
|
29802
|
+
live: true,
|
|
29803
|
+
committed: false,
|
|
29804
|
+
mutating: false,
|
|
29805
|
+
fiber: { dispose: () => {} }
|
|
29806
|
+
};
|
|
29807
|
+
const disposeFiber = ctx.effect(() => () => {
|
|
29808
|
+
record.live = false;
|
|
29809
|
+
for (const slot of [...record.modules.values(), ...record.shared.values()]) {
|
|
29810
|
+
slot.live = false;
|
|
29811
|
+
slot.off();
|
|
29812
|
+
}
|
|
29813
|
+
rules.dispose();
|
|
29814
|
+
return root.dispose();
|
|
29815
|
+
}, `prompt-tool assembly ${agent.id}`);
|
|
29816
|
+
record.fiber = { dispose: async () => {
|
|
29817
|
+
await disposeFiber();
|
|
29818
|
+
} };
|
|
29819
|
+
mounts.set(agent.id, record);
|
|
29820
|
+
current = record;
|
|
29821
|
+
}
|
|
29822
|
+
const record = current;
|
|
29346
29823
|
const promote = () => {
|
|
29347
|
-
if (!live || !
|
|
29824
|
+
if (!record.live || !record.committed || record.mutating || !active || disposed.has(agent)) return;
|
|
29348
29825
|
let good = lastGood.get(agent);
|
|
29349
29826
|
if (good === void 0) {
|
|
29350
29827
|
good = /* @__PURE__ */ new Map();
|
|
29351
29828
|
lastGood.set(agent, good);
|
|
29352
29829
|
}
|
|
29353
|
-
for (const item of prepared) if (
|
|
29830
|
+
for (const item of record.prepared) if ([...record.modules.values(), ...record.shared.values()].filter((slot) => slot.owners.includes(item)).every((slot) => slot.ready && slot.failed === void 0)) good.set(item.moduleId, item);
|
|
29354
29831
|
};
|
|
29355
|
-
const
|
|
29356
|
-
|
|
29357
|
-
|
|
29358
|
-
|
|
29359
|
-
|
|
29832
|
+
const disposeSlot = async (slot) => {
|
|
29833
|
+
slot.live = false;
|
|
29834
|
+
slot.off();
|
|
29835
|
+
await slot.fiber.dispose();
|
|
29836
|
+
};
|
|
29837
|
+
const applyCapability = async (scopeCtx, item, module) => {
|
|
29838
|
+
const result = await module.apply(scopeCtx, module.config, {
|
|
29839
|
+
agent,
|
|
29840
|
+
sourceModuleId: item.moduleId,
|
|
29841
|
+
sourceModuleDir: resolveModuleDir(item.moduleId, options.moduleRoot),
|
|
29842
|
+
recoveryState,
|
|
29843
|
+
contextRuntimeOf
|
|
29844
|
+
});
|
|
29845
|
+
if (typeof result === "function") scopeCtx.effect(() => result, module.id);
|
|
29846
|
+
};
|
|
29847
|
+
const createSlot = async (map, key, owners, apply, signature) => {
|
|
29848
|
+
const fiber = record.scope.plugin({
|
|
29849
|
+
name: `prompt-tool-${map === record.modules ? "module" : "shared"}:${key}`,
|
|
29850
|
+
inject: [...new Set(owners.flatMap((item) => [...item.services]))],
|
|
29851
|
+
apply
|
|
29852
|
+
});
|
|
29853
|
+
const slot = {
|
|
29854
|
+
fiber,
|
|
29855
|
+
owners,
|
|
29856
|
+
ready: false,
|
|
29857
|
+
live: true,
|
|
29858
|
+
off: () => {},
|
|
29859
|
+
...signature === void 0 ? {} : { signature }
|
|
29860
|
+
};
|
|
29861
|
+
map.set(key, slot);
|
|
29862
|
+
slot.off = initialization.observe(fiber, {
|
|
29360
29863
|
ready: () => {
|
|
29361
|
-
|
|
29362
|
-
|
|
29864
|
+
if (slot.live) {
|
|
29865
|
+
slot.ready = true;
|
|
29866
|
+
promote();
|
|
29867
|
+
}
|
|
29363
29868
|
},
|
|
29364
29869
|
failed: (error) => {
|
|
29365
|
-
if (!live || !active || disposed.has(agent)) return;
|
|
29366
|
-
|
|
29367
|
-
|
|
29368
|
-
|
|
29369
|
-
|
|
29370
|
-
|
|
29371
|
-
|
|
29372
|
-
|
|
29373
|
-
if (!live || !active || disposed.has(agent)) return;
|
|
29374
|
-
try {
|
|
29375
|
-
await replace([agent]);
|
|
29376
|
-
} catch (failure) {
|
|
29377
|
-
warn(failure);
|
|
29378
|
-
}
|
|
29379
|
-
});
|
|
29380
|
-
warn(new Error(`模块 ${owners.map((item) => item.moduleId).join("、")} 初始化失败:${failureReason(error)}`, { cause: error }));
|
|
29870
|
+
if (!slot.live || !record.live || !active || disposed.has(agent) || map.get(key) !== slot) return;
|
|
29871
|
+
slot.failed = error;
|
|
29872
|
+
if (record.mutating || !record.committed) return;
|
|
29873
|
+
for (const item of slot.owners) {
|
|
29874
|
+
reject(agent, item, error);
|
|
29875
|
+
publication.schedule(item.moduleId);
|
|
29876
|
+
}
|
|
29877
|
+
warn(new Error(`模块 ${slot.owners.map((item) => item.moduleId).join("、")} 初始化失败:${failureReason(error)}`, { cause: error }));
|
|
29381
29878
|
}
|
|
29382
|
-
})
|
|
29879
|
+
});
|
|
29880
|
+
try {
|
|
29881
|
+
await fiber;
|
|
29882
|
+
await initialization.settled([fiber]);
|
|
29883
|
+
if (slot.failed !== void 0) throw slot.failed;
|
|
29884
|
+
} catch (error) {
|
|
29885
|
+
await disposeSlot(slot);
|
|
29886
|
+
map.delete(key);
|
|
29887
|
+
throw Object.assign(new Error(`模块 ${owners.map((item) => item.moduleId).join("、")} 挂载失败:${failureReason(error)}`, { cause: error }), { sourceModuleIds: owners.map((item) => item.moduleId) });
|
|
29888
|
+
}
|
|
29383
29889
|
};
|
|
29384
|
-
|
|
29385
|
-
|
|
29386
|
-
|
|
29387
|
-
|
|
29388
|
-
|
|
29389
|
-
|
|
29390
|
-
|
|
29391
|
-
|
|
29392
|
-
|
|
29393
|
-
|
|
29394
|
-
|
|
29395
|
-
|
|
29396
|
-
|
|
29397
|
-
|
|
29890
|
+
record.mutating = true;
|
|
29891
|
+
try {
|
|
29892
|
+
record.rules.replace(prepared.filter((item) => item.rules.length > 0).map((item) => ({
|
|
29893
|
+
moduleId: item.moduleId,
|
|
29894
|
+
rules: item.rules
|
|
29895
|
+
})));
|
|
29896
|
+
const desired = new Set(prepared.map((item) => item.moduleId));
|
|
29897
|
+
for (const [id, slot] of record.modules) if (!desired.has(id) || !prepared.includes(slot.owners[0]) || !slot.live || slot.failed !== void 0) {
|
|
29898
|
+
await disposeSlot(slot);
|
|
29899
|
+
record.modules.delete(id);
|
|
29900
|
+
}
|
|
29901
|
+
for (const item of prepared) {
|
|
29902
|
+
const capabilities = item.modules.filter((module) => PRIVATE_SERVICES[module.id] === void 0 || module.id === "retrieval");
|
|
29903
|
+
if (capabilities.length > 0 && !record.modules.has(item.moduleId)) await createSlot(record.modules, item.moduleId, [item], async (scopeCtx) => {
|
|
29904
|
+
for (const module of capabilities) await applyCapability(scopeCtx, item, module);
|
|
29905
|
+
});
|
|
29906
|
+
}
|
|
29907
|
+
const shared = /* @__PURE__ */ new Map();
|
|
29908
|
+
for (const item of prepared) for (const module of item.modules) {
|
|
29909
|
+
if (PRIVATE_SERVICES[module.id] === void 0 || module.id === "retrieval" || shared.has(module.id)) continue;
|
|
29910
|
+
const owners = prepared.filter((source) => source.modules.some((candidate) => candidate.id === module.id));
|
|
29911
|
+
shared.set(module.id, {
|
|
29912
|
+
owners,
|
|
29913
|
+
item,
|
|
29914
|
+
module,
|
|
29915
|
+
signature: JSON.stringify([
|
|
29916
|
+
owners.map((owner) => owner.moduleId),
|
|
29917
|
+
item.moduleId,
|
|
29918
|
+
module.config
|
|
29919
|
+
])
|
|
29920
|
+
});
|
|
29921
|
+
}
|
|
29922
|
+
for (const [id, slot] of record.shared) if (shared.get(id)?.signature !== slot.signature || !slot.live || slot.failed !== void 0) {
|
|
29923
|
+
await disposeSlot(slot);
|
|
29924
|
+
record.shared.delete(id);
|
|
29925
|
+
}
|
|
29926
|
+
for (const [id, entry] of shared) {
|
|
29927
|
+
const old = record.shared.get(id);
|
|
29928
|
+
if (old !== void 0) old.owners = entry.owners;
|
|
29929
|
+
else await createSlot(record.shared, id, entry.owners, (scopeCtx) => applyCapability(scopeCtx, entry.item, entry.module), entry.signature);
|
|
29930
|
+
}
|
|
29931
|
+
const personaKey = JSON.stringify([
|
|
29932
|
+
personaSignature,
|
|
29933
|
+
plan.suppressRuntimeContext,
|
|
29934
|
+
plan.sections.map((section) => ({
|
|
29935
|
+
...section,
|
|
29936
|
+
text: String(section.text)
|
|
29937
|
+
}))
|
|
29938
|
+
]);
|
|
29939
|
+
if (record.persona?.signature !== personaKey) {
|
|
29940
|
+
if (record.persona !== void 0) {
|
|
29941
|
+
await record.persona.fiber.dispose();
|
|
29942
|
+
delete record.persona;
|
|
29398
29943
|
}
|
|
29399
|
-
|
|
29400
|
-
|
|
29401
|
-
|
|
29402
|
-
|
|
29403
|
-
|
|
29404
|
-
|
|
29405
|
-
|
|
29406
|
-
|
|
29407
|
-
|
|
29408
|
-
|
|
29409
|
-
|
|
29410
|
-
|
|
29411
|
-
|
|
29412
|
-
|
|
29413
|
-
|
|
29414
|
-
|
|
29415
|
-
|
|
29416
|
-
|
|
29417
|
-
while (applied.length > 0) applied.pop()?.();
|
|
29418
|
-
};
|
|
29419
|
-
try {
|
|
29420
|
-
for (const section of plan.sections) {
|
|
29421
|
-
(scope === void 0 ? void 0 : capture?.records(scope).find((record) => record.name === section.name))?.off();
|
|
29422
|
-
applied.push(scopeCtx.systemPrompt.section(section));
|
|
29944
|
+
if (plan.sections.length > 0 || plan.suppressRuntimeContext) {
|
|
29945
|
+
const fiber = record.scope.plugin({
|
|
29946
|
+
name: "prompt-tool-persona",
|
|
29947
|
+
inject: ["systemPrompt"],
|
|
29948
|
+
apply: (scopeCtx) => {
|
|
29949
|
+
const applied = [], scope = scopeOf(scopeCtx);
|
|
29950
|
+
const rollback = () => {
|
|
29951
|
+
while (applied.length > 0) applied.pop()?.();
|
|
29952
|
+
};
|
|
29953
|
+
try {
|
|
29954
|
+
for (const section of plan.sections) {
|
|
29955
|
+
if (scope !== void 0) options.personaCapture?.records(scope).find((record) => record.name === section.name)?.off();
|
|
29956
|
+
applied.push(scopeCtx.systemPrompt.section(section));
|
|
29957
|
+
}
|
|
29958
|
+
if (plan.suppressRuntimeContext) applied.push(scopeCtx.systemPrompt.suppressRuntimeContext());
|
|
29959
|
+
} catch (error) {
|
|
29960
|
+
rollback();
|
|
29961
|
+
throw error;
|
|
29423
29962
|
}
|
|
29424
|
-
|
|
29425
|
-
} catch (error) {
|
|
29426
|
-
rollback();
|
|
29427
|
-
throw error;
|
|
29428
|
-
}
|
|
29429
|
-
return rollback;
|
|
29430
|
-
}, "prompt-tool persona");
|
|
29431
|
-
}
|
|
29432
|
-
const applyCapability = async (capabilityCtx, item, module) => {
|
|
29433
|
-
const result = await module.apply(capabilityCtx, module.config, {
|
|
29434
|
-
agent,
|
|
29435
|
-
sourceModuleId: item.moduleId,
|
|
29436
|
-
sourceModuleDir: resolveModuleDir(item.moduleId, options.moduleRoot),
|
|
29437
|
-
recoveryState,
|
|
29438
|
-
contextRuntimeOf
|
|
29439
|
-
});
|
|
29440
|
-
if (typeof result === "function") capabilityCtx.effect(() => result, module.id);
|
|
29441
|
-
};
|
|
29442
|
-
const ownTokens = new Map(prepared.map((item) => [item, {}]));
|
|
29443
|
-
for (const item of prepared) waiting.get(item)?.add(ownTokens.get(item));
|
|
29444
|
-
for (const item of prepared) {
|
|
29445
|
-
const capabilities = item.modules.filter((module) => PRIVATE_SERVICES[module.id] === void 0 || module.id === "retrieval");
|
|
29446
|
-
if (capabilities.length === 0) continue;
|
|
29447
|
-
const child = scopeCtx.plugin({
|
|
29448
|
-
name: `prompt-tool-module:${item.moduleId}`,
|
|
29449
|
-
apply: async (moduleCtx) => {
|
|
29450
|
-
for (const module of capabilities) await applyCapability(moduleCtx, item, module);
|
|
29451
|
-
}
|
|
29452
|
-
});
|
|
29453
|
-
observe(child, [item]);
|
|
29454
|
-
try {
|
|
29455
|
-
await child;
|
|
29456
|
-
} catch (error) {
|
|
29457
|
-
await child.dispose();
|
|
29458
|
-
throw Object.assign(new Error(`模块 ${item.moduleId} 挂载失败:${failureReason(error)}`, { cause: error }), { sourceModuleId: item.moduleId });
|
|
29459
|
-
}
|
|
29460
|
-
}
|
|
29461
|
-
const privateMounted = /* @__PURE__ */ new Set();
|
|
29462
|
-
for (const item of prepared) for (const module of item.modules) {
|
|
29463
|
-
if (PRIVATE_SERVICES[module.id] === void 0 || module.id === "retrieval" || privateMounted.has(module.id)) continue;
|
|
29464
|
-
const owners = prepared.filter((source) => source.modules.some((candidate) => candidate.id === module.id));
|
|
29465
|
-
const child = scopeCtx.plugin({
|
|
29466
|
-
name: `prompt-tool-shared:${module.id}`,
|
|
29467
|
-
apply: async (sharedCtx) => {
|
|
29468
|
-
await applyCapability(sharedCtx, item, module);
|
|
29963
|
+
scopeCtx.effect(() => rollback, "prompt-tool persona");
|
|
29469
29964
|
}
|
|
29470
29965
|
});
|
|
29471
|
-
observe(child, owners);
|
|
29472
29966
|
try {
|
|
29473
|
-
await
|
|
29967
|
+
await fiber;
|
|
29474
29968
|
} catch (error) {
|
|
29475
|
-
|
|
29969
|
+
await fiber.dispose();
|
|
29970
|
+
throw error;
|
|
29476
29971
|
}
|
|
29477
|
-
|
|
29972
|
+
record.persona = {
|
|
29973
|
+
fiber,
|
|
29974
|
+
signature: personaKey
|
|
29975
|
+
};
|
|
29478
29976
|
}
|
|
29479
|
-
for (const item of prepared) waiting.get(item)?.delete(ownTokens.get(item));
|
|
29480
29977
|
}
|
|
29481
|
-
|
|
29482
|
-
|
|
29483
|
-
|
|
29484
|
-
for (const off of observers) off();
|
|
29485
|
-
return fiber.dispose();
|
|
29486
|
-
}, `prompt-tool assembly ${agent.id}`);
|
|
29487
|
-
try {
|
|
29488
|
-
await fiber;
|
|
29489
|
-
await initialization.settled(initializationRoots);
|
|
29490
|
-
if (initializationErrors.length > 0) {
|
|
29491
|
-
const failure = initializationErrors[0];
|
|
29492
|
-
throw Object.assign(new Error(`模块 ${failure.owners.map((item) => item.moduleId).join("、")} 初始化失败:${failureReason(failure.error)}`, { cause: failure.error }), { sourceModuleIds: failure.owners.map((item) => item.moduleId) });
|
|
29978
|
+
if (!active || disposed.has(agent)) {
|
|
29979
|
+
await release(agent.id, agent);
|
|
29980
|
+
return;
|
|
29493
29981
|
}
|
|
29494
|
-
|
|
29495
|
-
|
|
29496
|
-
|
|
29497
|
-
|
|
29498
|
-
|
|
29499
|
-
|
|
29500
|
-
|
|
29982
|
+
record.prepared = prepared;
|
|
29983
|
+
record.moduleIds = prepared.map((item) => item.moduleId);
|
|
29984
|
+
record.stamp = stamp;
|
|
29985
|
+
record.content = content;
|
|
29986
|
+
record.plan = plan;
|
|
29987
|
+
record.personaSignature = personaSignature;
|
|
29988
|
+
record.committed = true;
|
|
29989
|
+
for (const item of duplicateIdentities) {
|
|
29990
|
+
const where = item.channel === "kind" ? `显式 sourceKind ${JSON.stringify(item.identity)}` : `去重身份 ${JSON.stringify(item.identity)}`;
|
|
29991
|
+
warnOnce(item.suspectedCopy ? `模块 ${item.moduleIds.join("、")} 疑似由复制产生同一个${where}(dedupe: session/batch):去重按模块各记一份,两份正文都会注入,请改 rule id 或显式 identity 以区分` : `模块 ${item.moduleIds.join("、")} 声明了同一个${where}(dedupe: session/batch):去重按模块各记一份,两模块各自注入;同一模块内才共享这份去重`);
|
|
29992
|
+
}
|
|
29993
|
+
} finally {
|
|
29994
|
+
record.mutating = false;
|
|
29501
29995
|
}
|
|
29502
|
-
mounts.set(agent.id, {
|
|
29503
|
-
agent,
|
|
29504
|
-
fiber: { dispose: async () => {
|
|
29505
|
-
await disposeFiber();
|
|
29506
|
-
} },
|
|
29507
|
-
prepared,
|
|
29508
|
-
moduleIds: prepared.map((item) => item.moduleId),
|
|
29509
|
-
stamp,
|
|
29510
|
-
content,
|
|
29511
|
-
plan
|
|
29512
|
-
});
|
|
29513
|
-
mounted = true;
|
|
29514
29996
|
promote();
|
|
29515
29997
|
};
|
|
29516
29998
|
const assemblyStamp = (ids, personas) => JSON.stringify(personas) + readModulesRevision(options.moduleRoot, ids);
|
|
@@ -29534,7 +30016,23 @@ function createAgentAssembly(ctx, options) {
|
|
|
29534
30016
|
}
|
|
29535
30017
|
for (const file of files) if (!watched.has(file)) {
|
|
29536
30018
|
const listener = () => {
|
|
29537
|
-
if (active)
|
|
30019
|
+
if (!active) return;
|
|
30020
|
+
try {
|
|
30021
|
+
const ids = options.enabledModules(), personas = options.personaModules?.(), stamp = assemblyStamp(ids, personas);
|
|
30022
|
+
if (publishingContent !== void 0 && contentSignature(ids, personas) === publishingContent) return;
|
|
30023
|
+
const agents = /* @__PURE__ */ new Set([...knownAgents, ...ctx.get("agents")?.list() ?? []]);
|
|
30024
|
+
let changed = false;
|
|
30025
|
+
for (const agent of agents) {
|
|
30026
|
+
if (disposed.has(agent)) continue;
|
|
30027
|
+
const current = mounts.get(agent.id);
|
|
30028
|
+
if (current?.stamp === stamp) continue;
|
|
30029
|
+
if (current !== void 0 && current.content === contentSignature(ids, personas, current.content)) current.stamp = stamp;
|
|
30030
|
+
else changed = true;
|
|
30031
|
+
}
|
|
30032
|
+
if (changed) publication.schedule();
|
|
30033
|
+
} catch {
|
|
30034
|
+
publication.schedule();
|
|
30035
|
+
}
|
|
29538
30036
|
};
|
|
29539
30037
|
watched.set(file, listener);
|
|
29540
30038
|
watchFile(file, {
|
|
@@ -29543,7 +30041,7 @@ function createAgentAssembly(ctx, options) {
|
|
|
29543
30041
|
}, listener);
|
|
29544
30042
|
}
|
|
29545
30043
|
};
|
|
29546
|
-
const replace = async (targets, retry = false) => {
|
|
30044
|
+
const replace = async (targets, retry = false, attempt = 0) => {
|
|
29547
30045
|
readGlobalLayerSettings(options.moduleRoot);
|
|
29548
30046
|
const ids = [...options.enabledModules()];
|
|
29549
30047
|
const personaModules = options.personaModules?.();
|
|
@@ -29551,36 +30049,48 @@ function createAgentAssembly(ctx, options) {
|
|
|
29551
30049
|
const live = targets.filter((agent) => active && !disposed.has(agent));
|
|
29552
30050
|
const failures = [];
|
|
29553
30051
|
const candidates = [];
|
|
30052
|
+
const signatureSnapshot = contentSignature(ids, personaModules);
|
|
30053
|
+
const versions = new Map(ids.map((id) => [id, contentSignature([id], void 0)]));
|
|
29554
30054
|
for (const agent of live) {
|
|
29555
30055
|
const previous = mounts.get(agent.id);
|
|
29556
30056
|
if (retry === true) rejectedVersions.delete(agent);
|
|
29557
|
-
else if (
|
|
30057
|
+
else if (Array.isArray(retry)) for (const id of retry) rejectedVersions.get(agent)?.delete(id);
|
|
29558
30058
|
const good = lastGood.get(agent);
|
|
29559
30059
|
const goodSnapshot = good === void 0 ? void 0 : new Map(good);
|
|
29560
30060
|
const prepared = [];
|
|
29561
|
-
for (const id of ids)
|
|
29562
|
-
|
|
29563
|
-
|
|
29564
|
-
|
|
29565
|
-
|
|
30061
|
+
for (const id of ids) {
|
|
30062
|
+
try {
|
|
30063
|
+
const version = versions.get(id);
|
|
30064
|
+
const old = previous?.prepared.find((item) => item.moduleId === id);
|
|
30065
|
+
const item = old !== void 0 && sourceVersions.get(old) === version ? old : await prepareAssembly(options.moduleRoot, id, (name) => agent.ctx.get(name) !== void 0);
|
|
30066
|
+
sourceVersions.set(item, version);
|
|
30067
|
+
if (rejectedVersions.get(agent)?.get(id)?.has(version)) {
|
|
30068
|
+
failures.push(/* @__PURE__ */ new Error(`模块 ${id}(Agent ${agent.id})上次发布失败:${rejectedVersions.get(agent).get(id).get(version)}`));
|
|
30069
|
+
const fallback = good?.get(id);
|
|
30070
|
+
if (fallback !== void 0) prepared.push(fallback);
|
|
30071
|
+
} else {
|
|
30072
|
+
rejectedVersions.get(agent)?.delete(id);
|
|
30073
|
+
prepared.push(item);
|
|
30074
|
+
}
|
|
30075
|
+
} catch (error) {
|
|
30076
|
+
failures.push(new Error(`模块 ${id}(Agent ${agent.id})准备失败:${failureReason(error)}`, { cause: error }));
|
|
29566
30077
|
const fallback = good?.get(id);
|
|
29567
30078
|
if (fallback !== void 0) prepared.push(fallback);
|
|
29568
|
-
} else {
|
|
29569
|
-
rejectedVersions.get(agent)?.delete(id);
|
|
29570
|
-
prepared.push(item);
|
|
29571
30079
|
}
|
|
29572
|
-
|
|
29573
|
-
failures.push(new Error(`模块 ${id}(Agent ${agent.id})准备失败:${failureReason(error)}`, { cause: error }));
|
|
29574
|
-
const fallback = good?.get(id);
|
|
29575
|
-
if (fallback !== void 0) prepared.push(fallback);
|
|
30080
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
29576
30081
|
}
|
|
29577
30082
|
candidates.push({
|
|
29578
30083
|
agent,
|
|
29579
30084
|
prepared,
|
|
29580
|
-
previous,
|
|
30085
|
+
previous: previous === void 0 ? void 0 : { ...previous },
|
|
29581
30086
|
goodSnapshot
|
|
29582
30087
|
});
|
|
29583
30088
|
}
|
|
30089
|
+
if (JSON.stringify(options.enabledModules()) !== JSON.stringify(ids) || contentSignature(ids, options.personaModules?.()) !== signatureSnapshot) {
|
|
30090
|
+
if (attempt < 3) return replace(targets, retry, attempt + 1);
|
|
30091
|
+
publication.schedule();
|
|
30092
|
+
throw new Error("模块定义在准备期间持续变化,已安排重新发布");
|
|
30093
|
+
}
|
|
29584
30094
|
const stamp = assemblyStamp(ids, personaModules);
|
|
29585
30095
|
for (const item of candidates.flatMap((candidate) => candidate.prepared)) for (const id of item.skippedOfficialRows) warnOnce(`模块 ${item.moduleId} 声明官方 recipe 行 ${id};该行只能由会话原有预设提供,本插件不挂载官方包`);
|
|
29586
30096
|
if (!active) return;
|
|
@@ -29611,11 +30121,15 @@ function createAgentAssembly(ctx, options) {
|
|
|
29611
30121
|
for (const [index, candidate] of candidates.entries()) {
|
|
29612
30122
|
if (!active || disposed.has(candidate.agent)) continue;
|
|
29613
30123
|
changed.push(candidate);
|
|
29614
|
-
|
|
29615
|
-
const
|
|
30124
|
+
const content = signatureSnapshot;
|
|
30125
|
+
const personaSignature = JSON.stringify(personaModules ?? candidate.prepared.map(({ moduleId, persona, variablesEnabled }) => ({
|
|
30126
|
+
moduleId,
|
|
30127
|
+
persona,
|
|
30128
|
+
variablesEnabled
|
|
30129
|
+
})));
|
|
29616
30130
|
let plan = plans[index];
|
|
29617
30131
|
while (true) try {
|
|
29618
|
-
await mount(candidate.agent, candidate.prepared, plan, duplicateDedupeIdentities(candidate.prepared), stamp, content);
|
|
30132
|
+
await mount(candidate.agent, candidate.prepared, plan, duplicateDedupeIdentities(candidate.prepared), stamp, content, personaSignature);
|
|
29619
30133
|
break;
|
|
29620
30134
|
} catch (error) {
|
|
29621
30135
|
const sourceIds = error !== null && typeof error === "object" ? "sourceModuleIds" in error && Array.isArray(error.sourceModuleIds) ? error.sourceModuleIds : "sourceModuleId" in error ? [error.sourceModuleId] : [] : [];
|
|
@@ -29623,7 +30137,7 @@ function createAgentAssembly(ctx, options) {
|
|
|
29623
30137
|
if (failed.length === 0) throw error;
|
|
29624
30138
|
for (const item of failed) {
|
|
29625
30139
|
failures.push(new Error(`模块 ${item.moduleId}(Agent ${candidate.agent.id})发布失败:${failureReason(error)}`, { cause: error }));
|
|
29626
|
-
reject(candidate.agent, item);
|
|
30140
|
+
reject(candidate.agent, item, error);
|
|
29627
30141
|
}
|
|
29628
30142
|
candidate.prepared = candidate.prepared.flatMap((item) => {
|
|
29629
30143
|
if (!failed.includes(item)) return [item];
|
|
@@ -29632,18 +30146,24 @@ function createAgentAssembly(ctx, options) {
|
|
|
29632
30146
|
});
|
|
29633
30147
|
plan = planFor(candidate.agent, candidate.prepared);
|
|
29634
30148
|
}
|
|
30149
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
29635
30150
|
}
|
|
29636
30151
|
} catch (error) {
|
|
29637
30152
|
const restoreErrors = [];
|
|
29638
30153
|
for (const { agent, previous, goodSnapshot } of changed.reverse()) {
|
|
29639
30154
|
if (!active || disposed.has(agent)) continue;
|
|
29640
30155
|
try {
|
|
29641
|
-
await release(agent.id);
|
|
29642
30156
|
if (goodSnapshot === void 0) lastGood.delete(agent);
|
|
29643
30157
|
else lastGood.set(agent, new Map(goodSnapshot));
|
|
29644
|
-
if (previous?.agent === agent) await mount(agent, previous.prepared, previous.plan, [], previous.stamp, previous.content);
|
|
30158
|
+
if (previous?.agent === agent) await mount(agent, previous.prepared, previous.plan, [], previous.stamp, previous.content, previous.personaSignature);
|
|
30159
|
+
else await release(agent.id, agent);
|
|
29645
30160
|
} catch (restoreError) {
|
|
29646
30161
|
restoreErrors.push(restoreError);
|
|
30162
|
+
try {
|
|
30163
|
+
await release(agent.id, agent);
|
|
30164
|
+
} catch (cleanupError) {
|
|
30165
|
+
restoreErrors.push(cleanupError);
|
|
30166
|
+
}
|
|
29647
30167
|
}
|
|
29648
30168
|
}
|
|
29649
30169
|
if (restoreErrors.length > 0) throw new AggregateError([error, ...restoreErrors], `切换装配失败(${failureReason(error)}),且恢复原有装配也失败(${restoreErrors.map(failureReason).join(";")})`);
|
|
@@ -29658,12 +30178,40 @@ function createAgentAssembly(ctx, options) {
|
|
|
29658
30178
|
const install = async (agent) => {
|
|
29659
30179
|
knownAgents.add(agent);
|
|
29660
30180
|
if (!active || disposed.has(agent) || mounts.get(agent.id)?.agent === agent) return;
|
|
29661
|
-
|
|
29662
|
-
|
|
30181
|
+
publishingContent = contentSignature(options.enabledModules(), options.personaModules?.());
|
|
30182
|
+
try {
|
|
30183
|
+
await replace([agent]);
|
|
30184
|
+
} finally {
|
|
30185
|
+
publishingContent = void 0;
|
|
30186
|
+
}
|
|
30187
|
+
};
|
|
30188
|
+
const publication = createPublicationQueue({
|
|
30189
|
+
warn: (message) => warn(message),
|
|
30190
|
+
publish: (moduleIds, retry) => serial(async () => {
|
|
30191
|
+
if (!active) return;
|
|
30192
|
+
const enabled = options.enabledModules();
|
|
30193
|
+
const personas = options.personaModules?.();
|
|
30194
|
+
const live = [.../* @__PURE__ */ new Set([
|
|
30195
|
+
...ctx.get("agents")?.list() ?? [],
|
|
30196
|
+
...knownAgents,
|
|
30197
|
+
...[...mounts.values()].map((mount) => mount.agent)
|
|
30198
|
+
])].filter((agent) => !disposed.has(agent));
|
|
30199
|
+
const targets = live.filter((agent) => moduleIds === void 0 || moduleIds.some((id) => enabled.includes(id) || mounts.get(agent.id)?.moduleIds.includes(id) || (personas ?? []).some((item) => item.moduleId === id && item.persona?.[isDelegated(agent.session) ? "subagent" : "main"] !== void 0)));
|
|
30200
|
+
publishingContent = contentSignature(enabled, personas);
|
|
30201
|
+
try {
|
|
30202
|
+
await replace(targets, retry);
|
|
30203
|
+
} finally {
|
|
30204
|
+
publishingContent = void 0;
|
|
30205
|
+
}
|
|
30206
|
+
return targets.length === live.length;
|
|
30207
|
+
})
|
|
30208
|
+
});
|
|
29663
30209
|
let lastReadError;
|
|
29664
|
-
const ensureFresh =
|
|
30210
|
+
const ensureFresh = async (agent) => {
|
|
29665
30211
|
if (!active || disposed.has(agent) || !knownAgents.has(agent)) return;
|
|
29666
30212
|
try {
|
|
30213
|
+
await publication.flush(void 0, false);
|
|
30214
|
+
await pending;
|
|
29667
30215
|
readGlobalLayerSettings(options.moduleRoot);
|
|
29668
30216
|
const ids = options.enabledModules(), personas = options.personaModules?.();
|
|
29669
30217
|
watchSources(ids, personas);
|
|
@@ -29671,7 +30219,10 @@ function createAgentAssembly(ctx, options) {
|
|
|
29671
30219
|
const current = mounts.get(agent.id);
|
|
29672
30220
|
if (current?.stamp !== stamp) {
|
|
29673
30221
|
if (current?.content === contentSignature(ids, personas, current?.content)) current.stamp = stamp;
|
|
29674
|
-
else
|
|
30222
|
+
else {
|
|
30223
|
+
publication.schedule();
|
|
30224
|
+
await publication.flush(void 0, false);
|
|
30225
|
+
}
|
|
29675
30226
|
}
|
|
29676
30227
|
lastReadError = void 0;
|
|
29677
30228
|
} catch (error) {
|
|
@@ -29679,7 +30230,7 @@ function createAgentAssembly(ctx, options) {
|
|
|
29679
30230
|
if (message !== lastReadError) warn(error);
|
|
29680
30231
|
lastReadError = message;
|
|
29681
30232
|
}
|
|
29682
|
-
}
|
|
30233
|
+
};
|
|
29683
30234
|
const listeners = [
|
|
29684
30235
|
ctx.on("internal/get", (_caller, name, _error, next) => {
|
|
29685
30236
|
const service = next();
|
|
@@ -29714,7 +30265,7 @@ function createAgentAssembly(ctx, options) {
|
|
|
29714
30265
|
for (const [file, listener] of watched) unwatchFile(file, listener);
|
|
29715
30266
|
watched.clear();
|
|
29716
30267
|
knownAgents.clear();
|
|
29717
|
-
return pending.then(async () => {
|
|
30268
|
+
return publication.dispose().then(() => pending).then(async () => {
|
|
29718
30269
|
for (const id of mounts.keys()) await release(id);
|
|
29719
30270
|
});
|
|
29720
30271
|
}, "prompt-tool assembly runtime");
|
|
@@ -29728,24 +30279,22 @@ function createAgentAssembly(ctx, options) {
|
|
|
29728
30279
|
let previous;
|
|
29729
30280
|
do {
|
|
29730
30281
|
await initialization.settled();
|
|
30282
|
+
await publication.settled();
|
|
29731
30283
|
previous = pending;
|
|
29732
30284
|
await previous;
|
|
29733
30285
|
} while (previous !== pending);
|
|
29734
30286
|
},
|
|
29735
|
-
hasMounted: (sessionId) => mounts.
|
|
30287
|
+
hasMounted: (sessionId) => mounts.get(sessionId)?.committed === true,
|
|
29736
30288
|
moduleIds: (sessionId) => mounts.get(sessionId)?.moduleIds ?? [],
|
|
29737
30289
|
ruleDiagnostics: () => active ? ruleDiagnostics.snapshot() : emptyRuleDiagnostics(),
|
|
30290
|
+
schedule: (moduleId) => {
|
|
30291
|
+
if (active) publication.schedule(moduleId);
|
|
30292
|
+
},
|
|
30293
|
+
publicationFailures: () => publication.failures(),
|
|
29738
30294
|
refresh: async (moduleId) => {
|
|
29739
30295
|
if (!active) throw new Error("运行时配装已释放");
|
|
29740
30296
|
try {
|
|
29741
|
-
await
|
|
29742
|
-
const enabled = options.enabledModules();
|
|
29743
|
-
const targets = [.../* @__PURE__ */ new Set([...ctx.get("agents")?.list() ?? [], ...[...mounts.values()].map((mount) => mount.agent)])].filter((agent) => {
|
|
29744
|
-
const current = mounts.get(agent.id);
|
|
29745
|
-
return options.personaModules !== void 0 || moduleId === void 0 || current === void 0 || current.moduleIds.includes(moduleId) || enabled.includes(moduleId);
|
|
29746
|
-
});
|
|
29747
|
-
await replace(targets, moduleId ?? true);
|
|
29748
|
-
});
|
|
30297
|
+
await publication.flush(moduleId, true);
|
|
29749
30298
|
} catch (error) {
|
|
29750
30299
|
throw new AggregateError([error], `运行时配装更新失败:${failureReason(error)}`);
|
|
29751
30300
|
}
|
|
@@ -29756,6 +30305,7 @@ function createAgentAssembly(ctx, options) {
|
|
|
29756
30305
|
for (const [file, listener] of watched) unwatchFile(file, listener);
|
|
29757
30306
|
watched.clear();
|
|
29758
30307
|
knownAgents.clear();
|
|
30308
|
+
await publication.dispose();
|
|
29759
30309
|
await pending;
|
|
29760
30310
|
for (const id of mounts.keys()) await release(id);
|
|
29761
30311
|
}
|
|
@@ -29879,6 +30429,11 @@ function apply(ctx, configIn) {
|
|
|
29879
30429
|
},
|
|
29880
30430
|
capabilityChanged: (id) => id === void 0 ? assembly?.refresh() : refreshModuleRuntime(id),
|
|
29881
30431
|
moduleListChanged: () => assembly?.refresh(),
|
|
30432
|
+
schedulePublication: (id, reason) => {
|
|
30433
|
+
if (reason === "installed") skillsRuntime.invalidate();
|
|
30434
|
+
assembly?.schedule(reason === "list" ? void 0 : id);
|
|
30435
|
+
},
|
|
30436
|
+
publicationFailures: () => assembly?.publicationFailures() ?? [],
|
|
29882
30437
|
ruleDiagnostics: () => assembly?.ruleDiagnostics() ?? emptyRuleDiagnostics(),
|
|
29883
30438
|
warn: (message) => warn(ctx, message)
|
|
29884
30439
|
});
|