@blocklet/pages-kit-agents 0.5.12
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/.env.local.example +8 -0
- package/LICENSE +13 -0
- package/README.md +10 -0
- package/cli.ts +354 -0
- package/index.ts +14 -0
- package/lib/cjs/agents/multi-agent-page-writer.d.ts +48 -0
- package/lib/cjs/agents/multi-agent-page-writer.js +203 -0
- package/lib/cjs/agents/page-metadata-generator.d.ts +10 -0
- package/lib/cjs/agents/page-metadata-generator.js +43 -0
- package/lib/cjs/agents/page-structure-planner.d.ts +55 -0
- package/lib/cjs/agents/page-structure-planner.js +106 -0
- package/lib/cjs/agents/page-structure-validator.d.ts +30 -0
- package/lib/cjs/agents/page-structure-validator.js +124 -0
- package/lib/cjs/agents/sample-html-generator.d.ts +6 -0
- package/lib/cjs/agents/sample-html-generator.js +35 -0
- package/lib/cjs/agents/section-content-generator.d.ts +19 -0
- package/lib/cjs/agents/section-content-generator.js +97 -0
- package/lib/cjs/index.d.ts +7 -0
- package/lib/cjs/index.js +30 -0
- package/lib/cjs/tsconfig.tsbuildinfo +1 -0
- package/lib/cjs/utils/agent-utils.d.ts +3 -0
- package/lib/cjs/utils/agent-utils.js +44 -0
- package/lib/cjs/utils/file-utils.d.ts +5 -0
- package/lib/cjs/utils/file-utils.js +90 -0
- package/lib/cjs/utils/index.d.ts +12 -0
- package/lib/cjs/utils/index.js +48 -0
- package/lib/cjs/utils/logger.d.ts +1 -0
- package/lib/cjs/utils/logger.js +4 -0
- package/lib/cjs/utils/template-utils.d.ts +28 -0
- package/lib/cjs/utils/template-utils.js +74 -0
- package/lib/esm/agents/multi-agent-page-writer.d.ts +48 -0
- package/lib/esm/agents/multi-agent-page-writer.js +199 -0
- package/lib/esm/agents/page-metadata-generator.d.ts +10 -0
- package/lib/esm/agents/page-metadata-generator.js +40 -0
- package/lib/esm/agents/page-structure-planner.d.ts +55 -0
- package/lib/esm/agents/page-structure-planner.js +103 -0
- package/lib/esm/agents/page-structure-validator.d.ts +30 -0
- package/lib/esm/agents/page-structure-validator.js +121 -0
- package/lib/esm/agents/sample-html-generator.d.ts +6 -0
- package/lib/esm/agents/sample-html-generator.js +32 -0
- package/lib/esm/agents/section-content-generator.d.ts +19 -0
- package/lib/esm/agents/section-content-generator.js +94 -0
- package/lib/esm/index.d.ts +7 -0
- package/lib/esm/index.js +8 -0
- package/lib/esm/tsconfig.tsbuildinfo +1 -0
- package/lib/esm/utils/agent-utils.d.ts +3 -0
- package/lib/esm/utils/agent-utils.js +38 -0
- package/lib/esm/utils/file-utils.d.ts +5 -0
- package/lib/esm/utils/file-utils.js +61 -0
- package/lib/esm/utils/index.d.ts +12 -0
- package/lib/esm/utils/index.js +28 -0
- package/lib/esm/utils/logger.d.ts +1 -0
- package/lib/esm/utils/logger.js +1 -0
- package/lib/esm/utils/template-utils.d.ts +28 -0
- package/lib/esm/utils/template-utils.js +67 -0
- package/lib/types/agents/multi-agent-page-writer.d.ts +48 -0
- package/lib/types/agents/page-metadata-generator.d.ts +10 -0
- package/lib/types/agents/page-structure-planner.d.ts +55 -0
- package/lib/types/agents/page-structure-validator.d.ts +30 -0
- package/lib/types/agents/sample-html-generator.d.ts +6 -0
- package/lib/types/agents/section-content-generator.d.ts +19 -0
- package/lib/types/index.d.ts +7 -0
- package/lib/types/tsconfig.tsbuildinfo +1 -0
- package/lib/types/utils/agent-utils.d.ts +3 -0
- package/lib/types/utils/file-utils.d.ts +5 -0
- package/lib/types/utils/index.d.ts +12 -0
- package/lib/types/utils/logger.d.ts +1 -0
- package/lib/types/utils/template-utils.d.ts +28 -0
- package/package.json +46 -0
- package/types.d.ts +4 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Copyright 2018-2020 ArcBlock
|
|
2
|
+
|
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
you may not use this file except in compliance with the License.
|
|
5
|
+
You may obtain a copy of the License at
|
|
6
|
+
|
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
|
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
See the License for the specific language governing permissions and
|
|
13
|
+
limitations under the License.
|
package/README.md
ADDED
package/cli.ts
ADDED
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
import { AIGNE } from '@aigne/core';
|
|
2
|
+
import yaml from 'js-yaml';
|
|
3
|
+
import fs from 'node:fs/promises';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import open from 'open';
|
|
6
|
+
import yargs from 'yargs';
|
|
7
|
+
import { hideBin } from 'yargs/helpers';
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
|
|
10
|
+
import generatePageContentMultiAgent, { type GeneratePageContentInput } from './agents/multi-agent-page-writer.js';
|
|
11
|
+
import { sampleHtmlGeneratorAgent } from './agents/sample-html-generator.js';
|
|
12
|
+
import { generateHtmlFromTemplate, getModel, readFile, saveHtmlContent, updateFileList } from './utils/index.js';
|
|
13
|
+
import { logger } from './utils/logger.js';
|
|
14
|
+
|
|
15
|
+
// 定义配置文件的结构
|
|
16
|
+
const ConfigSchema = z.object({
|
|
17
|
+
models: z.array(
|
|
18
|
+
z.object({
|
|
19
|
+
name: z.string(),
|
|
20
|
+
enabled: z.boolean().default(true),
|
|
21
|
+
})
|
|
22
|
+
),
|
|
23
|
+
outputSettings: z.object({
|
|
24
|
+
useTemplate: z.boolean().default(true),
|
|
25
|
+
openBrowserAfterComplete: z.boolean().default(true),
|
|
26
|
+
}),
|
|
27
|
+
logging: z.object({
|
|
28
|
+
showProgress: z.boolean().default(true),
|
|
29
|
+
}),
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
type Config = z.infer<typeof ConfigSchema>;
|
|
33
|
+
|
|
34
|
+
// 默认配置
|
|
35
|
+
const defaultConfig: Config = {
|
|
36
|
+
models: [
|
|
37
|
+
{ name: 'gpt-4o-mini', enabled: true },
|
|
38
|
+
{ name: 'gemini-2.5-flash-preview-04-17', enabled: true },
|
|
39
|
+
{ name: 'gemini-2.5-pro-preview-05-06', enabled: true },
|
|
40
|
+
// { name: 'claude-3-7-sonnet-latest', enabled: false },
|
|
41
|
+
],
|
|
42
|
+
outputSettings: {
|
|
43
|
+
useTemplate: true,
|
|
44
|
+
openBrowserAfterComplete: true,
|
|
45
|
+
},
|
|
46
|
+
logging: {
|
|
47
|
+
showProgress: true,
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// 加载配置文件
|
|
52
|
+
async function loadConfig(): Promise<Config> {
|
|
53
|
+
const configPath = path.join(__dirname, 'config.yaml');
|
|
54
|
+
try {
|
|
55
|
+
const fileContent = await fs.readFile(configPath, 'utf-8');
|
|
56
|
+
const parsedConfig = yaml.load(fileContent) as any;
|
|
57
|
+
return ConfigSchema.parse(parsedConfig);
|
|
58
|
+
} catch (error) {
|
|
59
|
+
logger.warn(`Failed to load config file: ${error instanceof Error ? error.message : String(error)}`);
|
|
60
|
+
logger.warn('Using default configuration');
|
|
61
|
+
return defaultConfig;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// 处理命令行参数
|
|
66
|
+
function parseCommandLineArgs() {
|
|
67
|
+
return yargs(hideBin(process.argv))
|
|
68
|
+
.option('model', {
|
|
69
|
+
describe: 'Specify a single model to run',
|
|
70
|
+
type: 'string',
|
|
71
|
+
})
|
|
72
|
+
.option('use-template', {
|
|
73
|
+
describe: 'Whether to use template for output',
|
|
74
|
+
type: 'boolean',
|
|
75
|
+
})
|
|
76
|
+
.option('open-browser', {
|
|
77
|
+
describe: 'Open browser after completion',
|
|
78
|
+
type: 'boolean',
|
|
79
|
+
})
|
|
80
|
+
.option('show-progress', {
|
|
81
|
+
describe: 'Show progress logs',
|
|
82
|
+
type: 'boolean',
|
|
83
|
+
})
|
|
84
|
+
.help()
|
|
85
|
+
.parse();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// 定义命令行参数的类型
|
|
89
|
+
interface CommandLineArgs {
|
|
90
|
+
model?: string;
|
|
91
|
+
'use-template'?: boolean;
|
|
92
|
+
'open-browser'?: boolean;
|
|
93
|
+
'show-progress'?: boolean;
|
|
94
|
+
[key: string]: unknown;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// 记录执行时间作为 output 的文件夹名称
|
|
98
|
+
const now = new Date();
|
|
99
|
+
const runTime = `${now.getFullYear()}-${(now.getMonth() + 1).toString().padStart(2, '0')}-${now.getDate().toString().padStart(2, '0')}-${now.getHours().toString().padStart(2, '0')}-${now.getMinutes().toString().padStart(2, '0')}-${now.getSeconds().toString().padStart(2, '0')}`;
|
|
100
|
+
|
|
101
|
+
const generatePageContent = async (
|
|
102
|
+
input: GeneratePageContentInput,
|
|
103
|
+
{
|
|
104
|
+
outputUseTemplate,
|
|
105
|
+
showProgress,
|
|
106
|
+
currentModelIndex,
|
|
107
|
+
totalModels,
|
|
108
|
+
}: {
|
|
109
|
+
outputUseTemplate?: boolean;
|
|
110
|
+
showProgress?: boolean;
|
|
111
|
+
currentModelIndex?: number;
|
|
112
|
+
totalModels?: number;
|
|
113
|
+
} = {
|
|
114
|
+
outputUseTemplate: true,
|
|
115
|
+
showProgress: true,
|
|
116
|
+
}
|
|
117
|
+
) => {
|
|
118
|
+
const modelName = input.modelName || 'gpt-4o-mini';
|
|
119
|
+
|
|
120
|
+
if (showProgress && currentModelIndex !== undefined && totalModels !== undefined) {
|
|
121
|
+
logger.info(
|
|
122
|
+
`Processing model ${currentModelIndex + 1}/${totalModels} (${Math.round(((currentModelIndex + 1) / totalModels) * 100)}%): ${modelName}`
|
|
123
|
+
);
|
|
124
|
+
} else {
|
|
125
|
+
logger.info(`Generating page content with model: ${modelName}`);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (showProgress) {
|
|
129
|
+
logger.info(`[${modelName}] Step 1/2: Generating content structure...`);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const result = await generatePageContentMultiAgent(input);
|
|
133
|
+
|
|
134
|
+
if (!result) {
|
|
135
|
+
throw new Error('Failed to generate page content');
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (showProgress) {
|
|
139
|
+
logger.info(`[${modelName}] Step 2/2: Creating HTML output...`);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (outputUseTemplate) {
|
|
143
|
+
await generateHtmlFromTemplate({
|
|
144
|
+
jsonData: result,
|
|
145
|
+
outputFolder: runTime,
|
|
146
|
+
outputFileName: modelName,
|
|
147
|
+
});
|
|
148
|
+
} else {
|
|
149
|
+
const model = getModel('gemini-2.5-pro-preview-05-06');
|
|
150
|
+
const engine = new AIGNE({
|
|
151
|
+
model,
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
const htmlResult = await engine.invoke(sampleHtmlGeneratorAgent, {
|
|
155
|
+
jsonData: JSON.stringify(result),
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// 保存结果到output目录
|
|
159
|
+
await saveHtmlContent({
|
|
160
|
+
htmlContent: htmlResult.html,
|
|
161
|
+
outputFolder: runTime,
|
|
162
|
+
outputFileName: modelName,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (showProgress) {
|
|
167
|
+
logger.info(`[${modelName}] HTML output completed`);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
logger.info(
|
|
171
|
+
`Generated sample page successfully, model: ${modelName}, review path: ${path.join(process.cwd(), 'sample-output', runTime)}`
|
|
172
|
+
);
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
// 主函数
|
|
176
|
+
async function main() {
|
|
177
|
+
// 加载配置文件
|
|
178
|
+
const config = await loadConfig();
|
|
179
|
+
|
|
180
|
+
// 解析命令行参数
|
|
181
|
+
const args = parseCommandLineArgs() as CommandLineArgs;
|
|
182
|
+
|
|
183
|
+
// 合并配置,命令行参数优先
|
|
184
|
+
const effectiveConfig: Config = {
|
|
185
|
+
...config,
|
|
186
|
+
outputSettings: {
|
|
187
|
+
...config.outputSettings,
|
|
188
|
+
useTemplate:
|
|
189
|
+
args['use-template'] === undefined ? config.outputSettings.useTemplate : Boolean(args['use-template']),
|
|
190
|
+
openBrowserAfterComplete:
|
|
191
|
+
args['open-browser'] === undefined
|
|
192
|
+
? config.outputSettings.openBrowserAfterComplete
|
|
193
|
+
: Boolean(args['open-browser']),
|
|
194
|
+
},
|
|
195
|
+
logging: {
|
|
196
|
+
...config.logging,
|
|
197
|
+
showProgress: args['show-progress'] === undefined ? config.logging.showProgress : Boolean(args['show-progress']),
|
|
198
|
+
},
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
// 如果指定了单个模型,则只运行该模型
|
|
202
|
+
const modelsToRun = args.model
|
|
203
|
+
? [{ name: String(args.model), enabled: true }]
|
|
204
|
+
: effectiveConfig.models.filter((m) => m.enabled);
|
|
205
|
+
|
|
206
|
+
if (modelsToRun.length === 0) {
|
|
207
|
+
logger.warn(
|
|
208
|
+
'No models enabled. Please enable at least one model in config.yaml or specify a model via command line.'
|
|
209
|
+
);
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// 加载上下文
|
|
214
|
+
let context = '';
|
|
215
|
+
context = await readFile(path.join(__dirname, 'data-sources', 'aigne-framework.yaml'));
|
|
216
|
+
|
|
217
|
+
const imagesContext = await readFile(path.join(__dirname, 'data-sources', 'aigne-framework-images.md'));
|
|
218
|
+
|
|
219
|
+
context = `${context}\n
|
|
220
|
+
## 图片资源
|
|
221
|
+
1. 从中挑选相关的图片同合适文案一起展示
|
|
222
|
+
2. 不需要图片的描述和文案完全匹配,只需要相关即可
|
|
223
|
+
${imagesContext}`;
|
|
224
|
+
|
|
225
|
+
const pageRule = `
|
|
226
|
+
生成页面内容,文案有吸引力。
|
|
227
|
+
尽可能多的包含 context 中相关的信息。
|
|
228
|
+
`;
|
|
229
|
+
|
|
230
|
+
const locale = 'zh';
|
|
231
|
+
|
|
232
|
+
const input = {
|
|
233
|
+
context,
|
|
234
|
+
question: pageRule,
|
|
235
|
+
locale,
|
|
236
|
+
outputSchema: z.object({
|
|
237
|
+
title: z.string(),
|
|
238
|
+
description: z.string(),
|
|
239
|
+
sectionsData: z.object({
|
|
240
|
+
heroSection: z.object({
|
|
241
|
+
title: z.string(),
|
|
242
|
+
description: z.string(),
|
|
243
|
+
}),
|
|
244
|
+
featuresSection: z.object({
|
|
245
|
+
title: z.string(),
|
|
246
|
+
description: z.string(),
|
|
247
|
+
features: z.array(
|
|
248
|
+
z.object({
|
|
249
|
+
title: z.string(),
|
|
250
|
+
description: z.string(),
|
|
251
|
+
image: z.string(),
|
|
252
|
+
})
|
|
253
|
+
),
|
|
254
|
+
}),
|
|
255
|
+
architectureSection: z.object({
|
|
256
|
+
title: z.string(),
|
|
257
|
+
description: z.string(),
|
|
258
|
+
architecture: z.array(
|
|
259
|
+
z.object({
|
|
260
|
+
title: z.string(),
|
|
261
|
+
description: z.string(),
|
|
262
|
+
image: z.string(),
|
|
263
|
+
})
|
|
264
|
+
),
|
|
265
|
+
}),
|
|
266
|
+
workflowSection: z.object({
|
|
267
|
+
title: z.string(),
|
|
268
|
+
description: z.string(),
|
|
269
|
+
workflows: z.array(
|
|
270
|
+
z.object({
|
|
271
|
+
title: z.string(),
|
|
272
|
+
description: z.string(),
|
|
273
|
+
})
|
|
274
|
+
),
|
|
275
|
+
}),
|
|
276
|
+
mcpIntegrationSection: z.object({
|
|
277
|
+
title: z.string(),
|
|
278
|
+
description: z.string(),
|
|
279
|
+
integrations: z.array(
|
|
280
|
+
z.object({
|
|
281
|
+
title: z.string(),
|
|
282
|
+
description: z.string(),
|
|
283
|
+
})
|
|
284
|
+
),
|
|
285
|
+
}),
|
|
286
|
+
supportModelSection: z.object({
|
|
287
|
+
title: z.string(),
|
|
288
|
+
models: z.array(
|
|
289
|
+
z.object({
|
|
290
|
+
name: z.string(),
|
|
291
|
+
link: z.string(),
|
|
292
|
+
})
|
|
293
|
+
),
|
|
294
|
+
}),
|
|
295
|
+
faqSection: z.object({
|
|
296
|
+
title: z.string(),
|
|
297
|
+
description: z.string(),
|
|
298
|
+
questions: z.array(
|
|
299
|
+
z.object({
|
|
300
|
+
question: z.string(),
|
|
301
|
+
answer: z.string(),
|
|
302
|
+
})
|
|
303
|
+
),
|
|
304
|
+
}),
|
|
305
|
+
callToActionSection: z.object({
|
|
306
|
+
title: z.string(),
|
|
307
|
+
description: z.string(),
|
|
308
|
+
cta: z.string(),
|
|
309
|
+
}),
|
|
310
|
+
}),
|
|
311
|
+
}),
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
// 循环执行每个启用的模型
|
|
315
|
+
for (let i = 0; i < modelsToRun.length; i++) {
|
|
316
|
+
const model = modelsToRun[i];
|
|
317
|
+
if (model) {
|
|
318
|
+
try {
|
|
319
|
+
// eslint-disable-next-line no-await-in-loop
|
|
320
|
+
await generatePageContent(
|
|
321
|
+
{ ...input, modelName: model.name },
|
|
322
|
+
{
|
|
323
|
+
outputUseTemplate: effectiveConfig.outputSettings.useTemplate,
|
|
324
|
+
showProgress: effectiveConfig.logging.showProgress,
|
|
325
|
+
currentModelIndex: i,
|
|
326
|
+
totalModels: modelsToRun.length,
|
|
327
|
+
}
|
|
328
|
+
);
|
|
329
|
+
} catch (error) {
|
|
330
|
+
logger.error(
|
|
331
|
+
`Error generating page content for model ${model.name}: ${error instanceof Error ? error.message : String(error)}`
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
} else {
|
|
335
|
+
logger.warn(`Model at index ${i} is undefined, skipping`);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// 更新文件列表
|
|
340
|
+
await updateFileList();
|
|
341
|
+
|
|
342
|
+
// 如果配置启用了浏览器自动打开,则打开index.html
|
|
343
|
+
if (effectiveConfig.outputSettings.openBrowserAfterComplete) {
|
|
344
|
+
const indexPath = path.join(process.cwd(), 'sample-output', 'index.html');
|
|
345
|
+
await open(indexPath);
|
|
346
|
+
logger.info('Opened browser to view results');
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// 执行主函数
|
|
351
|
+
main().catch((error) => {
|
|
352
|
+
logger.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
353
|
+
process.exit(1);
|
|
354
|
+
});
|
package/index.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export {};
|
|
2
|
+
|
|
3
|
+
// Export all agents
|
|
4
|
+
export {
|
|
5
|
+
default as generatePageContentMultiAgent,
|
|
6
|
+
generateSingleSectionContent,
|
|
7
|
+
} from './agents/multi-agent-page-writer';
|
|
8
|
+
export * from './agents/page-metadata-generator';
|
|
9
|
+
export * from './agents/page-structure-planner';
|
|
10
|
+
export * from './agents/page-structure-validator';
|
|
11
|
+
export * from './agents/section-content-generator';
|
|
12
|
+
|
|
13
|
+
// Export utilities that might be useful for consumers
|
|
14
|
+
export * from './utils/index';
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { z } from 'zod';
|
|
2
|
+
export interface GeneratePageContentInput {
|
|
3
|
+
context: string;
|
|
4
|
+
question: string;
|
|
5
|
+
sectionsRules?: Record<string, string>;
|
|
6
|
+
locale: string;
|
|
7
|
+
outputSchema: z.ZodObject<any>;
|
|
8
|
+
modelName?: string;
|
|
9
|
+
onProgress?: (params: {
|
|
10
|
+
sectionName?: string;
|
|
11
|
+
sectionIndex?: number;
|
|
12
|
+
totalSections: number;
|
|
13
|
+
sectionData?: Record<string, any>;
|
|
14
|
+
eventType?: 'progress' | 'section' | 'structure_start' | 'structure_complete';
|
|
15
|
+
structureData?: any;
|
|
16
|
+
}) => void;
|
|
17
|
+
checkConnection?: () => boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* 多Agent协作生成页面内容
|
|
21
|
+
*
|
|
22
|
+
* 工作流程:
|
|
23
|
+
* 1. 使用页面结构规划Agent分析内容,规划各section内容
|
|
24
|
+
* 2. 使用结构验证Agent检查规划的完整性和有效性
|
|
25
|
+
* 3. 如果验证不通过,将反馈提供给规划Agent进行修正
|
|
26
|
+
* 4. 逐个生成各section内容
|
|
27
|
+
* 5. 基于所有section内容生成页面元数据
|
|
28
|
+
* 6. 整合所有内容返回完整页面数据
|
|
29
|
+
*/
|
|
30
|
+
export default function generatePageContentMultiAgent(input: GeneratePageContentInput): Promise<{
|
|
31
|
+
title: string;
|
|
32
|
+
description: string;
|
|
33
|
+
sectionsData: Record<string, any>;
|
|
34
|
+
} | null>;
|
|
35
|
+
/**
|
|
36
|
+
* 单独生成特定section的内容
|
|
37
|
+
* 支持独立调用,为特定section重新生成内容
|
|
38
|
+
*/
|
|
39
|
+
export declare function generateSingleSectionContent({ context, question, locale, sectionName, sectionSchema, sectionPlan, existingSections, modelName, }: {
|
|
40
|
+
context: string;
|
|
41
|
+
question: string;
|
|
42
|
+
locale: string;
|
|
43
|
+
sectionName: string;
|
|
44
|
+
sectionSchema: any;
|
|
45
|
+
sectionPlan?: string;
|
|
46
|
+
existingSections?: Record<string, any>;
|
|
47
|
+
modelName?: string;
|
|
48
|
+
}): Promise<import("@aigne/core").Message>;
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = generatePageContentMultiAgent;
|
|
4
|
+
exports.generateSingleSectionContent = generateSingleSectionContent;
|
|
5
|
+
const core_1 = require("@aigne/core");
|
|
6
|
+
const zod_utils_1 = require("@blocklet/pages-kit-block-studio/zod-utils");
|
|
7
|
+
const agent_utils_js_1 = require("../utils/agent-utils.js");
|
|
8
|
+
const logger_js_1 = require("../utils/logger.js");
|
|
9
|
+
const page_metadata_generator_js_1 = require("./page-metadata-generator.js");
|
|
10
|
+
const page_structure_planner_js_1 = require("./page-structure-planner.js");
|
|
11
|
+
const page_structure_validator_js_1 = require("./page-structure-validator.js");
|
|
12
|
+
const section_content_generator_js_1 = require("./section-content-generator.js");
|
|
13
|
+
/**
|
|
14
|
+
* 多Agent协作生成页面内容
|
|
15
|
+
*
|
|
16
|
+
* 工作流程:
|
|
17
|
+
* 1. 使用页面结构规划Agent分析内容,规划各section内容
|
|
18
|
+
* 2. 使用结构验证Agent检查规划的完整性和有效性
|
|
19
|
+
* 3. 如果验证不通过,将反馈提供给规划Agent进行修正
|
|
20
|
+
* 4. 逐个生成各section内容
|
|
21
|
+
* 5. 基于所有section内容生成页面元数据
|
|
22
|
+
* 6. 整合所有内容返回完整页面数据
|
|
23
|
+
*/
|
|
24
|
+
async function generatePageContentMultiAgent(input) {
|
|
25
|
+
const { context = '', question = '', locale = '', outputSchema, onProgress, checkConnection, sectionsRules, modelName = 'gpt-4o-mini', } = input;
|
|
26
|
+
try {
|
|
27
|
+
logger_js_1.logger.info('Starting multi-agent page content generation');
|
|
28
|
+
// 检查客户端连接状态的辅助函数
|
|
29
|
+
const isClientConnected = () => {
|
|
30
|
+
// 如果没有提供检查函数,默认认为客户端仍连接
|
|
31
|
+
if (!checkConnection)
|
|
32
|
+
return true;
|
|
33
|
+
// 否则调用提供的检查函数
|
|
34
|
+
return checkConnection();
|
|
35
|
+
};
|
|
36
|
+
// 1. 从outputSchema提取sectionsData结构
|
|
37
|
+
const outputSchemaJson = (0, zod_utils_1.zodSchemaToJsonSchema)(outputSchema);
|
|
38
|
+
const sectionsSchema = outputSchema.shape.sectionsData;
|
|
39
|
+
const sectionNames = Object.keys(sectionsSchema.shape);
|
|
40
|
+
// 触发页面结构开始生成事件
|
|
41
|
+
if (onProgress) {
|
|
42
|
+
onProgress({
|
|
43
|
+
totalSections: sectionNames.length,
|
|
44
|
+
eventType: 'structure_start',
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
// 2. 初始页面结构规划
|
|
48
|
+
logger_js_1.logger.info('Planning initial page structure');
|
|
49
|
+
// 检查客户端是否仍然连接
|
|
50
|
+
if (!isClientConnected()) {
|
|
51
|
+
logger_js_1.logger.warn('Client disconnected during structure planning, aborting generation');
|
|
52
|
+
throw new Error('Client disconnected');
|
|
53
|
+
}
|
|
54
|
+
let structurePlanMap = {};
|
|
55
|
+
const model = (0, agent_utils_js_1.getModel)(modelName);
|
|
56
|
+
// 3-4 使用反思工作流生成页面结构
|
|
57
|
+
const planningEngine = new core_1.AIGNE({
|
|
58
|
+
model,
|
|
59
|
+
agents: [page_structure_planner_js_1.pageStructurePlannerAgent, page_structure_validator_js_1.pageStructureValidatorAgent],
|
|
60
|
+
limits: {
|
|
61
|
+
maxAgentInvokes: 20,
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
await planningEngine.invoke(page_structure_planner_js_1.pageStructurePlannerAgent, {
|
|
65
|
+
context,
|
|
66
|
+
question,
|
|
67
|
+
locale,
|
|
68
|
+
initialStructurePlan: Object.entries(sectionsRules || {}).map(([sectionName, sectionContentPlan]) => ({
|
|
69
|
+
sectionName,
|
|
70
|
+
sectionContentPlan,
|
|
71
|
+
})),
|
|
72
|
+
outputSchema: JSON.stringify(outputSchemaJson),
|
|
73
|
+
expectedSections: JSON.stringify(sectionNames),
|
|
74
|
+
});
|
|
75
|
+
const structurePlanResult = await planningEngine.subscribe(core_1.UserOutputTopic);
|
|
76
|
+
const { structurePlan } = structurePlanResult.message;
|
|
77
|
+
// const { structurePlan } = structurePlanResult;
|
|
78
|
+
logger_js_1.logger.info('Initial structure plan generated', structurePlan);
|
|
79
|
+
await planningEngine.shutdown();
|
|
80
|
+
// 触发页面结构生成成功事件
|
|
81
|
+
if (onProgress) {
|
|
82
|
+
onProgress({
|
|
83
|
+
totalSections: sectionNames.length,
|
|
84
|
+
eventType: 'structure_complete',
|
|
85
|
+
structureData: {
|
|
86
|
+
structurePlan,
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
structurePlanMap = Object.fromEntries(structurePlan.map((item) => [item.sectionName, item.sectionContentPlan]));
|
|
91
|
+
const engine = new core_1.AIGNE({
|
|
92
|
+
model,
|
|
93
|
+
});
|
|
94
|
+
// 5. 逐个生成各section内容
|
|
95
|
+
const sectionsData = {};
|
|
96
|
+
for (let i = 0; i < sectionNames.length; i++) {
|
|
97
|
+
const sectionName = sectionNames[i];
|
|
98
|
+
if (!sectionName) {
|
|
99
|
+
// eslint-disable-next-line no-continue
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
// 每个section生成前检查客户端连接状态
|
|
103
|
+
if (!isClientConnected()) {
|
|
104
|
+
logger_js_1.logger.warn(`Client disconnected before generating section ${sectionName}, aborting generation`);
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
logger_js_1.logger.info(`Generating content for section: ${sectionName}`);
|
|
108
|
+
// 通知当前正在处理的section
|
|
109
|
+
if (onProgress) {
|
|
110
|
+
onProgress({
|
|
111
|
+
sectionName,
|
|
112
|
+
sectionIndex: i,
|
|
113
|
+
totalSections: sectionNames.length,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
const sectionSchema = sectionsSchema.shape[sectionName];
|
|
117
|
+
const sectionPlan = structurePlanMap[sectionName] || `Generate content for ${sectionName}`;
|
|
118
|
+
const sectionContentInput = {
|
|
119
|
+
context,
|
|
120
|
+
question,
|
|
121
|
+
locale,
|
|
122
|
+
sectionName,
|
|
123
|
+
sectionSchema,
|
|
124
|
+
sectionPlan,
|
|
125
|
+
generatedSections: JSON.stringify(sectionsData), // 传递已生成的sections
|
|
126
|
+
};
|
|
127
|
+
// eslint-disable-next-line no-await-in-loop
|
|
128
|
+
const sectionContentAgent = await (0, section_content_generator_js_1.createSectionContentAgent)(sectionContentInput);
|
|
129
|
+
// eslint-disable-next-line no-await-in-loop
|
|
130
|
+
const sectionContent = await engine.invoke(sectionContentAgent, sectionContentInput);
|
|
131
|
+
sectionsData[sectionName] = sectionContent;
|
|
132
|
+
logger_js_1.logger.info(`Content generated for section: ${sectionName}`);
|
|
133
|
+
// 通知该section已生成完成
|
|
134
|
+
if (onProgress) {
|
|
135
|
+
const sectionDataObj = {};
|
|
136
|
+
sectionDataObj[sectionName] = sectionContent;
|
|
137
|
+
onProgress({
|
|
138
|
+
sectionName,
|
|
139
|
+
sectionIndex: i,
|
|
140
|
+
totalSections: sectionNames.length,
|
|
141
|
+
sectionData: sectionDataObj,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
// 6. 生成页面元数据
|
|
146
|
+
logger_js_1.logger.info('Generating page metadata');
|
|
147
|
+
// 检查客户端是否仍然连接
|
|
148
|
+
if (!isClientConnected()) {
|
|
149
|
+
logger_js_1.logger.warn('Client disconnected before generating metadata, aborting generation');
|
|
150
|
+
throw new Error('Client disconnected');
|
|
151
|
+
}
|
|
152
|
+
const metadata = await engine.invoke(page_metadata_generator_js_1.generatePageMetadataAgent, {
|
|
153
|
+
context,
|
|
154
|
+
question,
|
|
155
|
+
locale,
|
|
156
|
+
sectionsData: JSON.stringify(sectionsData),
|
|
157
|
+
});
|
|
158
|
+
// 7. 组装完整页面数据
|
|
159
|
+
const result = {
|
|
160
|
+
title: metadata.title,
|
|
161
|
+
description: metadata.description,
|
|
162
|
+
sectionsData,
|
|
163
|
+
};
|
|
164
|
+
logger_js_1.logger.info('Multi-agent page content generation completed');
|
|
165
|
+
return result;
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
logger_js_1.logger.error('Error in multi-agent page content generation:', error);
|
|
169
|
+
throw error;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* 单独生成特定section的内容
|
|
174
|
+
* 支持独立调用,为特定section重新生成内容
|
|
175
|
+
*/
|
|
176
|
+
async function generateSingleSectionContent({ context, question, locale, sectionName, sectionSchema, sectionPlan, existingSections = {}, modelName = 'gpt-4o-mini', }) {
|
|
177
|
+
try {
|
|
178
|
+
logger_js_1.logger.info(`Starting single section content generation for: ${sectionName}`);
|
|
179
|
+
const actualSectionPlan = sectionPlan || `Generate content for ${sectionName}`;
|
|
180
|
+
const sectionContentInput = {
|
|
181
|
+
context,
|
|
182
|
+
question,
|
|
183
|
+
locale,
|
|
184
|
+
sectionName,
|
|
185
|
+
sectionSchema,
|
|
186
|
+
sectionPlan: actualSectionPlan,
|
|
187
|
+
generatedSections: JSON.stringify(existingSections),
|
|
188
|
+
};
|
|
189
|
+
const sectionContentAgent = await (0, section_content_generator_js_1.createSectionContentAgent)(sectionContentInput);
|
|
190
|
+
const model = (0, agent_utils_js_1.getModel)(modelName);
|
|
191
|
+
const engine = new core_1.AIGNE({
|
|
192
|
+
model,
|
|
193
|
+
});
|
|
194
|
+
// eslint-disable-next-line no-await-in-loop
|
|
195
|
+
const sectionContent = await engine.invoke(sectionContentAgent, sectionContentInput);
|
|
196
|
+
logger_js_1.logger.info(`Single section content generated for: ${sectionName}`);
|
|
197
|
+
return sectionContent;
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
logger_js_1.logger.error(`Error generating content for section ${sectionName}:`, error);
|
|
201
|
+
throw error;
|
|
202
|
+
}
|
|
203
|
+
}
|