dsh-plugin-prompt-tool 0.6.2 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -9
- package/engine/anchor-match.mjs +38 -12
- package/engine/anchor-turn.mjs +68 -0
- package/engine/classify-task.mjs +35 -0
- package/engine/code-presentation.mjs +103 -0
- package/engine/compositions/library/anchor-turn.yml +10 -0
- package/engine/compositions/library/bootstrap-filesystem.yml +1 -1
- package/engine/compositions/library/code-presentation.yml +8 -0
- package/engine/compositions/library/command-goal.yml +11 -0
- package/engine/compositions/library/compaction.yml +1 -1
- package/engine/compositions/library/context-gate.yml +1 -2
- package/engine/compositions/library/cot-drip.yml +11 -0
- package/engine/compositions/library/custom-bash.yml +1 -1
- package/engine/compositions/library/delegation.yml +11 -7
- package/engine/compositions/library/deliberation-gate.yml +11 -0
- package/engine/compositions/library/persistent-shell.yml +25 -2
- package/engine/compositions/library/persona.yml +6 -2
- package/engine/compositions/library/planning.yml +1 -1
- package/engine/compositions/library/prompt-config-engine.yml +1 -1
- package/engine/compositions/library/run-code-env.yml +1 -1
- package/engine/compositions/library/skill-filesystem.yml +1 -1
- package/engine/compositions/library/skill-search.yml +1 -1
- package/engine/compositions/library/str-replace-editor.yml +2 -2
- package/engine/compositions/library/tool-ask-user.yml +1 -1
- package/engine/compositions/library/tool-bash.yml +1 -1
- package/engine/compositions/library/tool-bootstrap.yml +1 -3
- package/engine/compositions/library/tool-config-engine.yml +9 -0
- package/engine/compositions/library/tool-filter.yml +3 -7
- package/engine/compositions/library/tool-fs-search.yml +1 -1
- package/engine/compositions/library/tool-fs.yml +1 -1
- package/engine/compositions/library/tool-goal.yml +1 -9
- package/engine/compositions/library/tool-jobs.yml +1 -1
- package/engine/compositions/library/tool-pwsh.yml +1 -1
- package/engine/compositions/library/tool-todo.yml +1 -1
- package/engine/compositions/library/tool-web.yml +2 -2
- package/engine/compositions/source/local/code-presentation.yml +8 -0
- package/engine/compositions/source/local/context-gate.yml +0 -1
- package/engine/compositions/source/local/str-replace-editor.yml +10 -0
- package/engine/compositions/source/local/tool-bootstrap.yml +1 -3
- package/engine/compositions/source/local/tool-config-engine.yml +9 -0
- package/engine/compositions/source/local/tool-filter.yml +8 -0
- package/engine/cot-drip.mjs +137 -0
- package/engine/custom-bash.mjs +73 -21
- package/engine/deliberation-gate.mjs +127 -0
- package/engine/layers.mjs +223 -198
- package/engine/run-code-env.mjs +8 -2
- package/engine/schema.mjs +1 -1
- package/engine/strategies.mjs +25 -14
- package/engine/tool-bootstrap.mjs +185 -59
- package/engine/tool-config-engine.mjs +390 -0
- package/lib/client.js +3840 -2311
- package/lib/client.js.map +1 -1
- package/lib/index.d.mts +185 -79
- package/lib/index.mjs +1000 -356
- package/lib/preset-core.d.mts +1 -1
- package/lib/preset-core.mjs +29 -3
- package/lib/{prompt-configs-BgFw_bFf.mjs → prompt-configs-BnQKRHVb.mjs} +211 -136
- package/lib/prompt-configs-CN0sJTUL.d.mts +193 -0
- package/package.json +121 -105
- package/preset/anchored/preset.yml +262 -308
- package/preset/creative/preset.yml +34 -32
- package/preset/custom/preset.yml +0 -1
- package/preset/liangshen/preset.yml +53 -50
- package/preset/minimal/preset.yml +18 -17
- package/preset/ptc/preset.yml +35 -33
- package/preset/standard/preset.yml +34 -32
- package/templates/10-pre-step.yml +18 -15
- package/templates/14-first-turn-anchor.yml +13 -13
- package/templates/15-guide-auto.yml +13 -13
- package/templates/16-custom-fallback.yml +19 -18
- package/templates/18-placeholder-env-facts.yml +13 -2
- package/templates/30-runtime-context.yml +3 -0
- package/templates/40-agent-request.yml +9 -9
- package/templates/60-tool-pipeline.yml +9 -8
- package/templates/tools/10-shell-command.yml +20 -0
- package/templates/tools/20-http-fetch.yml +24 -0
- package/templates/tools/30-fs-read.yml +20 -0
- package/templates/tools/40-delegate-character.yml +15 -0
- package/templates/tools/50-delegate-worldbook.yml +15 -0
- package/templates/tools/60-delegate-session-var.yml +15 -0
- package/templates/tools/70-delegate-worldbook-upsert.yml +36 -0
- package/lib/prompt-configs-B4vH09wx.d.mts +0 -100
- package/templates/11-merged-a.yml +0 -11
- package/templates/13-anchor.yml +0 -19
- package/templates/17-instruction-hint.yml +0 -23
- package/templates/19-placeholder-skill-catalog.yml +0 -19
- package/templates/31-runtime-context-placeholder.yml +0 -18
package/lib/preset-core.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as mergePromptConfigs, i as loadPromptConfigFiles, n as PromptConfigFile, o as renderPromptConfigYaml, r as PromptConfigSpec, t as BuildCordisOptions } from "./prompt-configs-
|
|
1
|
+
import { a as mergePromptConfigs, i as loadPromptConfigFiles, n as PromptConfigFile, o as renderPromptConfigYaml, r as PromptConfigSpec, t as BuildCordisOptions } from "./prompt-configs-CN0sJTUL.mjs";
|
|
2
2
|
//#region src/preset-core.d.ts
|
|
3
3
|
/**
|
|
4
4
|
* 渲染 anchored 组合文件:
|
package/lib/preset-core.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { h as loadPresetSpec, n as mergePromptConfigs, r as renderPromptConfigYaml, s as assertCompositionArray, t as loadPromptConfigFiles, x as renderComposition } from "./prompt-configs-BnQKRHVb.mjs";
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
3
|
//#region src/preset-core.ts
|
|
4
4
|
/**
|
|
@@ -21,8 +21,9 @@ function buildCordis(prompt, options = {}) {
|
|
|
21
21
|
firstTurnText: typeof options.firstTurnText === "string" ? options.firstTurnText : "",
|
|
22
22
|
guideCustom: options.guideCustom === true,
|
|
23
23
|
guideText: typeof options.guideText === "string" ? options.guideText : "",
|
|
24
|
+
guideEnabled: typeof options.guideEnabled === "boolean" ? options.guideEnabled : void 0,
|
|
24
25
|
injectPrompt: options.injectPrompt !== false,
|
|
25
|
-
usePtcMode: options.usePtcMode
|
|
26
|
+
usePtcMode: typeof options.usePtcMode === "boolean" ? options.usePtcMode : void 0,
|
|
26
27
|
bootstrapMaxTokens: Number.isSafeInteger(options.bootstrapMaxTokens) && (options.bootstrapMaxTokens ?? 0) > 0 ? options.bootstrapMaxTokens : 0,
|
|
27
28
|
modelProvider: typeof options.modelProvider === "string" && options.modelProvider.length > 0 ? options.modelProvider : "",
|
|
28
29
|
modelName: typeof options.modelName === "string" && options.modelName.length > 0 ? options.modelName : "",
|
|
@@ -34,11 +35,36 @@ function buildCordis(prompt, options = {}) {
|
|
|
34
35
|
subagentReasoningEffort: typeof options.subagentReasoningEffort === "string" ? options.subagentReasoningEffort : "",
|
|
35
36
|
subagentTemperature: typeof options.subagentTemperature === "string" ? options.subagentTemperature : "",
|
|
36
37
|
subagentMaxTokens: typeof options.subagentMaxTokens === "string" ? options.subagentMaxTokens : "",
|
|
37
|
-
subagentPersona: typeof options.subagentPersona === "string" && options.subagentPersona.length > 0 ? options.subagentPersona : "",
|
|
38
38
|
toolFilterAllow: options.toolFilterAllow,
|
|
39
39
|
toolFilterDeny: options.toolFilterDeny,
|
|
40
40
|
maxDepth: options.maxDepth,
|
|
41
41
|
allowKinds: options.allowKinds,
|
|
42
|
+
promoteGate: options.promoteGate,
|
|
43
|
+
promoteAfterFirstResponse: options.promoteAfterFirstResponse,
|
|
44
|
+
maxPromoteSteps: options.maxPromoteSteps,
|
|
45
|
+
bootstrapTools: options.bootstrapTools,
|
|
46
|
+
compactionTools: options.compactionTools,
|
|
47
|
+
personaSectionsOnly: options.personaSectionsOnly,
|
|
48
|
+
workspaceLine: options.workspaceLine,
|
|
49
|
+
messageSources: options.messageSources,
|
|
50
|
+
deferredSources: options.deferredSources,
|
|
51
|
+
deferredGraceSteps: options.deferredGraceSteps,
|
|
52
|
+
instructionHint: options.instructionHint,
|
|
53
|
+
phase1FirstCallInstruction: options.phase1FirstCallInstruction,
|
|
54
|
+
stages: options.stages,
|
|
55
|
+
stagePreUnlock: options.stagePreUnlock,
|
|
56
|
+
stageAdvanceTool: options.stageAdvanceTool,
|
|
57
|
+
stageAdvanceDescription: options.stageAdvanceDescription,
|
|
58
|
+
stageSectionTemplate: options.stageSectionTemplate,
|
|
59
|
+
toolFilterSubagents: options.toolFilterSubagents,
|
|
60
|
+
anchorTurn: options.anchorTurn,
|
|
61
|
+
anchorTurnText: options.anchorTurnText,
|
|
62
|
+
deliberationGate: options.deliberationGate,
|
|
63
|
+
deliberationMinChars: options.deliberationMinChars,
|
|
64
|
+
deliberationMaxGatesPerTurn: options.deliberationMaxGatesPerTurn,
|
|
65
|
+
cotDrip: options.cotDrip,
|
|
66
|
+
cotDripEvery: options.cotDripEvery,
|
|
67
|
+
cotDripMaxPerTurn: options.cotDripMaxPerTurn,
|
|
42
68
|
firstTurnWord: typeof options.firstTurnWord === "string" && options.firstTurnWord.length > 0 ? options.firstTurnWord : void 0
|
|
43
69
|
};
|
|
44
70
|
const out = renderComposition(spec, runtime, ANCHORED_TEMPLATE_DIR);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { Pair, Scalar, YAMLMap, YAMLSeq, parse, parseDocument } from "yaml";
|
|
1
|
+
import { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
3
2
|
import { basename, dirname, join, resolve, sep } from "node:path";
|
|
4
3
|
import { spawn } from "node:child_process";
|
|
5
4
|
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { Pair, Scalar, YAMLMap, YAMLSeq, parse, parseDocument } from "yaml";
|
|
6
6
|
import { homedir } from "node:os";
|
|
7
7
|
//#region src/host/paths.ts
|
|
8
8
|
/** host 数据层的部署路径与序数常量(settings 层与运行时共用,避免 host→config 反向依赖)。 */
|
|
@@ -56,9 +56,10 @@ const DEFAULT_SKILLS_DIR = SKILLS_DIR;
|
|
|
56
56
|
* 一个预设 = 一个 preset.yml:
|
|
57
57
|
* - modules/params/content/meta 全部是直读参数,无模板语法;
|
|
58
58
|
* - 默认提示词配置由引擎按 params 生成(见 write-preset),promptConfigs 仅为可选覆盖;
|
|
59
|
-
* -
|
|
60
|
-
*
|
|
61
|
-
*
|
|
59
|
+
* - 组合模块的行级 config 由参数桥 buildModuleConfigsFromParams 按 params
|
|
60
|
+
* 构造对象合并(取代旧 __TOKEN__ 文本渲染,无占位符、无文本往返),
|
|
61
|
+
* params(UI/基础层)优先于 moduleConfigs 行级直写(旧作者锁定语义已移除)。
|
|
62
|
+
* 本模块负责参数归一化与引擎模块配置装配;所有 anchored 专属行为都在引擎内部。
|
|
62
63
|
*/
|
|
63
64
|
/** 包根 preset/ 目录(配置/模板文件夹):兼容源码运行(src/host)与打包运行(lib/)。 */
|
|
64
65
|
function packagePresetDir() {
|
|
@@ -78,9 +79,23 @@ function packageEngineDir() {
|
|
|
78
79
|
}
|
|
79
80
|
throw new Error("prompt-tool: cannot locate package engine/ directory");
|
|
80
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* preset.yml 读缓存:按 mtime+size 签名失效。load()/describe/param-overrides 等
|
|
84
|
+
* 每次请求读盘解析,加缓存后同一文件只解析一次;写盘路径(savePresetParams /
|
|
85
|
+
* withPresetDoc)与外部编辑(stat 签名变化)都会正确失效。
|
|
86
|
+
*/
|
|
87
|
+
const presetSpecCache = /* @__PURE__ */ new Map();
|
|
88
|
+
/** 写盘后失效缓存(调用方在写完 preset.yml 后调用;不调用也安全——stat 签名兜底)。 */
|
|
89
|
+
function invalidatePresetSpec(dir) {
|
|
90
|
+
presetSpecCache.delete(join(dir, "preset.yml"));
|
|
91
|
+
}
|
|
81
92
|
/** 加载某个预设模板的单一参数文件 preset/<name>/preset.yml。 */
|
|
82
93
|
function loadPresetSpec(dir) {
|
|
83
|
-
const
|
|
94
|
+
const file = join(dir, "preset.yml");
|
|
95
|
+
const stat = statSync(file);
|
|
96
|
+
const cached = presetSpecCache.get(file);
|
|
97
|
+
if (cached !== void 0 && cached.mtimeMs === stat.mtimeMs && cached.size === stat.size) return cached.spec;
|
|
98
|
+
const raw = readFileSync(file, "utf8");
|
|
84
99
|
const parsed = parse(raw, { logLevel: "silent" });
|
|
85
100
|
if (parsed === null || typeof parsed !== "object") throw new Error(`preset ${join(dir, "preset.yml")} is not a YAML map`);
|
|
86
101
|
if (typeof parsed.id !== "string" || parsed.id.length === 0) parsed.id = basename(dir);
|
|
@@ -92,19 +107,17 @@ function loadPresetSpec(dir) {
|
|
|
92
107
|
if (value !== void 0) parsed.params[flatKey] = value;
|
|
93
108
|
}
|
|
94
109
|
};
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
temperature: "subagentTemperature",
|
|
107
|
-
maxTokens: "subagentMaxTokens"
|
|
110
|
+
const flattenMapping = (segmentName) => {
|
|
111
|
+
const mapping = {};
|
|
112
|
+
for (const [flatKey, [segment, segmentKey]] of Object.entries(MODEL_SEGMENT_MAP)) if (segment === segmentName) mapping[segmentKey] = flatKey;
|
|
113
|
+
return mapping;
|
|
114
|
+
};
|
|
115
|
+
flattenModelGroup(parsed.model, flattenMapping("model"));
|
|
116
|
+
flattenModelGroup(parsed.subagentModel, flattenMapping("subagentModel"));
|
|
117
|
+
presetSpecCache.set(file, {
|
|
118
|
+
mtimeMs: stat.mtimeMs,
|
|
119
|
+
size: stat.size,
|
|
120
|
+
spec: parsed
|
|
108
121
|
});
|
|
109
122
|
return parsed;
|
|
110
123
|
}
|
|
@@ -129,6 +142,23 @@ const asString = (value, fallback = "") => {
|
|
|
129
142
|
if (value === void 0 || value === null) return fallback;
|
|
130
143
|
return String(value);
|
|
131
144
|
};
|
|
145
|
+
/**
|
|
146
|
+
* 顶层模型段 ↔ 扁平参数键双向映射(单一来源)。
|
|
147
|
+
* loadPresetSpec 展平(段 → 扁平键)与 savePresetParams 迁移(扁平键 → 段)
|
|
148
|
+
* 共用本常量,杜绝两处字面量漂移。段结构 = 官方 agent-default-model 同构。
|
|
149
|
+
*/
|
|
150
|
+
const MODEL_SEGMENT_MAP = {
|
|
151
|
+
modelProvider: ["model", "provider"],
|
|
152
|
+
modelName: ["model", "name"],
|
|
153
|
+
modelReasoningEffort: ["model", "reasoningEffort"],
|
|
154
|
+
modelTemperature: ["model", "temperature"],
|
|
155
|
+
modelMaxTokens: ["model", "maxTokens"],
|
|
156
|
+
subagentModelProvider: ["subagentModel", "provider"],
|
|
157
|
+
subagentModelName: ["subagentModel", "name"],
|
|
158
|
+
subagentReasoningEffort: ["subagentModel", "reasoningEffort"],
|
|
159
|
+
subagentTemperature: ["subagentModel", "temperature"],
|
|
160
|
+
subagentMaxTokens: ["subagentModel", "maxTokens"]
|
|
161
|
+
};
|
|
132
162
|
/** 预设根:官方 USER_PRESET_DIR(~/.dsh/.agent-presets),导入/新建/种子化的预设都放这里。 */
|
|
133
163
|
function userPresetsDir() {
|
|
134
164
|
return DEFAULT_PRESET_DIR;
|
|
@@ -159,7 +189,7 @@ function resolvePresetDir(template) {
|
|
|
159
189
|
function listPresets() {
|
|
160
190
|
const scan = (dir) => {
|
|
161
191
|
try {
|
|
162
|
-
return readdirSync(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).flatMap((entry) => {
|
|
192
|
+
return readdirSync(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).filter((entry) => entry.name !== "prompt-tool").flatMap((entry) => {
|
|
163
193
|
try {
|
|
164
194
|
const spec = loadPresetSpec(join(dir, entry.name));
|
|
165
195
|
if (typeof spec.id !== "string" || spec.id.length === 0) return [];
|
|
@@ -228,16 +258,13 @@ function ensurePresetSeed() {
|
|
|
228
258
|
const root = userPresetsDir();
|
|
229
259
|
const legacyMark = join(root, ".pt-seeded");
|
|
230
260
|
const state = readPluginState();
|
|
231
|
-
if (
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
} catch {}
|
|
239
|
-
return { created: [] };
|
|
240
|
-
}
|
|
261
|
+
if (existsSync(legacyMark)) try {
|
|
262
|
+
writePluginState({
|
|
263
|
+
...state,
|
|
264
|
+
seeded: true
|
|
265
|
+
});
|
|
266
|
+
rmSync(legacyMark, { force: true });
|
|
267
|
+
} catch {}
|
|
241
268
|
const created = [];
|
|
242
269
|
try {
|
|
243
270
|
mkdirSync(root, { recursive: true });
|
|
@@ -378,35 +405,34 @@ function openPresetLocation(id, presetRoot = userPresetsDir()) {
|
|
|
378
405
|
};
|
|
379
406
|
}
|
|
380
407
|
}
|
|
408
|
+
/** 删除 yaml 两级键;父集合缺失时不触发 deleteIn 对不存在集合的异常。 */
|
|
409
|
+
function deleteYamlPath(doc, path) {
|
|
410
|
+
if (doc.hasIn(path)) doc.deleteIn(path);
|
|
411
|
+
}
|
|
412
|
+
/** 删除扁平 params 键。 */
|
|
413
|
+
function deleteFlatParam(doc, key) {
|
|
414
|
+
deleteYamlPath(doc, ["params", key]);
|
|
415
|
+
}
|
|
381
416
|
/**
|
|
382
417
|
* 保存预设参数:写激活预设目录 preset.yml 的 params(merge)/ promptConfigs(整体替换)。
|
|
383
|
-
* parseDocument 保留注释与未知键(preset.yml
|
|
384
|
-
*
|
|
418
|
+
* parseDocument 保留注释与未知键(preset.yml 模板含大量注释);空值键删除('' / [],
|
|
419
|
+
* 回落模板/引擎默认;0 与 false 照常写入--语义与函数内注释、docs §3 一致)。写入后删除 prompt-tool.overrides.yml(旧参数覆盖
|
|
385
420
|
* 通道残留——参数已并入 preset.yml,避免旧值覆盖新值)。
|
|
386
421
|
*/
|
|
387
422
|
function savePresetParams(presetRoot, templateName, params, promptConfigs, variables, variablesEnabled) {
|
|
388
|
-
const MODEL_KEY_MAP = {
|
|
389
|
-
modelProvider: ["model", "provider"],
|
|
390
|
-
modelName: ["model", "name"],
|
|
391
|
-
modelReasoningEffort: ["model", "reasoningEffort"],
|
|
392
|
-
modelTemperature: ["model", "temperature"],
|
|
393
|
-
modelMaxTokens: ["model", "maxTokens"],
|
|
394
|
-
subagentModelProvider: ["subagentModel", "provider"],
|
|
395
|
-
subagentModelName: ["subagentModel", "name"],
|
|
396
|
-
subagentReasoningEffort: ["subagentModel", "reasoningEffort"],
|
|
397
|
-
subagentTemperature: ["subagentModel", "temperature"],
|
|
398
|
-
subagentMaxTokens: ["subagentModel", "maxTokens"]
|
|
399
|
-
};
|
|
400
423
|
const file = join(presetRoot, templateName, "preset.yml");
|
|
401
424
|
if (!existsSync(file)) throw new Error(`preset ${templateName} 无 preset.yml`);
|
|
402
425
|
const doc = parseDocument(readFileSync(file, "utf8"), { logLevel: "silent" });
|
|
403
426
|
if (params !== void 0) for (const [key, value] of Object.entries(params)) {
|
|
404
427
|
if (value === void 0 || value === null || key.trim().length === 0) continue;
|
|
405
|
-
const
|
|
428
|
+
const isEmpty = value === "" || Array.isArray(value) && value.length === 0;
|
|
429
|
+
const segment = MODEL_SEGMENT_MAP[key];
|
|
406
430
|
if (segment !== void 0) {
|
|
407
|
-
doc
|
|
408
|
-
doc.
|
|
409
|
-
|
|
431
|
+
if (isEmpty) deleteYamlPath(doc, [segment[0], segment[1]]);
|
|
432
|
+
else doc.setIn([segment[0], segment[1]], value);
|
|
433
|
+
deleteFlatParam(doc, key);
|
|
434
|
+
} else if (isEmpty) deleteFlatParam(doc, key);
|
|
435
|
+
else doc.setIn(["params", key], value);
|
|
410
436
|
}
|
|
411
437
|
if (promptConfigs !== void 0) {
|
|
412
438
|
const cleaned = promptConfigs.map((config) => {
|
|
@@ -427,7 +453,7 @@ function savePresetParams(presetRoot, templateName, params, promptConfigs, varia
|
|
|
427
453
|
else doc.deleteIn(["variables"]);
|
|
428
454
|
for (const [key, value] of Object.entries(variables)) {
|
|
429
455
|
if (typeof value !== "string") continue;
|
|
430
|
-
doc
|
|
456
|
+
deleteFlatParam(doc, key);
|
|
431
457
|
}
|
|
432
458
|
}
|
|
433
459
|
if (variablesEnabled !== void 0) {
|
|
@@ -435,8 +461,20 @@ function savePresetParams(presetRoot, templateName, params, promptConfigs, varia
|
|
|
435
461
|
else doc.setIn(["variablesEnabled"], false);
|
|
436
462
|
}
|
|
437
463
|
writeFileSync(file, doc.toString(), "utf8");
|
|
464
|
+
invalidatePresetSpec(join(presetRoot, templateName));
|
|
438
465
|
rmSync(join(presetRoot, templateName, "prompt-tool.overrides.yml"), { force: true });
|
|
439
466
|
}
|
|
467
|
+
/** 预设文件读-改-写(parseDocument 保留注释与未知键;mutate 内 setIn/deleteIn)。
|
|
468
|
+
* 角色卡库(characters)与世界书工具(world-book-tools)共用此入口,避免
|
|
469
|
+
* 各自实现 parseDocument 往返。 */
|
|
470
|
+
function withPresetDoc(presetDir, mutate) {
|
|
471
|
+
const file = join(presetDir, "preset.yml");
|
|
472
|
+
if (!existsSync(file)) throw new Error(`${presetDir} 无 preset.yml`);
|
|
473
|
+
const doc = parseDocument(readFileSync(file, "utf8"), { logLevel: "silent" });
|
|
474
|
+
mutate(doc);
|
|
475
|
+
writeFileSync(file, doc.toString(), "utf8");
|
|
476
|
+
invalidatePresetSpec(presetDir);
|
|
477
|
+
}
|
|
440
478
|
/** 删除预设目录(预设根/<id>;含同名导入的 .bak-* 备份目录)。
|
|
441
479
|
* 仅作用于预设根(官方 USER_PRESET_DIR),包内置模板天然不受影响;路径越界与非法 id 拒绝。
|
|
442
480
|
* 删除后宿主 agent-presets 目录列表自然不再出现该预设(官方 roster 即目录列表)。 */
|
|
@@ -492,17 +530,6 @@ function resolvePresetParams(spec, runtime) {
|
|
|
492
530
|
if (typeof params.promptText !== "string" || params.promptText.length === 0) params.promptText = typeof runtime.promptText === "string" ? runtime.promptText : "";
|
|
493
531
|
return params;
|
|
494
532
|
}
|
|
495
|
-
/** {{key}} 嵌套插值(块模板内引用 params);键正则与引擎插值及 processStText 中文变量支持一致。 */
|
|
496
|
-
function interpolateNested(text, scope) {
|
|
497
|
-
return text.replace(/\{\{([A-Za-z0-9_.\u4e00-\u9fff-]+)\}\}/g, (whole, key, offset) => {
|
|
498
|
-
if (!Object.prototype.hasOwnProperty.call(scope, key)) return whole;
|
|
499
|
-
const value = asString(scope[key]);
|
|
500
|
-
if (!value.includes("\n")) return value;
|
|
501
|
-
const lineStart = text.lastIndexOf("\n", offset) + 1;
|
|
502
|
-
const prefix = text.slice(lineStart, offset);
|
|
503
|
-
return value.split("\n").map((line, at) => at === 0 ? line : line.length > 0 ? prefix + line : "").join("\n");
|
|
504
|
-
});
|
|
505
|
-
}
|
|
506
533
|
/** 逗号分隔 / YAML flow 数组 / 空格分隔的字符串列表 → 字符串数组。 */
|
|
507
534
|
function parseListParam(value) {
|
|
508
535
|
if (Array.isArray(value)) return value.map((item) => String(item)).filter((item) => item.length > 0);
|
|
@@ -512,51 +539,95 @@ function parseListParam(value) {
|
|
|
512
539
|
return (trimmed.startsWith("[") && trimmed.endsWith("]") ? trimmed.slice(1, -1) : trimmed).split(",").map((item) => item.trim()).filter((item) => item.length > 0);
|
|
513
540
|
}
|
|
514
541
|
/**
|
|
515
|
-
*
|
|
516
|
-
*
|
|
517
|
-
*
|
|
542
|
+
* 参数桥:params 扁平键 → 引擎模块行 config 对象(取代旧 __TOKEN__ 文本渲染)。
|
|
543
|
+
*
|
|
544
|
+
* 原则:
|
|
545
|
+
* - 未声明的键不合并(composition 行默认 / 引擎默认生效),与旧"空值删行"语义等价;
|
|
546
|
+
* - 值类型直达(布尔/数字/数组不再字符串化再解析);
|
|
547
|
+
* - 合并优先级:参数桥(UI/基础层)> moduleConfigs(模板/ST 行级直写)> 行默认。
|
|
518
548
|
* 模型路由/委派参数统一扁平键(modelProvider/subagentModelProvider/toolFilterAllow/maxDepth 等),
|
|
519
549
|
* 与官方 AgentOptions{provider,model} / toolFilter{allow,deny} / maxDepth 对齐。
|
|
520
550
|
*/
|
|
521
|
-
function
|
|
551
|
+
function buildModuleConfigsFromParams(params) {
|
|
552
|
+
const out = {};
|
|
553
|
+
const merge = (module, cfg) => {
|
|
554
|
+
if (Object.keys(cfg).length === 0) return;
|
|
555
|
+
out[module] = {
|
|
556
|
+
...out[module],
|
|
557
|
+
...cfg
|
|
558
|
+
};
|
|
559
|
+
};
|
|
560
|
+
const bootstrap = {};
|
|
561
|
+
if (typeof params.bootstrapMaxTokens === "number" && params.bootstrapMaxTokens > 0) bootstrap.bootstrapMaxTokens = params.bootstrapMaxTokens;
|
|
562
|
+
if (params.bootstrapTools !== void 0) bootstrap.bootstrapTools = parseListParam(params.bootstrapTools);
|
|
563
|
+
if (params.promoteGate !== void 0) bootstrap.promoteGate = params.promoteGate === true;
|
|
564
|
+
if (params.promoteAfterFirstResponse !== void 0) bootstrap.promoteAfterFirstResponse = params.promoteAfterFirstResponse === true;
|
|
565
|
+
if (params.maxPromoteSteps !== void 0 && Number.isSafeInteger(params.maxPromoteSteps)) bootstrap.maxPromoteSteps = params.maxPromoteSteps;
|
|
566
|
+
if (params.compactionTools !== void 0) bootstrap.compactionTools = parseListParam(params.compactionTools);
|
|
567
|
+
if (params.personaSectionsOnly !== void 0) bootstrap.personaSectionsOnly = params.personaSectionsOnly === true;
|
|
568
|
+
if (params.workspaceLine !== void 0) bootstrap.workspaceLine = params.workspaceLine === true;
|
|
569
|
+
if (typeof params.phase1FirstCallInstruction === "string" && params.phase1FirstCallInstruction.length > 0) bootstrap.phase1FirstCallInstruction = params.phase1FirstCallInstruction;
|
|
570
|
+
if (params.stages !== void 0) bootstrap.stages = params.stages;
|
|
571
|
+
if (params.stagePreUnlock !== void 0 && Number.isSafeInteger(params.stagePreUnlock)) bootstrap.stagePreUnlock = params.stagePreUnlock;
|
|
572
|
+
if (typeof params.stageAdvanceTool === "string" && params.stageAdvanceTool.length > 0) bootstrap.stageAdvanceTool = params.stageAdvanceTool;
|
|
573
|
+
if (typeof params.stageAdvanceDescription === "string" && params.stageAdvanceDescription.length > 0) bootstrap.stageAdvanceDescription = params.stageAdvanceDescription;
|
|
574
|
+
if (typeof params.stageSectionTemplate === "string" && params.stageSectionTemplate.length > 0) bootstrap.stageSectionTemplate = params.stageSectionTemplate;
|
|
575
|
+
merge("tool-bootstrap", bootstrap);
|
|
576
|
+
const gate = {};
|
|
577
|
+
if (params.allowKinds !== void 0) gate.allowKinds = parseListParam(params.allowKinds);
|
|
578
|
+
if (params.messageSources !== void 0) gate.messageSources = parseListParam(params.messageSources);
|
|
579
|
+
if (params.deferredSources !== void 0) gate.deferredSources = parseListParam(params.deferredSources);
|
|
580
|
+
if (params.deferredGraceSteps !== void 0 && Number.isSafeInteger(params.deferredGraceSteps)) gate.deferredGraceSteps = params.deferredGraceSteps;
|
|
581
|
+
if (params.instructionHint !== void 0) gate.instructionHint = params.instructionHint === true;
|
|
582
|
+
merge("context-gate", gate);
|
|
583
|
+
const presentation = {};
|
|
584
|
+
if (params.usePtcMode !== void 0) presentation.usePtcMode = params.usePtcMode === true;
|
|
585
|
+
merge("code-presentation", presentation);
|
|
586
|
+
const anchorTurn = {};
|
|
587
|
+
if (params.anchorTurn !== void 0) anchorTurn.enabled = params.anchorTurn === true;
|
|
588
|
+
if (typeof params.anchorTurnText === "string" && params.anchorTurnText.length > 0) anchorTurn.text = params.anchorTurnText;
|
|
589
|
+
merge("anchor-turn", anchorTurn);
|
|
590
|
+
const gate2 = {};
|
|
591
|
+
if (params.deliberationGate !== void 0) gate2.enabled = params.deliberationGate === true;
|
|
592
|
+
if (typeof params.deliberationMinChars === "number" && params.deliberationMinChars > 0) gate2.minChars = params.deliberationMinChars;
|
|
593
|
+
if (typeof params.deliberationMaxGatesPerTurn === "number" && params.deliberationMaxGatesPerTurn > 0) gate2.maxGatesPerTurn = params.deliberationMaxGatesPerTurn;
|
|
594
|
+
merge("deliberation-gate", gate2);
|
|
595
|
+
const drip = {};
|
|
596
|
+
if (params.cotDrip !== void 0) drip.enabled = params.cotDrip === true;
|
|
597
|
+
if (typeof params.cotDripEvery === "number" && params.cotDripEvery > 0) drip.every = params.cotDripEvery;
|
|
598
|
+
if (typeof params.cotDripMaxPerTurn === "number" && params.cotDripMaxPerTurn > 0) drip.maxPerTurn = params.cotDripMaxPerTurn;
|
|
599
|
+
merge("cot-drip", drip);
|
|
600
|
+
const editor = {};
|
|
601
|
+
editor.maxOutputChars = typeof params.strReplaceEditorMaxOutputChars === "number" && Number.isSafeInteger(params.strReplaceEditorMaxOutputChars) && params.strReplaceEditorMaxOutputChars > 0 ? params.strReplaceEditorMaxOutputChars : 16e3;
|
|
602
|
+
merge("str-replace-editor", editor);
|
|
603
|
+
const filter = {};
|
|
604
|
+
const mainAllow = parseListParam(params.toolFilterAllow);
|
|
605
|
+
const mainDeny = parseListParam(params.toolFilterDeny);
|
|
606
|
+
if (mainAllow.length > 0) filter.allow = mainAllow;
|
|
607
|
+
if (mainDeny.length > 0) filter.deny = mainDeny;
|
|
608
|
+
if (params.toolFilterSubagents === true) filter.includeSubagents = true;
|
|
609
|
+
merge("tool-filter", filter);
|
|
610
|
+
const subagent = {};
|
|
522
611
|
const provider = asString(params.subagentModelProvider, "");
|
|
523
612
|
const model = asString(params.subagentModelName, "");
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
const
|
|
529
|
-
const
|
|
530
|
-
|
|
531
|
-
|
|
613
|
+
if (provider.length > 0 && model.length > 0) subagent.agentOptions = {
|
|
614
|
+
provider,
|
|
615
|
+
model
|
|
616
|
+
};
|
|
617
|
+
const subAllow = parseListParam(params.toolFilterAllow);
|
|
618
|
+
const subDeny = parseListParam(params.toolFilterDeny);
|
|
619
|
+
if (subAllow.length > 0 || subDeny.length > 0) subagent.toolFilter = {
|
|
620
|
+
...subAllow.length > 0 ? { allow: subAllow } : {},
|
|
621
|
+
...subDeny.length > 0 ? { deny: subDeny } : {}
|
|
622
|
+
};
|
|
532
623
|
const rawMaxDepth = params.maxDepth;
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
if (
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
subagentLines.push("toolFilter:");
|
|
539
|
-
if (toolFilterAllow.length > 0) subagentLines.push(` allow: [${toolFilterAllow.join(", ")}]`);
|
|
540
|
-
if (toolFilterDeny.length > 0) subagentLines.push(` deny: [${toolFilterDeny.join(", ")}]`);
|
|
624
|
+
if (rawMaxDepth === "provider-managed") subagent.maxDepth = "provider-managed";
|
|
625
|
+
else if (Number.isSafeInteger(rawMaxDepth) && rawMaxDepth >= 0) subagent.maxDepth = rawMaxDepth;
|
|
626
|
+
if (Object.keys(subagent).length > 0) {
|
|
627
|
+
out["tool-subagent"] = subagent;
|
|
628
|
+
out["tool-subagent-fork"] = subagent;
|
|
541
629
|
}
|
|
542
|
-
|
|
543
|
-
const subagentConfigBlock = subagentLines.join("\n");
|
|
544
|
-
const bootstrap = typeof params.bootstrapMaxTokens === "number" && params.bootstrapMaxTokens > 0 ? `bootstrapMaxTokens: ${params.bootstrapMaxTokens}` : "";
|
|
545
|
-
const editorMaxOutputChars = typeof params.strReplaceEditorMaxOutputChars === "number" && Number.isSafeInteger(params.strReplaceEditorMaxOutputChars) && params.strReplaceEditorMaxOutputChars > 0 ? String(params.strReplaceEditorMaxOutputChars) : "16000";
|
|
546
|
-
return {
|
|
547
|
-
usePtcMode: params.usePtcMode === void 0 ? "" : params.usePtcMode === true ? "true" : "false",
|
|
548
|
-
bootstrapMaxTokens: bootstrap,
|
|
549
|
-
subagentConfig: subagentConfigBlock,
|
|
550
|
-
allowKinds: params.allowKinds === void 0 ? "" : Array.isArray(params.allowKinds) ? `[${params.allowKinds.map((item) => String(item)).join(", ")}]` : asString(params.allowKinds),
|
|
551
|
-
strReplaceEditorMaxOutputChars: editorMaxOutputChars,
|
|
552
|
-
mainToolFilterAllow: mainFilterAllowLine,
|
|
553
|
-
mainToolFilterDeny: mainFilterDenyLine,
|
|
554
|
-
mainToolFilterSubagents: String(mainFilterSubagents)
|
|
555
|
-
};
|
|
556
|
-
}
|
|
557
|
-
/** 预设 params + runtime → 组合 token 渲染(便捷入口)。 */
|
|
558
|
-
function resolvePresetTokens(spec, runtime) {
|
|
559
|
-
return renderEngineTokens(resolvePresetParams(spec, runtime));
|
|
630
|
+
return out;
|
|
560
631
|
}
|
|
561
632
|
/** 按参数文件的 modules 清单从引擎模块库装配组合文本。 */
|
|
562
633
|
/** 空模块清单兜底骨架(自定义预设空白起点:模块集与 minimal 一致,参数/配置全空)。 */
|
|
@@ -565,6 +636,7 @@ const FALLBACK_MODULES = [
|
|
|
565
636
|
"bootstrap-filesystem",
|
|
566
637
|
"context-gate",
|
|
567
638
|
"tool-bootstrap",
|
|
639
|
+
"code-presentation",
|
|
568
640
|
"prompt-config-engine",
|
|
569
641
|
"run-code-env",
|
|
570
642
|
"custom-bash",
|
|
@@ -588,9 +660,10 @@ function assembleModules(spec, library) {
|
|
|
588
660
|
* 2. 兼容 `composition:` 内联文本或组合清单名。
|
|
589
661
|
*/
|
|
590
662
|
/**
|
|
591
|
-
* 行级 config
|
|
592
|
-
* 数组型 config(如
|
|
593
|
-
* 未声明
|
|
663
|
+
* 行级 config 合并:仅支持 map 型 config 浅合并;
|
|
664
|
+
* 数组型 config(如 delegation 组)按子行 id 嵌套合并;未声明模块原样保留。
|
|
665
|
+
* 未声明 configs 时返回原文(零开销);parseDocument 往返保留注释。
|
|
666
|
+
* 本函数是参数桥产物落位组合行的唯一机制(含 delegation 组子行嵌套),不是预设覆盖通道。
|
|
594
667
|
*/
|
|
595
668
|
function applyModuleConfigs(raw, configs) {
|
|
596
669
|
if (configs === void 0 || Object.keys(configs).length === 0) return raw;
|
|
@@ -598,21 +671,38 @@ function applyModuleConfigs(raw, configs) {
|
|
|
598
671
|
if (!(doc.contents instanceof YAMLSeq)) return raw;
|
|
599
672
|
const rows = doc.contents;
|
|
600
673
|
let changed = false;
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
const idNode = item.get("id", true);
|
|
604
|
-
const id = idNode !== null && typeof idNode === "object" && "value" in idNode ? String(idNode.value) : void 0;
|
|
605
|
-
if (id === void 0 || !Object.prototype.hasOwnProperty.call(configs, id)) continue;
|
|
674
|
+
/** 把 cfg 的键写入一个 config 节点(无 config 时创建)。 */
|
|
675
|
+
const mergeInto = (item, cfg) => {
|
|
606
676
|
const existingConfig = item.get("config", true);
|
|
607
677
|
let configNode;
|
|
608
678
|
if (existingConfig instanceof YAMLMap) configNode = existingConfig;
|
|
609
679
|
else if (existingConfig === null || existingConfig === void 0) {
|
|
610
680
|
configNode = new YAMLMap();
|
|
611
681
|
item.items.push(new Pair(new Scalar("config"), configNode));
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
682
|
+
} else return false;
|
|
683
|
+
for (const [key, value] of Object.entries(cfg)) configNode.set(key, value);
|
|
684
|
+
return true;
|
|
685
|
+
};
|
|
686
|
+
/** 从行节点读 id(ParsedNode 值包装兼容)。 */
|
|
687
|
+
const rowId = (item) => {
|
|
688
|
+
const idNode = item.get("id", true);
|
|
689
|
+
return idNode !== null && typeof idNode === "object" && "value" in idNode ? String(idNode.value) : void 0;
|
|
690
|
+
};
|
|
691
|
+
for (const item of rows.items) {
|
|
692
|
+
if (!(item instanceof YAMLMap)) continue;
|
|
693
|
+
const id = rowId(item);
|
|
694
|
+
const existingConfig = item.get("config", true);
|
|
695
|
+
if (existingConfig instanceof YAMLSeq && id !== void 0 && !Object.prototype.hasOwnProperty.call(configs, id)) {
|
|
696
|
+
for (const child of existingConfig.items) {
|
|
697
|
+
if (!(child instanceof YAMLMap)) continue;
|
|
698
|
+
const childId = rowId(child);
|
|
699
|
+
if (childId === void 0 || !Object.prototype.hasOwnProperty.call(configs, childId)) continue;
|
|
700
|
+
if (mergeInto(child, configs[childId])) changed = true;
|
|
701
|
+
}
|
|
702
|
+
continue;
|
|
703
|
+
}
|
|
704
|
+
if (id === void 0 || !Object.prototype.hasOwnProperty.call(configs, id)) continue;
|
|
705
|
+
if (mergeInto(item, configs[id])) changed = true;
|
|
616
706
|
}
|
|
617
707
|
return changed ? doc.toString() : raw;
|
|
618
708
|
}
|
|
@@ -657,13 +747,18 @@ function loadCompositionText(spec, templateDir) {
|
|
|
657
747
|
return raw;
|
|
658
748
|
}
|
|
659
749
|
/**
|
|
660
|
-
*
|
|
661
|
-
*
|
|
662
|
-
* 如
|
|
750
|
+
* 预设组合渲染完整链路:模块装配 → 参数桥(moduleConfigs + params)行级合并。
|
|
751
|
+
* 合并优先级:参数桥(params/UI 基础层) > moduleConfigs(模板/ST 行级直写) > 行默认。
|
|
752
|
+
* moduleConfigs 仅补充参数桥未覆盖的行级 config(如 ST 导入的 tool-web.fetch),
|
|
753
|
+
* 不再锁定覆盖 UI 可管理参数(旧作者锁定语义已移除)。
|
|
663
754
|
*/
|
|
664
755
|
function renderComposition(spec, runtime, templateDir) {
|
|
665
|
-
const
|
|
666
|
-
|
|
756
|
+
const merged = buildModuleConfigsFromParams(resolvePresetParams(spec, runtime));
|
|
757
|
+
for (const [id, cfg] of Object.entries(spec.moduleConfigs ?? {})) merged[id] = {
|
|
758
|
+
...cfg,
|
|
759
|
+
...merged[id]
|
|
760
|
+
};
|
|
761
|
+
return applyModuleConfigs(loadCompositionText(spec, templateDir), merged);
|
|
667
762
|
}
|
|
668
763
|
/** 组合文本基础校验(模板无关):无未解析 token,且必须是 YAML 数组。 */
|
|
669
764
|
function assertCompositionArray(raw, spec) {
|
|
@@ -673,26 +768,6 @@ function assertCompositionArray(raw, spec) {
|
|
|
673
768
|
if (!Array.isArray(parsed)) throw new Error(`generated agent.cordis.yml is not a YAML array (preset ${spec.id})`);
|
|
674
769
|
return parsed;
|
|
675
770
|
}
|
|
676
|
-
/**
|
|
677
|
-
* 文本 token 替换:
|
|
678
|
-
* - token 独立成行时,替换块按该行缩进前缀(用于 line/block);
|
|
679
|
-
* - token 内联时直接替换(用于布尔/字符串标量)。
|
|
680
|
-
*/
|
|
681
|
-
function renderTemplateVariables(raw, variables) {
|
|
682
|
-
let text = raw.replace(/^[ \t]*(?:[A-Za-z0-9_.-]+:[ \t]*)?__([A-Za-z0-9_]+)__[ \t]*\r?\n/gm, (whole, key) => Object.prototype.hasOwnProperty.call(variables, key) && variables[key] === "" ? "" : whole);
|
|
683
|
-
return text.replace(/__([A-Za-z0-9_]+)__/g, (whole, key, offset) => {
|
|
684
|
-
if (!Object.prototype.hasOwnProperty.call(variables, key)) return whole;
|
|
685
|
-
const value = variables[key];
|
|
686
|
-
if (value === "") return "";
|
|
687
|
-
const lineStart = text.lastIndexOf("\n", offset) + 1;
|
|
688
|
-
const lineEndRaw = text.indexOf("\n", offset);
|
|
689
|
-
const lineEnd = lineEndRaw < 0 ? text.length : lineEndRaw;
|
|
690
|
-
const prefix = text.slice(lineStart, offset);
|
|
691
|
-
const rest = text.slice(offset + whole.length, lineEnd);
|
|
692
|
-
if (prefix.trim() === "" && rest.trim() === "") return value.split("\n").map((line, at) => at === 0 ? line : line.length > 0 ? prefix + line : "").join("\n");
|
|
693
|
-
return value;
|
|
694
|
-
});
|
|
695
|
-
}
|
|
696
771
|
//#endregion
|
|
697
772
|
//#region src/host/prompt-configs.ts
|
|
698
773
|
/**
|
|
@@ -806,4 +881,4 @@ function loadPromptConfigFiles(dir) {
|
|
|
806
881
|
return specs;
|
|
807
882
|
}
|
|
808
883
|
//#endregion
|
|
809
|
-
export {
|
|
884
|
+
export { DEFAULT_SKILLS_DIR as A, resolvePresetParams as C, writePluginState as D, withPresetDoc as E, LEGACY_USER_PRESETS_DIR as M, DEFAULT_PRESET_DIR as O, resolvePresetDir as S, userPresetsDir as T, packageEngineDir as _, applyModuleConfigs as a, removeUserPreset as b, buildModuleConfigsFromParams as c, ensurePresetSeed as d, listBuiltinTemplates as f, openPresetLocation as g, loadPresetSpec as h, MODEL_SEGMENT_MAP as i, LEGACY_CONTAINER_DIR as j, DEFAULT_RESIDENT_AGENTS_PATH as k, cloneBuiltinPreset as l, loadPresetContent as m, mergePromptConfigs as n, asString as o, listPresets as p, renderPromptConfigYaml as r, assertCompositionArray as s, loadPromptConfigFiles as t, duplicateUserPreset as u, parseImportedPresetId as v, savePresetParams as w, renderComposition as x, readPluginState as y };
|