@fieldwangai/agentflow 0.1.153 → 0.1.156

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.
Files changed (193) hide show
  1. package/README.md +16 -34
  2. package/README.zh-CN.md +14 -34
  3. package/agents/agentflow-node-executor-code.md +13 -3
  4. package/agents/agentflow-node-executor-planning.md +13 -3
  5. package/agents/agentflow-node-executor-requirement.md +13 -3
  6. package/agents/agentflow-node-executor-test.md +13 -3
  7. package/agents/agentflow-node-executor-ui.md +13 -3
  8. package/agents/agentflow-node-executor.md +13 -3
  9. package/agents/en/agentflow-node-executor.md +13 -3
  10. package/agents/zh/agentflow-node-executor.md +13 -3
  11. package/bin/agentflow.mjs +3 -3
  12. package/bin/lib/admin-builtin-pipelines.mjs +3 -2
  13. package/bin/lib/agent-runners.mjs +0 -929
  14. package/bin/lib/auth.mjs +2 -1
  15. package/bin/lib/catalog-agents.mjs +2 -1
  16. package/bin/lib/catalog-flows.mjs +165 -90
  17. package/bin/lib/composer-agent.mjs +3 -793
  18. package/bin/lib/composer-skill-router.mjs +3 -323
  19. package/bin/lib/exec-buffered.mjs +32 -0
  20. package/bin/lib/flow-dsl/cli.mjs +277 -0
  21. package/bin/lib/flow-dsl/codegen.mjs +358 -0
  22. package/bin/lib/flow-dsl/defs.mjs +103 -0
  23. package/bin/lib/flow-dsl/index.mjs +77 -0
  24. package/bin/lib/flow-dsl/ir.mjs +305 -0
  25. package/bin/lib/flow-dsl/layout.mjs +115 -0
  26. package/bin/lib/flow-dsl/legacy-yaml.mjs +303 -0
  27. package/bin/lib/flow-dsl/lint.mjs +241 -0
  28. package/bin/lib/flow-dsl/packages.mjs +251 -0
  29. package/bin/lib/flow-dsl/parser.mjs +444 -0
  30. package/bin/lib/flow-import.mjs +96 -26
  31. package/bin/lib/flow-write.mjs +48 -12
  32. package/bin/lib/help.mjs +8 -28
  33. package/bin/lib/html-escape.mjs +19 -0
  34. package/bin/lib/http-util.mjs +49 -0
  35. package/bin/lib/legacy-flow-execution.mjs +37 -0
  36. package/bin/lib/locales/en.json +1 -1
  37. package/bin/lib/locales/zh.json +1 -1
  38. package/bin/lib/main.mjs +152 -286
  39. package/bin/lib/marketplace.mjs +206 -61
  40. package/bin/lib/model-config.mjs +10 -0
  41. package/bin/lib/node-package-archive.mjs +240 -0
  42. package/bin/lib/node-package-bootstrap.mjs +72 -0
  43. package/bin/lib/node-package-manifest.mjs +174 -0
  44. package/bin/lib/paths.mjs +42 -19
  45. package/bin/lib/prd-workflow-routes.mjs +2949 -0
  46. package/bin/lib/prd-workflow-server.mjs +4884 -0
  47. package/bin/lib/run-events.mjs +0 -66
  48. package/bin/lib/schedule-config.mjs +4 -4
  49. package/bin/lib/skill-runtime.mjs +35 -0
  50. package/bin/lib/startup-storage-migrations.mjs +274 -0
  51. package/bin/lib/ui-server.mjs +1092 -18123
  52. package/bin/lib/user-env.mjs +16 -0
  53. package/bin/lib/workspace-auto-layout.mjs +234 -0
  54. package/bin/lib/workspace-flow-store.mjs +478 -0
  55. package/bin/lib/workspace-graph-merge.mjs +41 -34
  56. package/bin/lib/workspace-preview.mjs +12 -2
  57. package/bin/lib/workspace-routes.mjs +3088 -0
  58. package/bin/lib/workspace-server.mjs +6199 -0
  59. package/bin/lib/workspace-state.mjs +331 -0
  60. package/bin/lib/workspace.mjs +2 -1
  61. package/builtin/nodes/agent_subAgent.md +1 -0
  62. package/builtin/nodes/control_agent_toBool.md +2 -0
  63. package/builtin/nodes/control_anyOne.md +2 -0
  64. package/builtin/nodes/control_cancelled.md +2 -0
  65. package/builtin/nodes/control_cd_workspace.md +5 -11
  66. package/builtin/nodes/control_delay.md +2 -0
  67. package/builtin/nodes/control_end.md +2 -0
  68. package/builtin/nodes/control_if.md +1 -0
  69. package/builtin/nodes/control_interval_loop.md +2 -0
  70. package/builtin/nodes/control_load_mcp.md +24 -0
  71. package/builtin/nodes/control_load_skills.md +8 -23
  72. package/builtin/nodes/control_start.md +2 -0
  73. package/builtin/nodes/control_toBool.md +2 -0
  74. package/builtin/nodes/control_user_workspace.md +2 -0
  75. package/builtin/nodes/control_wait_until.md +2 -0
  76. package/builtin/nodes/display_ascii.md +1 -0
  77. package/builtin/nodes/display_chart.md +1 -0
  78. package/builtin/nodes/display_html.md +1 -0
  79. package/builtin/nodes/display_image.md +1 -0
  80. package/builtin/nodes/display_markdown.md +1 -0
  81. package/builtin/nodes/display_mermaid.md +1 -0
  82. package/builtin/nodes/display_react_app.md +1 -0
  83. package/builtin/nodes/display_table.md +1 -0
  84. package/builtin/nodes/provide_bool.md +1 -0
  85. package/builtin/nodes/provide_file.md +1 -0
  86. package/builtin/nodes/provide_password.md +1 -0
  87. package/builtin/nodes/provide_str.md +1 -0
  88. package/builtin/nodes/tool_display_share_link.md +1 -0
  89. package/builtin/nodes/tool_get_env.md +2 -0
  90. package/builtin/nodes/tool_git_checkout.md +1 -0
  91. package/builtin/nodes/tool_git_worktree_load.md +1 -0
  92. package/builtin/nodes/tool_git_worktree_unload.md +1 -0
  93. package/builtin/nodes/tool_gitlab_create_mr.md +1 -0
  94. package/builtin/nodes/tool_jenkins_build.md +2 -0
  95. package/builtin/nodes/tool_load_key.md +2 -0
  96. package/builtin/nodes/tool_nodejs.md +17 -19
  97. package/builtin/nodes/tool_print.md +2 -0
  98. package/builtin/nodes/tool_save_key.md +2 -0
  99. package/builtin/nodes/tool_set_run_env.md +1 -0
  100. package/builtin/nodes/tool_user_ask.md +2 -0
  101. package/builtin/nodes/tool_user_check.md +2 -0
  102. package/builtin/nodes/tool_wecom_send_app_markdown.md +1 -0
  103. package/builtin/nodes/tool_wecom_send_group_markdown.md +1 -0
  104. package/builtin/nodes/workspace_one_click_task.md +44 -0
  105. package/builtin/nodes/workspace_run.md +16 -0
  106. package/builtin/nodes/workspace_scheduled_run.md +16 -0
  107. package/builtin/pipelines/module-migrate/scripts/gate.mjs +37 -0
  108. package/builtin/pipelines/module-migrate/scripts/static-check.mjs +82 -0
  109. package/builtin/pipelines/module-migrate/workspace.flow.js +172 -0
  110. package/builtin/pipelines/module-migrate/workspace.layout.json +134 -0
  111. package/builtin/pipelines/new/scripts/lint-flow.mjs +38 -0
  112. package/builtin/pipelines/new/workspace.flow.js +91 -0
  113. package/builtin/pipelines/new/workspace.layout.json +70 -0
  114. package/builtin/web-ui/dist/assets/{WorkflowAssistantThread-B9xslwI0.js → WorkflowAssistantThread-ClNxY2Wu.js} +1 -1
  115. package/builtin/web-ui/dist/assets/index-BJzMYRK3.js +870 -0
  116. package/builtin/web-ui/dist/assets/index-CEXmmwM2.css +1 -0
  117. package/builtin/web-ui/dist/index.html +2 -2
  118. package/package.json +3 -1
  119. package/reference/flow-control-capabilities.md +77 -158
  120. package/reference/flow-layout.md +1 -1
  121. package/reference/flow-prompt-handler-check.md +2 -2
  122. package/skills/agentflow-author-flow/SKILL.md +1 -1
  123. package/skills/agentflow-cli/SKILL.md +139 -24
  124. package/skills/agentflow-cli/agents/openai.yaml +2 -2
  125. package/skills/agentflow-cli/scripts/agentflow-cli.mjs +654 -20
  126. package/skills/agentflow-cli/scripts/agentflow-runtime.mjs +97 -0
  127. package/skills/agentflow-flow-add-instances/SKILL.md +1 -1
  128. package/skills/agentflow-flow-dsl/SKILL.md +206 -0
  129. package/skills/agentflow-flow-dsl/agents/openai.yaml +4 -0
  130. package/skills/agentflow-flow-dsl/references/node-calls.md +39 -0
  131. package/skills/agentflow-flow-edit-node-fields/SKILL.md +1 -1
  132. package/skills/agentflow-flow-recipes/SKILL.md +7 -4
  133. package/skills/agentflow-flow-recipes/references/recipes.md +97 -43
  134. package/skills/agentflow-flow-sync-ui/SKILL.md +1 -1
  135. package/skills/agentflow-node-dsl/SKILL.md +212 -0
  136. package/skills/agentflow-node-dsl/agents/openai.yaml +4 -0
  137. package/skills/agentflow-node-reference/SKILL.md +2 -2
  138. package/skills/agentflow-node-reference/references/builtin-nodes.md +166 -115
  139. package/skills/agentflow-runtime-reference/references/runtime.md +1 -1
  140. package/skills/agentflow-workspace-ascii/SKILL.md +9 -16
  141. package/skills/agentflow-workspace-graph/SKILL.md +62 -48
  142. package/skills/agentflow-workspace-html/SKILL.md +7 -2
  143. package/skills/agentflow-workspace-image/SKILL.md +6 -2
  144. package/skills/agentflow-workspace-markdown/SKILL.md +14 -21
  145. package/skills/agentflow-workspace-mermaid/SKILL.md +8 -16
  146. package/bin/lib/api-runner.mjs +0 -387
  147. package/bin/lib/apply.mjs +0 -903
  148. package/bin/lib/composer-flow-instances.mjs +0 -68
  149. package/bin/lib/composer-flow-skeleton.mjs +0 -334
  150. package/bin/lib/composer-flow-validate.mjs +0 -47
  151. package/bin/lib/composer-model-router.mjs +0 -185
  152. package/bin/lib/composer-node-schema.mjs +0 -303
  153. package/bin/lib/composer-planner.mjs +0 -751
  154. package/bin/lib/composer-script-ops.mjs +0 -233
  155. package/bin/lib/flow-static-preview.mjs +0 -104
  156. package/bin/lib/hub-login.mjs +0 -54
  157. package/bin/lib/hub-publish.mjs +0 -159
  158. package/bin/lib/hub-remote.mjs +0 -189
  159. package/bin/lib/hub.mjs +0 -299
  160. package/bin/lib/jenkins.mjs +0 -380
  161. package/bin/lib/node-execute.mjs +0 -539
  162. package/bin/lib/normalize-node-tool-command.mjs +0 -97
  163. package/bin/lib/runtime-context.mjs +0 -243
  164. package/bin/lib/scheduler.mjs +0 -601
  165. package/bin/lib/ui-print.mjs +0 -94
  166. package/bin/pipeline/build-node-prompt.mjs +0 -271
  167. package/bin/pipeline/check-cache.mjs +0 -191
  168. package/bin/pipeline/check-flow.mjs +0 -543
  169. package/bin/pipeline/collect-nodes.mjs +0 -212
  170. package/bin/pipeline/compute-cache-md5.mjs +0 -177
  171. package/bin/pipeline/ensure-run-dir.mjs +0 -71
  172. package/bin/pipeline/gc.mjs +0 -129
  173. package/bin/pipeline/get-env.mjs +0 -59
  174. package/bin/pipeline/get-resolved-values.mjs +0 -344
  175. package/bin/pipeline/load-key.mjs +0 -62
  176. package/bin/pipeline/parse-flow.mjs +0 -708
  177. package/bin/pipeline/post-process-control-if.mjs +0 -23
  178. package/bin/pipeline/post-process-node.mjs +0 -490
  179. package/bin/pipeline/pre-process-node.mjs +0 -1430
  180. package/bin/pipeline/resolve-inputs.mjs +0 -201
  181. package/bin/pipeline/run-tool-nodejs.mjs +0 -167
  182. package/bin/pipeline/save-key.mjs +0 -93
  183. package/bin/pipeline/snapshot-prior-round.mjs +0 -70
  184. package/bin/pipeline/validate-for-ui.mjs +0 -234
  185. package/bin/pipeline/validate-script-output.mjs +0 -130
  186. package/bin/pipeline/write-result.mjs +0 -182
  187. package/builtin/pipelines/module-migrate/flow.yaml +0 -819
  188. package/builtin/pipelines/new/flow.yaml +0 -545
  189. package/builtin/pipelines/new/scripts/check-flow.mjs +0 -9
  190. package/builtin/pipelines/new/scripts/collect-nodes.mjs +0 -211
  191. package/builtin/web-ui/dist/assets/index-DZ328oSo.css +0 -1
  192. package/builtin/web-ui/dist/assets/index-DmUV7ZCL.js +0 -888
  193. package/skills/agentflow-node-authoring/SKILL.md +0 -57
