htmlgen-mcp 0.3.5__tar.gz → 0.3.7__tar.gz
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.
Potentially problematic release.
This version of htmlgen-mcp might be problematic. Click here for more details.
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/PKG-INFO +1 -1
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/pyproject.toml +1 -1
- htmlgen_mcp-0.3.7/src/htmlgen_mcp/context_aware_executor.py +262 -0
- htmlgen_mcp-0.3.7/src/htmlgen_mcp/prompt_enhancer.py +240 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp/web_agent_server.py +136 -56
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp.egg-info/PKG-INFO +1 -1
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp.egg-info/SOURCES.txt +2 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/README.md +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/setup.cfg +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp/__init__.py +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp/agents/__init__.py +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp/agents/ai_content_generator.py +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp/agents/quick_generator.py +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp/agents/smart_web_agent.py +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp/agents/web_tools/__init__.py +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp/agents/web_tools/bootstrap.py +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp/agents/web_tools/browser.py +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp/agents/web_tools/colors.py +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp/agents/web_tools/css.py +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp/agents/web_tools/edgeone_deploy.py +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp/agents/web_tools/html_templates.py +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp/agents/web_tools/html_templates_improved.py +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp/agents/web_tools/images.py +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp/agents/web_tools/images_fixed.py +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp/agents/web_tools/js.py +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp/agents/web_tools/navigation.py +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp/agents/web_tools/project.py +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp/agents/web_tools/simple_builder.py +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp/agents/web_tools/simple_css.py +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp/agents/web_tools/simple_js.py +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp/agents/web_tools/simple_templates.py +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp/agents/web_tools/validation.py +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp/config.py +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp/improved_progress.py +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp/nas_log_manager.py +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp/nas_storage.py +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp/progress_tools.py +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp/progress_tracker.py +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp/sse_optimizations.py +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp.egg-info/dependency_links.txt +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp.egg-info/entry_points.txt +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp.egg-info/requires.txt +0 -0
- {htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp.egg-info/top_level.txt +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "htmlgen-mcp"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.7"
|
|
8
8
|
description = "AI-powered HTML website generator with auto-upload functionality via Model Context Protocol"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
"""上下文感知的执行器 - 确保 context_content 被正确使用"""
|
|
2
|
+
import json
|
|
3
|
+
from typing import Dict, Any, Optional
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ContextAwareExecutor:
|
|
7
|
+
"""确保上下文内容在执行过程中被正确传递和使用"""
|
|
8
|
+
|
|
9
|
+
@staticmethod
|
|
10
|
+
def inject_context_to_tools(plan: Dict[str, Any], context_content: str) -> Dict[str, Any]:
|
|
11
|
+
"""
|
|
12
|
+
将上下文内容注入到工具调用序列中
|
|
13
|
+
|
|
14
|
+
Args:
|
|
15
|
+
plan: 执行计划
|
|
16
|
+
context_content: 上下文内容(如咖啡馆列表)
|
|
17
|
+
|
|
18
|
+
Returns:
|
|
19
|
+
修改后的计划
|
|
20
|
+
"""
|
|
21
|
+
if not context_content:
|
|
22
|
+
return plan
|
|
23
|
+
|
|
24
|
+
# 获取工具序列
|
|
25
|
+
tools_sequence = plan.get("tools_sequence", [])
|
|
26
|
+
|
|
27
|
+
# 遍历每个工具调用,注入上下文
|
|
28
|
+
for tool in tools_sequence:
|
|
29
|
+
tool_name = tool.get("tool", "")
|
|
30
|
+
|
|
31
|
+
# 对于创建 HTML 文件的工具,注入具体内容
|
|
32
|
+
if tool_name == "create_html_file":
|
|
33
|
+
# 修改内容参数,确保包含实际数据
|
|
34
|
+
original_content = tool.get("parameters", {}).get("content", "")
|
|
35
|
+
|
|
36
|
+
# 如果是主页面,替换内容
|
|
37
|
+
if "index.html" in tool.get("parameters", {}).get("file_name", ""):
|
|
38
|
+
tool["parameters"]["content"] = generate_html_with_context(
|
|
39
|
+
context_content,
|
|
40
|
+
tool.get("parameters", {}).get("title", "网站")
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
# 对于创建内容的工具,也要注入上下文
|
|
44
|
+
elif tool_name in ["add_content_section", "create_content", "add_text_content"]:
|
|
45
|
+
# 确保内容参数包含实际数据
|
|
46
|
+
tool["parameters"]["context_data"] = context_content
|
|
47
|
+
|
|
48
|
+
return plan
|
|
49
|
+
|
|
50
|
+
@staticmethod
|
|
51
|
+
def enhance_prompt_with_context(prompt: str, context_content: str) -> str:
|
|
52
|
+
"""
|
|
53
|
+
增强提示词,明确要求使用上下文内容
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
prompt: 原始提示词
|
|
57
|
+
context_content: 上下文内容
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
增强后的提示词
|
|
61
|
+
"""
|
|
62
|
+
if not context_content:
|
|
63
|
+
return prompt
|
|
64
|
+
|
|
65
|
+
enhanced = f"""
|
|
66
|
+
{prompt}
|
|
67
|
+
|
|
68
|
+
【重要:必须使用以下具体数据】
|
|
69
|
+
以下是必须在网页中展示的实际内容,请完整地将这些信息整合到网页中:
|
|
70
|
+
|
|
71
|
+
{context_content}
|
|
72
|
+
|
|
73
|
+
要求:
|
|
74
|
+
1. 必须将上述所有咖啡馆信息完整展示在网页中
|
|
75
|
+
2. 使用卡片或列表形式展示每个咖啡馆
|
|
76
|
+
3. 包含咖啡馆名称和地址
|
|
77
|
+
4. 可以添加适当的样式和布局,但内容必须准确
|
|
78
|
+
5. 不要生成虚构的内容,只使用提供的实际数据
|
|
79
|
+
"""
|
|
80
|
+
return enhanced
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def generate_html_with_context(context_content: str, title: str = "咖啡馆指南") -> str:
|
|
84
|
+
"""
|
|
85
|
+
根据上下文内容生成 HTML
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
context_content: 咖啡馆列表等具体内容
|
|
89
|
+
title: 网站标题
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
完整的 HTML 内容
|
|
93
|
+
"""
|
|
94
|
+
# 解析咖啡馆信息
|
|
95
|
+
cafes = []
|
|
96
|
+
lines = context_content.split('\n')
|
|
97
|
+
current_cafe = {}
|
|
98
|
+
|
|
99
|
+
for line in lines:
|
|
100
|
+
line = line.strip()
|
|
101
|
+
if not line:
|
|
102
|
+
continue
|
|
103
|
+
|
|
104
|
+
# 识别咖啡馆名称(带序号的行)
|
|
105
|
+
if line[0].isdigit() and '. ' in line:
|
|
106
|
+
if current_cafe:
|
|
107
|
+
cafes.append(current_cafe)
|
|
108
|
+
# 提取咖啡馆名称
|
|
109
|
+
name = line.split('. ', 1)[1] if '. ' in line else line
|
|
110
|
+
current_cafe = {'name': name, 'address': ''}
|
|
111
|
+
|
|
112
|
+
# 识别地址(- 开头的行)
|
|
113
|
+
elif line.startswith('- 地址:'):
|
|
114
|
+
if current_cafe:
|
|
115
|
+
current_cafe['address'] = line.replace('- 地址:', '').strip()
|
|
116
|
+
|
|
117
|
+
# 添加最后一个咖啡馆
|
|
118
|
+
if current_cafe:
|
|
119
|
+
cafes.append(current_cafe)
|
|
120
|
+
|
|
121
|
+
# 生成 HTML
|
|
122
|
+
cafe_cards = []
|
|
123
|
+
for cafe in cafes:
|
|
124
|
+
card = f'''
|
|
125
|
+
<div class="col-md-6 col-lg-4 mb-4">
|
|
126
|
+
<div class="card h-100 shadow-sm">
|
|
127
|
+
<div class="card-body">
|
|
128
|
+
<h5 class="card-title">
|
|
129
|
+
<i class="bi bi-cup-hot-fill text-brown"></i> {cafe['name']}
|
|
130
|
+
</h5>
|
|
131
|
+
<p class="card-text">
|
|
132
|
+
<i class="bi bi-geo-alt-fill text-muted"></i>
|
|
133
|
+
<span class="text-muted">{cafe['address']}</span>
|
|
134
|
+
</p>
|
|
135
|
+
<a href="#" class="btn btn-outline-primary btn-sm">
|
|
136
|
+
<i class="bi bi-map"></i> 查看地图
|
|
137
|
+
</a>
|
|
138
|
+
</div>
|
|
139
|
+
</div>
|
|
140
|
+
</div>'''
|
|
141
|
+
cafe_cards.append(card)
|
|
142
|
+
|
|
143
|
+
html = f'''<!DOCTYPE html>
|
|
144
|
+
<html lang="zh-CN">
|
|
145
|
+
<head>
|
|
146
|
+
<meta charset="UTF-8">
|
|
147
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
148
|
+
<title>{title}</title>
|
|
149
|
+
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
150
|
+
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css" rel="stylesheet">
|
|
151
|
+
<link href="assets/css/style.css" rel="stylesheet">
|
|
152
|
+
<style>
|
|
153
|
+
.text-brown {{ color: #6f4e37; }}
|
|
154
|
+
.hero-section {{
|
|
155
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
156
|
+
color: white;
|
|
157
|
+
padding: 80px 0;
|
|
158
|
+
}}
|
|
159
|
+
.card {{
|
|
160
|
+
transition: transform 0.3s;
|
|
161
|
+
border-radius: 15px;
|
|
162
|
+
}}
|
|
163
|
+
.card:hover {{
|
|
164
|
+
transform: translateY(-5px);
|
|
165
|
+
}}
|
|
166
|
+
</style>
|
|
167
|
+
</head>
|
|
168
|
+
<body>
|
|
169
|
+
<!-- 导航栏 -->
|
|
170
|
+
<nav class="navbar navbar-expand-lg navbar-light bg-light shadow-sm">
|
|
171
|
+
<div class="container">
|
|
172
|
+
<a class="navbar-brand" href="#">
|
|
173
|
+
<i class="bi bi-cup-hot-fill text-brown"></i> {title}
|
|
174
|
+
</a>
|
|
175
|
+
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
|
176
|
+
<span class="navbar-toggler-icon"></span>
|
|
177
|
+
</button>
|
|
178
|
+
<div class="collapse navbar-collapse" id="navbarNav">
|
|
179
|
+
<ul class="navbar-nav ms-auto">
|
|
180
|
+
<li class="nav-item">
|
|
181
|
+
<a class="nav-link" href="#cafes">咖啡馆列表</a>
|
|
182
|
+
</li>
|
|
183
|
+
<li class="nav-item">
|
|
184
|
+
<a class="nav-link" href="#about">关于</a>
|
|
185
|
+
</li>
|
|
186
|
+
</ul>
|
|
187
|
+
</div>
|
|
188
|
+
</div>
|
|
189
|
+
</nav>
|
|
190
|
+
|
|
191
|
+
<!-- Hero 区域 -->
|
|
192
|
+
<section class="hero-section text-center">
|
|
193
|
+
<div class="container">
|
|
194
|
+
<h1 class="display-4 fw-bold mb-4">{title}</h1>
|
|
195
|
+
<p class="lead mb-4">探索大族广场周边的精品咖啡馆</p>
|
|
196
|
+
<p class="mb-4">共收录 {len(cafes)} 家咖啡馆,均在步行范围内</p>
|
|
197
|
+
<a href="#cafes" class="btn btn-light btn-lg">
|
|
198
|
+
<i class="bi bi-arrow-down-circle"></i> 浏览咖啡馆
|
|
199
|
+
</a>
|
|
200
|
+
</div>
|
|
201
|
+
</section>
|
|
202
|
+
|
|
203
|
+
<!-- 咖啡馆列表 -->
|
|
204
|
+
<section id="cafes" class="py-5">
|
|
205
|
+
<div class="container">
|
|
206
|
+
<h2 class="text-center mb-5">咖啡馆列表</h2>
|
|
207
|
+
<div class="row">
|
|
208
|
+
{"".join(cafe_cards)}
|
|
209
|
+
</div>
|
|
210
|
+
</div>
|
|
211
|
+
</section>
|
|
212
|
+
|
|
213
|
+
<!-- 关于区域 -->
|
|
214
|
+
<section id="about" class="py-5 bg-light">
|
|
215
|
+
<div class="container">
|
|
216
|
+
<div class="row align-items-center">
|
|
217
|
+
<div class="col-md-6">
|
|
218
|
+
<h2>关于本指南</h2>
|
|
219
|
+
<p class="lead">为您精选大族广场附近的咖啡馆</p>
|
|
220
|
+
<p>本指南收录了北京市大兴区大族广场周边1公里范围内的所有知名咖啡馆,包括星巴克、Peet's Coffee、M Stand等品牌,以及特色独立咖啡馆。</p>
|
|
221
|
+
<p>无论您是需要商务洽谈的安静环境,还是休闲放松的舒适空间,都能在这里找到合适的选择。</p>
|
|
222
|
+
</div>
|
|
223
|
+
<div class="col-md-6">
|
|
224
|
+
<div class="p-4 bg-white rounded shadow">
|
|
225
|
+
<h4><i class="bi bi-info-circle-fill text-primary"></i> 实用信息</h4>
|
|
226
|
+
<ul class="list-unstyled mt-3">
|
|
227
|
+
<li class="mb-2">
|
|
228
|
+
<i class="bi bi-geo-alt text-muted"></i>
|
|
229
|
+
位置:北京市大兴区荣华南路
|
|
230
|
+
</li>
|
|
231
|
+
<li class="mb-2">
|
|
232
|
+
<i class="bi bi-clock text-muted"></i>
|
|
233
|
+
营业时间:大部分 7:00-22:00
|
|
234
|
+
</li>
|
|
235
|
+
<li class="mb-2">
|
|
236
|
+
<i class="bi bi-wifi text-muted"></i>
|
|
237
|
+
设施:WiFi、充电插座
|
|
238
|
+
</li>
|
|
239
|
+
<li class="mb-2">
|
|
240
|
+
<i class="bi bi-car-front text-muted"></i>
|
|
241
|
+
交通:地铁亦庄线荣昌东街站
|
|
242
|
+
</li>
|
|
243
|
+
</ul>
|
|
244
|
+
</div>
|
|
245
|
+
</div>
|
|
246
|
+
</div>
|
|
247
|
+
</div>
|
|
248
|
+
</section>
|
|
249
|
+
|
|
250
|
+
<!-- 页脚 -->
|
|
251
|
+
<footer class="bg-dark text-white py-4 mt-5">
|
|
252
|
+
<div class="container text-center">
|
|
253
|
+
<p class="mb-0">© 2024 {title}. 信息仅供参考,请以实际为准。</p>
|
|
254
|
+
</div>
|
|
255
|
+
</footer>
|
|
256
|
+
|
|
257
|
+
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
|
258
|
+
<script src="assets/js/main.js"></script>
|
|
259
|
+
</body>
|
|
260
|
+
</html>'''
|
|
261
|
+
|
|
262
|
+
return html
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
"""提示词增强模块 - 确保AI使用真实数据而非生成示例"""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class PromptEnhancer:
|
|
5
|
+
"""提示词增强器,用于改进AI对真实数据的处理"""
|
|
6
|
+
|
|
7
|
+
@staticmethod
|
|
8
|
+
def enhance_for_real_data(base_prompt: str, context_data: str = None) -> str:
|
|
9
|
+
"""
|
|
10
|
+
增强提示词,确保AI使用真实数据
|
|
11
|
+
|
|
12
|
+
Args:
|
|
13
|
+
base_prompt: 基础提示词
|
|
14
|
+
context_data: 上下文数据内容
|
|
15
|
+
|
|
16
|
+
Returns:
|
|
17
|
+
增强后的提示词
|
|
18
|
+
"""
|
|
19
|
+
if not context_data:
|
|
20
|
+
return base_prompt
|
|
21
|
+
|
|
22
|
+
# 分析数据类型
|
|
23
|
+
data_type = PromptEnhancer._analyze_data_type(context_data)
|
|
24
|
+
|
|
25
|
+
# 根据数据类型生成特定的指令
|
|
26
|
+
specific_instructions = PromptEnhancer._get_specific_instructions(data_type, context_data)
|
|
27
|
+
|
|
28
|
+
enhanced = f"""
|
|
29
|
+
{base_prompt}
|
|
30
|
+
|
|
31
|
+
【🔴 极其重要的数据使用规则 🔴】
|
|
32
|
+
=====================================
|
|
33
|
+
以下是必须严格遵守的数据使用规则:
|
|
34
|
+
|
|
35
|
+
1. 【数据来源】下面提供的是真实的业务数据,不是示例或模板
|
|
36
|
+
2. 【使用要求】必须100%使用这些数据,不得修改、省略或虚构
|
|
37
|
+
3. 【禁止行为】严禁生成以下虚构内容:
|
|
38
|
+
- ❌ 虚构的客户评价(如"设计质感与转化率提升明显")
|
|
39
|
+
- ❌ 虚构的定价方案(如"¥9,999起步套餐")
|
|
40
|
+
- ❌ 虚构的服务内容(如"品牌升级与重构")
|
|
41
|
+
- ❌ 占位符内容(如"Lorem ipsum"或"示例文本")
|
|
42
|
+
|
|
43
|
+
4. 【正确做法】:
|
|
44
|
+
- ✅ 完整展示所有提供的数据项
|
|
45
|
+
- ✅ 保持数据的原始格式和内容
|
|
46
|
+
- ✅ 使用合适的布局展示(卡片、列表、表格等)
|
|
47
|
+
- ✅ 可以添加导航、样式,但内容必须是提供的真实数据
|
|
48
|
+
|
|
49
|
+
【必须使用的真实数据】
|
|
50
|
+
=====================================
|
|
51
|
+
{context_data}
|
|
52
|
+
=====================================
|
|
53
|
+
|
|
54
|
+
{specific_instructions}
|
|
55
|
+
|
|
56
|
+
【工具调用要求】
|
|
57
|
+
=====================================
|
|
58
|
+
在调用以下工具时,必须包含真实数据:
|
|
59
|
+
- create_html_file: content参数必须包含上述真实数据
|
|
60
|
+
- add_content_section: 必须使用真实数据填充内容
|
|
61
|
+
- create_text_content: 文本内容必须来自上述数据
|
|
62
|
+
- add_hero_section: 标题和描述要反映真实业务
|
|
63
|
+
- create_card_grid: 卡片内容必须是真实数据项
|
|
64
|
+
|
|
65
|
+
【验证要求】
|
|
66
|
+
=====================================
|
|
67
|
+
生成的每个HTML文件都必须包含:
|
|
68
|
+
1. 完整的数据列表(不得遗漏任何一项)
|
|
69
|
+
2. 准确的名称和地址信息
|
|
70
|
+
3. 正确的数据展示格式
|
|
71
|
+
|
|
72
|
+
记住:这是一个数据展示任务,不是创意写作任务!
|
|
73
|
+
"""
|
|
74
|
+
return enhanced
|
|
75
|
+
|
|
76
|
+
@staticmethod
|
|
77
|
+
def _analyze_data_type(context_data: str) -> str:
|
|
78
|
+
"""
|
|
79
|
+
分析数据类型
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
context_data: 上下文数据
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
数据类型标识
|
|
86
|
+
"""
|
|
87
|
+
lower_data = context_data.lower()
|
|
88
|
+
|
|
89
|
+
# 检测不同类型的数据
|
|
90
|
+
if "咖啡" in context_data or "coffee" in lower_data or "店" in context_data:
|
|
91
|
+
if "地址" in context_data or "address" in lower_data:
|
|
92
|
+
return "store_list"
|
|
93
|
+
|
|
94
|
+
if "产品" in context_data or "product" in lower_data:
|
|
95
|
+
return "product_list"
|
|
96
|
+
|
|
97
|
+
if "菜单" in context_data or "menu" in lower_data:
|
|
98
|
+
return "menu_list"
|
|
99
|
+
|
|
100
|
+
if "价格" in context_data or "price" in lower_data:
|
|
101
|
+
return "pricing_list"
|
|
102
|
+
|
|
103
|
+
if "联系" in context_data or "contact" in lower_data:
|
|
104
|
+
return "contact_info"
|
|
105
|
+
|
|
106
|
+
return "general_list"
|
|
107
|
+
|
|
108
|
+
@staticmethod
|
|
109
|
+
def _get_specific_instructions(data_type: str, context_data: str) -> str:
|
|
110
|
+
"""
|
|
111
|
+
根据数据类型生成特定指令
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
data_type: 数据类型
|
|
115
|
+
context_data: 上下文数据
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
特定的指令
|
|
119
|
+
"""
|
|
120
|
+
# 计算数据项数量
|
|
121
|
+
item_count = context_data.count('\n1.') + context_data.count('\n2.') + \
|
|
122
|
+
context_data.count('\n3.') + context_data.count('\n-')
|
|
123
|
+
|
|
124
|
+
if data_type == "store_list":
|
|
125
|
+
return f"""
|
|
126
|
+
【针对店铺列表的特定要求】
|
|
127
|
+
- 必须展示所有{item_count}个店铺
|
|
128
|
+
- 每个店铺必须包含:名称、地址
|
|
129
|
+
- 使用卡片布局,每行2-3个
|
|
130
|
+
- 可以添加地图链接按钮
|
|
131
|
+
- 可以按区域或品牌分组展示
|
|
132
|
+
"""
|
|
133
|
+
|
|
134
|
+
elif data_type == "product_list":
|
|
135
|
+
return f"""
|
|
136
|
+
【针对产品列表的特定要求】
|
|
137
|
+
- 必须展示所有产品信息
|
|
138
|
+
- 保持原始的产品名称和描述
|
|
139
|
+
- 使用产品卡片或展示网格
|
|
140
|
+
- 可以添加产品图片占位符
|
|
141
|
+
"""
|
|
142
|
+
|
|
143
|
+
elif data_type == "menu_list":
|
|
144
|
+
return f"""
|
|
145
|
+
【针对菜单的特定要求】
|
|
146
|
+
- 必须展示完整菜单
|
|
147
|
+
- 保持原始的菜品名称和价格
|
|
148
|
+
- 可以按类别分组
|
|
149
|
+
- 使用清晰的表格或列表格式
|
|
150
|
+
"""
|
|
151
|
+
|
|
152
|
+
else:
|
|
153
|
+
return f"""
|
|
154
|
+
【通用数据展示要求】
|
|
155
|
+
- 必须展示所有数据项(共约{item_count}项)
|
|
156
|
+
- 保持数据的原始格式
|
|
157
|
+
- 使用适合的布局展示
|
|
158
|
+
- 不得添加虚构内容
|
|
159
|
+
"""
|
|
160
|
+
|
|
161
|
+
@staticmethod
|
|
162
|
+
def validate_content_usage(generated_content: str, original_data: str) -> dict:
|
|
163
|
+
"""
|
|
164
|
+
验证生成的内容是否正确使用了原始数据
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
generated_content: 生成的内容
|
|
168
|
+
original_data: 原始数据
|
|
169
|
+
|
|
170
|
+
Returns:
|
|
171
|
+
验证结果
|
|
172
|
+
"""
|
|
173
|
+
# 提取原始数据中的关键项
|
|
174
|
+
key_items = []
|
|
175
|
+
lines = original_data.split('\n')
|
|
176
|
+
for line in lines:
|
|
177
|
+
line = line.strip()
|
|
178
|
+
# 提取店名或关键信息
|
|
179
|
+
if '. ' in line and line[0].isdigit():
|
|
180
|
+
item = line.split('. ', 1)[1] if '. ' in line else line
|
|
181
|
+
if '(' in item:
|
|
182
|
+
item = item.split('(')[0].strip()
|
|
183
|
+
key_items.append(item)
|
|
184
|
+
elif '- 地址:' in line:
|
|
185
|
+
address = line.replace('- 地址:', '').strip()
|
|
186
|
+
key_items.append(address)
|
|
187
|
+
|
|
188
|
+
# 检查每个关键项是否在生成的内容中
|
|
189
|
+
missing_items = []
|
|
190
|
+
found_items = []
|
|
191
|
+
|
|
192
|
+
for item in key_items:
|
|
193
|
+
if item in generated_content:
|
|
194
|
+
found_items.append(item)
|
|
195
|
+
else:
|
|
196
|
+
missing_items.append(item)
|
|
197
|
+
|
|
198
|
+
# 检测虚构内容的特征
|
|
199
|
+
fake_content_patterns = [
|
|
200
|
+
"转化率提升",
|
|
201
|
+
"品牌形象",
|
|
202
|
+
"¥9,999",
|
|
203
|
+
"¥29,999",
|
|
204
|
+
"¥59,999",
|
|
205
|
+
"起步套餐",
|
|
206
|
+
"专业套餐",
|
|
207
|
+
"旗舰套餐",
|
|
208
|
+
"Alex Chen",
|
|
209
|
+
"Liang Wu",
|
|
210
|
+
"Yvonne Zhao",
|
|
211
|
+
"设计质感",
|
|
212
|
+
"交付质量",
|
|
213
|
+
"Lorem ipsum",
|
|
214
|
+
"示例文本"
|
|
215
|
+
]
|
|
216
|
+
|
|
217
|
+
detected_fake = [pattern for pattern in fake_content_patterns
|
|
218
|
+
if pattern in generated_content]
|
|
219
|
+
|
|
220
|
+
return {
|
|
221
|
+
"valid": len(missing_items) == 0 and len(detected_fake) == 0,
|
|
222
|
+
"found_items": found_items,
|
|
223
|
+
"missing_items": missing_items,
|
|
224
|
+
"detected_fake_content": detected_fake,
|
|
225
|
+
"coverage_rate": len(found_items) / len(key_items) if key_items else 0,
|
|
226
|
+
"has_fake_content": len(detected_fake) > 0
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
# 导出便捷函数
|
|
231
|
+
def enhance_prompt_for_real_data(prompt: str, context: str = None) -> str:
|
|
232
|
+
"""增强提示词以使用真实数据"""
|
|
233
|
+
enhancer = PromptEnhancer()
|
|
234
|
+
return enhancer.enhance_for_real_data(prompt, context)
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def validate_data_usage(content: str, original: str) -> dict:
|
|
238
|
+
"""验证数据使用情况"""
|
|
239
|
+
enhancer = PromptEnhancer()
|
|
240
|
+
return enhancer.validate_content_usage(content, original)
|
|
@@ -33,13 +33,19 @@ from pathlib import Path
|
|
|
33
33
|
from htmlgen_mcp.agents.smart_web_agent import SmartWebAgent
|
|
34
34
|
from htmlgen_mcp.nas_storage import get_nas_storage
|
|
35
35
|
from htmlgen_mcp.nas_log_manager import get_nas_log_manager, ensure_job_log, log_progress, query_progress
|
|
36
|
+
from htmlgen_mcp.prompt_enhancer import enhance_prompt_for_real_data
|
|
36
37
|
from datetime import datetime
|
|
37
38
|
|
|
38
39
|
# 使用 NAS 作为默认存储路径
|
|
39
40
|
NAS_PATH = os.environ.get("NAS_STORAGE_PATH", "/app/mcp-servers/mcp-servers/html_agent")
|
|
41
|
+
# 项目根目录:优先使用 WEB_AGENT_PROJECT_ROOT 环境变量,否则使用 NAS_PATH/projects
|
|
40
42
|
DEFAULT_PROJECT_ROOT = os.path.abspath(
|
|
41
43
|
os.environ.get("WEB_AGENT_PROJECT_ROOT", f"{NAS_PATH}/projects")
|
|
42
44
|
)
|
|
45
|
+
# 是否自动生成项目子目录(可通过环境变量控制)
|
|
46
|
+
AUTO_CREATE_PROJECT_DIR = os.environ.get("AUTO_CREATE_PROJECT_DIR", "true").lower() == "true"
|
|
47
|
+
# 默认的文件上传URL(固定值)
|
|
48
|
+
DEFAULT_UPLOAD_URL = "https://www.mcpcn.cc/api/fileUploadAndDownload/uploadMcpFile"
|
|
43
49
|
DEFAULT_MODEL = os.environ.get("WEB_AGENT_MODEL", "qwen3-coder-plus-2025-09-23")
|
|
44
50
|
DEFAULT_BASE_URL = os.environ.get(
|
|
45
51
|
"OPENAI_BASE_URL", "https://dashscope.aliyuncs.com/compatible-mode/v1"
|
|
@@ -172,9 +178,47 @@ def _resolve_cached_context(context_id: Optional[str]) -> Optional[Dict[str, Any
|
|
|
172
178
|
return None
|
|
173
179
|
|
|
174
180
|
|
|
175
|
-
def _resolve_project_directory(project_root: Optional[str]) -> str:
|
|
176
|
-
|
|
177
|
-
|
|
181
|
+
def _resolve_project_directory(project_root: Optional[str], project_name: Optional[str] = None) -> str:
|
|
182
|
+
"""
|
|
183
|
+
解析项目目录路径
|
|
184
|
+
|
|
185
|
+
Args:
|
|
186
|
+
project_root: 项目根目录或完整路径
|
|
187
|
+
project_name: 项目名称(可选)
|
|
188
|
+
|
|
189
|
+
Returns:
|
|
190
|
+
完整的项目目录路径
|
|
191
|
+
"""
|
|
192
|
+
if project_root:
|
|
193
|
+
# 如果提供了 project_root
|
|
194
|
+
if os.path.isabs(project_root):
|
|
195
|
+
# 绝对路径:直接使用
|
|
196
|
+
abs_path = project_root
|
|
197
|
+
else:
|
|
198
|
+
# 相对路径:相对于默认根目录
|
|
199
|
+
# 如果 project_root 看起来像项目名(不含/),则作为子目录
|
|
200
|
+
if '/' not in project_root and '\\' not in project_root:
|
|
201
|
+
abs_path = os.path.join(DEFAULT_PROJECT_ROOT, project_root)
|
|
202
|
+
else:
|
|
203
|
+
# 包含路径分隔符,作为相对路径处理
|
|
204
|
+
abs_path = os.path.abspath(os.path.join(DEFAULT_PROJECT_ROOT, project_root))
|
|
205
|
+
else:
|
|
206
|
+
# 没有提供 project_root,使用默认根目录
|
|
207
|
+
base = DEFAULT_PROJECT_ROOT
|
|
208
|
+
|
|
209
|
+
# 如果提供了 project_name 且启用了自动创建子目录
|
|
210
|
+
if project_name and AUTO_CREATE_PROJECT_DIR:
|
|
211
|
+
# 清理项目名称,去除特殊字符
|
|
212
|
+
safe_name = "".join(c for c in project_name if c.isalnum() or c in (' ', '-', '_', '.'))
|
|
213
|
+
safe_name = safe_name.strip().replace(' ', '_')
|
|
214
|
+
if safe_name:
|
|
215
|
+
abs_path = os.path.join(base, safe_name)
|
|
216
|
+
else:
|
|
217
|
+
abs_path = base
|
|
218
|
+
else:
|
|
219
|
+
abs_path = base
|
|
220
|
+
|
|
221
|
+
# 创建目录
|
|
178
222
|
os.makedirs(abs_path, exist_ok=True)
|
|
179
223
|
return abs_path
|
|
180
224
|
|
|
@@ -402,8 +446,7 @@ def _execute_plan(
|
|
|
402
446
|
@mcp.tool()
|
|
403
447
|
async def execute_plan(
|
|
404
448
|
plan_id: str,
|
|
405
|
-
|
|
406
|
-
project_root: str,
|
|
449
|
+
project_root: Optional[str] = None,
|
|
407
450
|
# auto_plan: bool = False, # 已禁用,没有实际作用
|
|
408
451
|
# confirm_each_step: bool = False, # 后台执行模式下用户无法交互确认
|
|
409
452
|
# show_code: bool = False, # 后台执行时用户看不到输出
|
|
@@ -411,7 +454,7 @@ async def execute_plan(
|
|
|
411
454
|
save_output: bool = False,
|
|
412
455
|
progress_log: Optional[str] = None,
|
|
413
456
|
auto_upload: bool = False,
|
|
414
|
-
upload_url: str =
|
|
457
|
+
upload_url: Optional[str] = None,
|
|
415
458
|
) -> Dict[str, Any]:
|
|
416
459
|
"""执行网页构建计划,始终以后台模式运行。
|
|
417
460
|
|
|
@@ -441,9 +484,9 @@ async def execute_plan(
|
|
|
441
484
|
False: 仅构建,不上传
|
|
442
485
|
默认为 False
|
|
443
486
|
|
|
444
|
-
- upload_url: 文件上传API
|
|
487
|
+
- upload_url: 文件上传API地址(可选)
|
|
445
488
|
默认为 "https://www.mcpcn.cc/api/fileUploadAndDownload/uploadMcpFile"
|
|
446
|
-
只在 auto_upload=True
|
|
489
|
+
只在 auto_upload=True 时生效,一般不需要修改
|
|
447
490
|
|
|
448
491
|
执行流程:
|
|
449
492
|
- 任务始终在后台异步执行,立即返回 job_id 和 progress_log 路径
|
|
@@ -453,7 +496,40 @@ async def execute_plan(
|
|
|
453
496
|
- 🎯 新增:auto_upload=True时,构建完成(100%)后自动上传并返回访问URL
|
|
454
497
|
"""
|
|
455
498
|
try:
|
|
456
|
-
|
|
499
|
+
# 如果没有提供project_root,尝试从缓存中获取
|
|
500
|
+
if not project_root:
|
|
501
|
+
cached_by_id = _PLAN_CACHE_BY_ID.get(plan_id)
|
|
502
|
+
if cached_by_id and cached_by_id.get("project_directory"):
|
|
503
|
+
project_root = cached_by_id["project_directory"]
|
|
504
|
+
else:
|
|
505
|
+
# 尝试从文件中读取
|
|
506
|
+
possible_paths = [
|
|
507
|
+
PLAN_CACHE_DIR / f"{plan_id}.json",
|
|
508
|
+
PLAN_CACHE_DIR / f"simple_site_plan_{plan_id}.json",
|
|
509
|
+
]
|
|
510
|
+
for path in possible_paths:
|
|
511
|
+
if path.exists():
|
|
512
|
+
try:
|
|
513
|
+
plan_data = json.loads(path.read_text(encoding="utf-8"))
|
|
514
|
+
project_root = plan_data.get("project_directory")
|
|
515
|
+
if project_root:
|
|
516
|
+
break
|
|
517
|
+
except Exception:
|
|
518
|
+
pass
|
|
519
|
+
|
|
520
|
+
if not project_root:
|
|
521
|
+
# 使用默认根目录,但不添加子目录
|
|
522
|
+
project_root = None
|
|
523
|
+
|
|
524
|
+
# 从计划中获取项目名称(如果有)
|
|
525
|
+
project_name = None
|
|
526
|
+
if plan_id:
|
|
527
|
+
cached_plan = _PLAN_CACHE_BY_ID.get(plan_id)
|
|
528
|
+
if cached_plan:
|
|
529
|
+
# 尝试从缓存中获取项目名称
|
|
530
|
+
project_name = cached_plan.get("site_title") or cached_plan.get("project_name")
|
|
531
|
+
|
|
532
|
+
project_dir = _resolve_project_directory(project_root, project_name)
|
|
457
533
|
|
|
458
534
|
# 移除 auto_plan 检查,因为参数已被移除
|
|
459
535
|
|
|
@@ -562,6 +638,9 @@ async def execute_plan(
|
|
|
562
638
|
|
|
563
639
|
_persist_job_state(job_id)
|
|
564
640
|
|
|
641
|
+
# 使用默认URL如果没有提供
|
|
642
|
+
effective_upload_url = upload_url or DEFAULT_UPLOAD_URL
|
|
643
|
+
|
|
565
644
|
asyncio.create_task(
|
|
566
645
|
_run_execution_job(
|
|
567
646
|
job_id,
|
|
@@ -569,7 +648,7 @@ async def execute_plan(
|
|
|
569
648
|
plan_dict,
|
|
570
649
|
progress_log_path=progress_log_path,
|
|
571
650
|
auto_upload=auto_upload,
|
|
572
|
-
upload_url=
|
|
651
|
+
upload_url=effective_upload_url,
|
|
573
652
|
)
|
|
574
653
|
)
|
|
575
654
|
|
|
@@ -608,7 +687,7 @@ async def _run_execution_job(
|
|
|
608
687
|
*,
|
|
609
688
|
progress_log_path: Optional[str],
|
|
610
689
|
auto_upload: bool = False,
|
|
611
|
-
upload_url: str =
|
|
690
|
+
upload_url: str = None,
|
|
612
691
|
) -> None:
|
|
613
692
|
job_info = _JOB_REGISTRY.get(job_id)
|
|
614
693
|
if not job_info:
|
|
@@ -633,9 +712,12 @@ async def _run_execution_job(
|
|
|
633
712
|
job_info["upload_status"] = "uploading"
|
|
634
713
|
_persist_job_state(job_id)
|
|
635
714
|
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
715
|
+
# 只在不是默认值时传递upload_url
|
|
716
|
+
upload_params = {"folder_path": job_info["project_directory"]}
|
|
717
|
+
if upload_url and upload_url != DEFAULT_UPLOAD_URL:
|
|
718
|
+
upload_params["upload_url"] = upload_url
|
|
719
|
+
|
|
720
|
+
upload_result = await upload_project_to_mcp_server(**upload_params)
|
|
639
721
|
|
|
640
722
|
# 记录上传结果
|
|
641
723
|
job_info["upload_result"] = upload_result
|
|
@@ -734,18 +816,9 @@ async def create_simple_site(
|
|
|
734
816
|
# 使用指定模型或默认模型
|
|
735
817
|
used_model = model or DEFAULT_MODEL
|
|
736
818
|
|
|
737
|
-
#
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
project_directory = os.path.join(DEFAULT_PROJECT_ROOT, project_root)
|
|
741
|
-
else:
|
|
742
|
-
project_directory = project_root
|
|
743
|
-
else:
|
|
744
|
-
# 使用站点标题作为目录名
|
|
745
|
-
safe_title = "".join(
|
|
746
|
-
c if c.isalnum() or c in "._-" else "_" for c in site_title
|
|
747
|
-
)
|
|
748
|
-
project_directory = os.path.join(DEFAULT_PROJECT_ROOT, safe_title)
|
|
819
|
+
# 使用新的路径解析逻辑
|
|
820
|
+
# 如果没有提供 project_root,使用 site_title 作为项目名
|
|
821
|
+
project_directory = _resolve_project_directory(project_root, site_title)
|
|
749
822
|
|
|
750
823
|
# 处理上下文
|
|
751
824
|
context_data = ""
|
|
@@ -776,42 +849,45 @@ async def create_simple_site(
|
|
|
776
849
|
force_single_page=True,
|
|
777
850
|
)
|
|
778
851
|
|
|
779
|
-
#
|
|
780
|
-
|
|
852
|
+
# 如果有上下文内容,将其整合到描述中
|
|
853
|
+
enhanced_description = description
|
|
781
854
|
if context_data:
|
|
782
|
-
|
|
855
|
+
enhanced_description = f"""{description}
|
|
783
856
|
|
|
784
|
-
|
|
857
|
+
【必须使用的具体数据内容】:
|
|
785
858
|
{context_data}
|
|
786
859
|
|
|
787
|
-
|
|
860
|
+
【重要提示】:上述数据是真实的业务数据,必须完整准确地展示在网页中,不要生成虚构的示例内容。"""
|
|
788
861
|
|
|
789
|
-
|
|
862
|
+
# 构建改进的提示词,强调使用真实数据
|
|
863
|
+
simple_prompt = f"""请为以下需求创建一个网站,并严格使用提供的真实数据:
|
|
790
864
|
|
|
791
|
-
|
|
792
|
-
|
|
865
|
+
**网站标题**: {site_title}
|
|
866
|
+
**具体需求和数据**:
|
|
867
|
+
{enhanced_description}
|
|
793
868
|
|
|
794
|
-
|
|
795
|
-
1.
|
|
796
|
-
2.
|
|
797
|
-
3.
|
|
798
|
-
4.
|
|
799
|
-
5.
|
|
800
|
-
6. 智能图片集成,根据内容类型匹配合适主题
|
|
801
|
-
7. 如果有上下文内容,请充分利用这些信息来丰富网页内容
|
|
869
|
+
**执行要求**:
|
|
870
|
+
1. 【数据要求】如果提供了具体数据(如店铺列表、产品信息等),必须100%使用这些真实数据,不要创建虚构内容
|
|
871
|
+
2. 【内容展示】将所有提供的数据项完整展示,使用合适的布局(如卡片、列表、表格等)
|
|
872
|
+
3. 【样式设计】保持简洁美观,使用响应式设计
|
|
873
|
+
4. 【代码限制】CSS不超过300行,避免复杂特效
|
|
874
|
+
5. 【功能实现】包含基础交互功能(导航、滚动等)
|
|
802
875
|
|
|
803
|
-
|
|
804
|
-
|
|
876
|
+
**特别强调**:
|
|
877
|
+
- 当创建HTML内容时,必须使用上面提供的真实数据
|
|
878
|
+
- 不要生成"示例客户评价"、"虚拟定价方案"等占位内容
|
|
879
|
+
- 如果是咖啡馆列表,就展示真实的咖啡馆名称和地址
|
|
880
|
+
- 如果是产品信息,就展示真实的产品数据
|
|
881
|
+
- 每个create_html_file或add_content_section工具调用时,都要包含真实数据
|
|
805
882
|
|
|
806
|
-
|
|
807
|
-
- 每个步骤都要具体可执行
|
|
808
|
-
- 优先使用简单模板函数而非复杂模板
|
|
809
|
-
- 注重实用性和美观性的平衡
|
|
810
|
-
- 充分利用提供的上下文信息来生成个性化内容
|
|
883
|
+
请生成3-6个步骤的执行计划,确保每个步骤都能正确使用提供的数据。
|
|
811
884
|
"""
|
|
812
885
|
|
|
813
886
|
# 生成简化计划(仅规划,不执行)
|
|
814
|
-
|
|
887
|
+
# 传递强化后的提示词,确保AI使用真实数据
|
|
888
|
+
# 使用提示词增强器进一步强化
|
|
889
|
+
final_prompt = enhance_prompt_for_real_data(simple_prompt, context_data)
|
|
890
|
+
plan = agent._get_execution_plan(final_prompt)
|
|
815
891
|
|
|
816
892
|
# 在计划中标记为简单网站类型和相关信息
|
|
817
893
|
plan["site_type"] = "simple"
|
|
@@ -826,9 +902,8 @@ async def create_simple_site(
|
|
|
826
902
|
plan_id = str(uuid.uuid4())
|
|
827
903
|
|
|
828
904
|
# 构建完整的源描述(包含上下文)
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
source_description = f"{description}\n\n【附加内容】\n{context_data}"
|
|
905
|
+
# 使用enhanced_description以确保数据被传递
|
|
906
|
+
source_description = enhanced_description
|
|
832
907
|
|
|
833
908
|
# 在计划中添加源描述字段
|
|
834
909
|
plan["__source_description"] = source_description
|
|
@@ -1072,13 +1147,15 @@ async def get_progress(
|
|
|
1072
1147
|
@mcp.tool()
|
|
1073
1148
|
async def upload_project_to_mcp_server(
|
|
1074
1149
|
folder_path: str,
|
|
1075
|
-
upload_url: str =
|
|
1150
|
+
upload_url: Optional[str] = None,
|
|
1076
1151
|
) -> Dict[str, Any]:
|
|
1077
1152
|
"""将项目文件夹打包成ZIP并上传到MCP服务器。
|
|
1078
1153
|
|
|
1079
1154
|
参数说明:
|
|
1080
1155
|
- folder_path: 项目文件夹的绝对路径
|
|
1081
|
-
- upload_url: 上传API
|
|
1156
|
+
- upload_url: 上传API地址(可选)
|
|
1157
|
+
默认为 "https://www.mcpcn.cc/api/fileUploadAndDownload/uploadMcpFile"
|
|
1158
|
+
一般不需要修改
|
|
1082
1159
|
|
|
1083
1160
|
返回值:
|
|
1084
1161
|
- status: 上传状态 ("success" 或 "error")
|
|
@@ -1087,6 +1164,9 @@ async def upload_project_to_mcp_server(
|
|
|
1087
1164
|
- message: 状态信息
|
|
1088
1165
|
"""
|
|
1089
1166
|
try:
|
|
1167
|
+
# 使用默认URL如果没有提供
|
|
1168
|
+
effective_upload_url = upload_url or DEFAULT_UPLOAD_URL
|
|
1169
|
+
|
|
1090
1170
|
# 验证文件夹路径
|
|
1091
1171
|
if not os.path.exists(folder_path):
|
|
1092
1172
|
return {"status": "error", "message": f"项目文件夹不存在: {folder_path}"}
|
|
@@ -1126,7 +1206,7 @@ async def upload_project_to_mcp_server(
|
|
|
1126
1206
|
"file", f, filename=zip_filename, content_type="application/zip"
|
|
1127
1207
|
)
|
|
1128
1208
|
|
|
1129
|
-
async with session.post(
|
|
1209
|
+
async with session.post(effective_upload_url, data=data) as response:
|
|
1130
1210
|
response_text = await response.text()
|
|
1131
1211
|
|
|
1132
1212
|
if response.status != 200:
|
|
@@ -2,11 +2,13 @@ README.md
|
|
|
2
2
|
pyproject.toml
|
|
3
3
|
src/htmlgen_mcp/__init__.py
|
|
4
4
|
src/htmlgen_mcp/config.py
|
|
5
|
+
src/htmlgen_mcp/context_aware_executor.py
|
|
5
6
|
src/htmlgen_mcp/improved_progress.py
|
|
6
7
|
src/htmlgen_mcp/nas_log_manager.py
|
|
7
8
|
src/htmlgen_mcp/nas_storage.py
|
|
8
9
|
src/htmlgen_mcp/progress_tools.py
|
|
9
10
|
src/htmlgen_mcp/progress_tracker.py
|
|
11
|
+
src/htmlgen_mcp/prompt_enhancer.py
|
|
10
12
|
src/htmlgen_mcp/sse_optimizations.py
|
|
11
13
|
src/htmlgen_mcp/web_agent_server.py
|
|
12
14
|
src/htmlgen_mcp.egg-info/PKG-INFO
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp/agents/web_tools/html_templates_improved.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{htmlgen_mcp-0.3.5 → htmlgen_mcp-0.3.7}/src/htmlgen_mcp/agents/web_tools/simple_templates.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|