@@ -1,243 +0,0 @@
1
- import path from "path";
2
- import yaml from "js-yaml";
3
- import { getFlowDir } from "./workspace.mjs";
4
- import { PACKAGE_ROOT, PIPELINES_DIR } from "./paths.mjs";
5
- import { listSkills, listSkillsFromSources, workspaceSkillSources } from "./skill-registry.mjs";
6
-
7
- function parseJsonObject(raw) {
8
- if (raw == null) return null;
9
- if (typeof raw === "object" && !Array.isArray(raw)) return raw;
10
- const text = String(raw || "").trim();
11
- if (!text) return null;
12
- try {
13
- const parsed = JSON.parse(text);
14
- return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
15
- } catch {
16
- return null;
17
- }
18
- }
19
-
20
- export function getPipelineFlowDir(workspaceRoot, flowName, flowJson = null) {
21
- if (flowJson?.flowDir && typeof flowJson.flowDir === "string" && flowJson.flowDir.trim()) {
22
- return path.isAbsolute(flowJson.flowDir) ? path.resolve(flowJson.flowDir) : path.resolve(workspaceRoot, flowJson.flowDir);
23
- }
24
- return getFlowDir(workspaceRoot, flowName) || path.join(path.resolve(workspaceRoot), PIPELINES_DIR, flowName);
25
- }
26
-
27
- export function buildDefaultWorkspaceContext(workspaceRoot, flowName, flowJson = null) {
28
- const pipelineWorkspace = path.resolve(workspaceRoot);
29
- const flowDir = getPipelineFlowDir(workspaceRoot, flowName, flowJson);
30
- return {
31
- version: 1,
32
- label: "pipeline",
33
- cwd: pipelineWorkspace,
34
- workspaceRoot: pipelineWorkspace,
35
- pipelineWorkspace,
36
- flowDir,
37
- previous: null,
38
- };
39
- }
40
-
41
- export function normalizeWorkspaceContext(raw, workspaceRoot, flowName, flowJson = null) {
42
- const base = buildDefaultWorkspaceContext(workspaceRoot, flowName, flowJson);
43
- const parsed = parseJsonObject(raw);
44
- if (!parsed) return base;
45
- const cwdRaw = parsed.cwd || parsed.workspaceRoot || parsed.path || "";
46
- const cwd = cwdRaw ? path.resolve(String(cwdRaw)) : base.cwd;
47
- return {
48
- ...base,
49
- ...parsed,
50
- version: 1,
51
- cwd,
52
- workspaceRoot: cwd,
53
- pipelineWorkspace: path.resolve(parsed.pipelineWorkspace || base.pipelineWorkspace),
54
- flowDir: path.resolve(parsed.flowDir || base.flowDir),
55
- previous: parsed.previous && typeof parsed.previous === "object" ? parsed.previous : null,
56
- };
57
- }
58
-
59
- export function normalizeSkillsContext(raw) {
60
- const parsed = parseJsonObject(raw);
61
- if (!parsed) return null;
62
- return {
63
- version: 1,
64
- ...parsed,
65
- skills: Array.isArray(parsed.skills) ? parsed.skills : [],
66
- skillKeys: Array.isArray(parsed.skillKeys) ? parsed.skillKeys : [],
67
- sources: Array.isArray(parsed.sources) ? parsed.sources : [],
68
- warnings: Array.isArray(parsed.warnings) ? parsed.warnings : [],
69
- };
70
- }
71
-
72
- export function expandRuntimePlaceholders(text, workspaceContext, extra = {}) {
73
- if (text == null) return "";
74
- const raw = String(text).trim();
75
- if (!raw) return "";
76
- const values = {
77
- workspaceRoot: workspaceContext.workspaceRoot || workspaceContext.cwd || "",
78
- cwd: workspaceContext.cwd || workspaceContext.workspaceRoot || "",
79
- pipelineWorkspace: workspaceContext.pipelineWorkspace || "",
80
- flowDir: workspaceContext.flowDir || "",
81
- ...extra,
82
- };
83
- return raw.replace(/\$\{([^}]+)\}/g, (_, key) => {
84
- const k = String(key || "").trim();
85
- return values[k] != null ? String(values[k]) : "";
86
- });
87
- }
88
-
89
- export function resolveWorkspaceTarget(rawTarget, workspaceContext, extra = {}) {
90
- const expanded = expandRuntimePlaceholders(rawTarget, workspaceContext, extra).trim();
91
- if (!expanded || expanded === "pipeline" || expanded === "pipeline-workspace") {
92
- return workspaceContext.pipelineWorkspace;
93
- }
94
- if (expanded === "current" || expanded === ".") return workspaceContext.cwd;
95
- if (expanded === "flowDir") return workspaceContext.flowDir;
96
- return path.isAbsolute(expanded) ? path.resolve(expanded) : path.resolve(workspaceContext.cwd, expanded);
97
- }
98
-
99
- export function scanSkillsFromPaths(paths, opts = {}) {
100
- const sources = (paths || []).map((entry, index) => ({
101
- source: entry.source || `runtime-${index}`,
102
- sourceLabel: entry.sourceLabel || entry.label || entry.dir,
103
- dir: path.resolve(entry.dir),
104
- installedBy: entry.installedBy || "runtime",
105
- }));
106
- return listSkillsFromSources(sources, { ...opts, warnMissing: true });
107
- }
108
-
109
- export function parseSkillKeyList(raw) {
110
- if (Array.isArray(raw)) return raw.map((x) => String(x || "").trim()).filter(Boolean);
111
- return String(raw || "")
112
- .split(/[\s,]+/)
113
- .map((x) => x.trim())
114
- .filter(Boolean);
115
- }
116
-
117
- function skillBodyFromRegistryItem(skill) {
118
- return {
119
- name: skill.name,
120
- key: skill.key,
121
- description: skill.description,
122
- frontmatter: skill.frontmatter,
123
- source: skill.source,
124
- sourceLabel: skill.sourceLabel,
125
- path: skill.path,
126
- body: skill.body,
127
- };
128
- }
129
-
130
- export function buildSkillsContextFromRegistry({ workspaceContext, skillKeys = [], mergeMode = "replace" }) {
131
- const wc = workspaceContext;
132
- const wanted = parseSkillKeyList(skillKeys);
133
- const registryWorkspaceRoot = wc.pipelineWorkspace || wc.workspaceRoot || wc.cwd || process.cwd();
134
- const registry = listSkills(PACKAGE_ROOT, registryWorkspaceRoot);
135
- const skillBodies = [];
136
- const warnings = [];
137
- const seenKeys = new Set();
138
-
139
- for (const raw of wanted) {
140
- const key = String(raw || "").trim();
141
- if (!key) continue;
142
- const match = registry.find((skill) => skill.key === key || skill.name === key || skill.id === key);
143
- if (!match) {
144
- warnings.push(`skill not found: ${key}`);
145
- continue;
146
- }
147
- const dedupeKey = match.key || match.path || match.name;
148
- if (seenKeys.has(dedupeKey)) continue;
149
- seenKeys.add(dedupeKey);
150
- skillBodies.push(skillBodyFromRegistryItem(match));
151
- }
152
-
153
- return {
154
- version: 1,
155
- workspaceRoot: wc.workspaceRoot,
156
- cwd: wc.cwd,
157
- pipelineWorkspace: wc.pipelineWorkspace,
158
- flowDir: wc.flowDir,
159
- source: "public-registry",
160
- mergeMode,
161
- requestedSkillKeys: wanted,
162
- skills: skillBodies.map(({ body, ...meta }) => meta),
163
- skillKeys: skillBodies.map((s) => s.key),
164
- sources: [...new Set(skillBodies.map((s) => s.sourceLabel || s.source || "").filter(Boolean))],
165
- loadedCount: skillBodies.length,
166
- warnings,
167
- skillBodies,
168
- };
169
- }
170
-
171
- export function buildSkillsContext({ workspaceContext, source = "current-workspace", paths = [], include = [], exclude = [], mergeMode = "replace" }) {
172
- const wc = workspaceContext;
173
- const sourcePaths = [];
174
- const addWorkspace = (root, label) => {
175
- sourcePaths.push(...workspaceSkillSources(root, label, label));
176
- };
177
- if (source === "pipeline-workspace") {
178
- addWorkspace(wc.pipelineWorkspace, "pipeline");
179
- } else if (source === "explicit-paths") {
180
- for (const p of paths) {
181
- const resolved = path.isAbsolute(p) ? path.resolve(p) : path.resolve(wc.cwd, p);
182
- sourcePaths.push({ dir: resolved, label: "explicit" });
183
- }
184
- } else if (source === "all") {
185
- addWorkspace(wc.cwd, "current");
186
- if (path.resolve(wc.cwd) !== path.resolve(wc.pipelineWorkspace)) addWorkspace(wc.pipelineWorkspace, "pipeline");
187
- } else {
188
- addWorkspace(wc.cwd, "current");
189
- }
190
- const scanned = scanSkillsFromPaths(sourcePaths, { include, exclude });
191
- return {
192
- version: 1,
193
- workspaceRoot: wc.workspaceRoot,
194
- cwd: wc.cwd,
195
- source,
196
- mergeMode,
197
- skills: scanned.skills.map(({ body, ...meta }) => meta),
198
- skillKeys: scanned.skills.map((s) => s.key),
199
- sources: sourcePaths.map((p) => p.dir),
200
- loadedCount: scanned.skills.length,
201
- warnings: scanned.warnings,
202
- skillBodies: scanned.skills.map((s) => ({
203
- name: s.name,
204
- key: s.key,
205
- description: s.description,
206
- frontmatter: s.frontmatter,
207
- sourceLabel: s.sourceLabel,
208
- path: s.path,
209
- body: s.body,
210
- })),
211
- };
212
- }
213
-
214
- function renderSkillFrontmatter(frontmatter) {
215
- if (!frontmatter || typeof frontmatter !== "object" || Array.isArray(frontmatter)) return "";
216
- const extra = Object.fromEntries(
217
- Object.entries(frontmatter).filter(([key, value]) => {
218
- if (key === "name" || key === "description") return false;
219
- if (value == null) return false;
220
- if (typeof value === "string" && value.trim() === "") return false;
221
- return true;
222
- }),
223
- );
224
- if (Object.keys(extra).length === 0) return "";
225
- return yaml.dump(extra, { lineWidth: 100, noRefs: true }).trim();
226
- }
227
-
228
- export function renderSkillsContextForPrompt(skillsContext) {
229
- const ctx = normalizeSkillsContext(skillsContext);
230
- if (!ctx || !Array.isArray(ctx.skillBodies) || ctx.skillBodies.length === 0) return "";
231
- const blocks = ctx.skillBodies.slice(0, 20).map((skill) => {
232
- const body = String(skill.body || "").trim();
233
- const frontmatter = renderSkillFrontmatter(skill.frontmatter);
234
- const header = [
235
- `### ${skill.name}`,
236
- skill.description ? `说明:${skill.description}` : "",
237
- `来源:${skill.path || skill.sourceLabel || ""}`,
238
- frontmatter ? `元数据:\n${frontmatter}` : "",
239
- ].filter(Boolean).join("\n");
240
- return [header, body.slice(0, 16000)].filter(Boolean).join("\n\n");
241
- });
242
- return ["## 已加载 Skills", ...blocks].join("\n\n");
243
- }