Skip to content

Commit e9c66c2

Browse files
Cherry-pick upstream PR fixes and tune smoke test params
- Editor: add `content` param to `create_file` (inspired by PR FoundationAgents#1921) - ToT: replace eval() with json.loads() for security (from PR FoundationAgents#1946) - run_optizap: reduce investment to $1 / 5 rounds for cheap smoke tests, add ProductManager patch and stronger tone requirements Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 9d28bf2 commit e9c66c2

3 files changed

Lines changed: 22 additions & 7 deletions

File tree

metagpt/strategy/tot.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from __future__ import annotations
66

77
import asyncio
8+
import json
89
from typing import Any, List, Optional
910

1011
from pydantic import BaseModel, ConfigDict, Field
@@ -63,7 +64,11 @@ async def generate_thoughts(self, current_state="", current_node=None) -> List[T
6364
)
6465
rsp = await self.llm.aask(msg=state_prompt + "\n" + OUTPUT_FORMAT)
6566
thoughts = CodeParser.parse_code(text=rsp)
66-
thoughts = eval(thoughts)
67+
try:
68+
thoughts = json.loads(thoughts)
69+
except json.JSONDecodeError:
70+
logger.warning(f"Failed to parse thoughts as JSON, attempting eval fallback: {thoughts[:100]}")
71+
thoughts = eval(thoughts) # noqa: S307 - fallback for non-standard LLM output
6772
# fixme 避免不跟随,生成过多nodes
6873
# valid_thoughts = [_node for idx, _node in enumerate(thoughts) if idx < self.n_generate_sample]
6974
return self.thought_tree.update_node(thoughts, current_node=current_node)

metagpt/tools/libs/editor.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -354,17 +354,18 @@ def scroll_up(self) -> str:
354354
output += self._print_window(self.current_file, self.current_line, self.window)
355355
return output
356356

357-
async def create_file(self, path: str) -> str:
358-
"""Creates and opens a new file with the given name.
357+
async def create_file(self, path: str, content: str = "") -> str:
358+
"""Creates and opens a new file with the given name and optional content.
359359
360360
Args:
361361
path: str: The name of the file to create. If the parent directory does not exist, it will be created.
362+
content: str: Optional initial content for the file. Defaults to empty.
362363
"""
363364
path = self._try_fix_path(path)
364365

365366
if path.exists():
366367
raise FileExistsError(f"File '{path}' already exists.")
367-
await awrite(path, "\n")
368+
await awrite(path, content if content else "\n")
368369

369370
self.open_file(path)
370371
return f"[File {path} created.]"

run_optizap.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ def auto_human_input(prompt: str = "") -> str:
2424
from metagpt.logs import set_human_input_func
2525
set_human_input_func(auto_human_input)
2626

27+
# Prevent ProductManager from registering WritePRD.run as a tool command.
28+
# In RoleZero mode, WritePRD writes to MetaGPT's internal workspace path,
29+
# not to our custom OUTPUT_DIR. Without it, Alice uses Editor.write with
30+
# the explicit absolute paths from the instruction — same as David.
31+
from metagpt.roles import ProductManager
32+
ProductManager._update_tool_execution = lambda self: None
33+
2734
from metagpt.software_company import generate_repo
2835

2936
IDEA = f"""
@@ -48,7 +55,8 @@ def auto_human_input(prompt: str = "") -> str:
4855
## BUSINESS REQUIREMENTS
4956
5057
The bot handles pre-service triage: understanding what the customer needs, collecting required information, and either resolving their query directly or handing off to a human specialist with full context.
51-
The bot answers should sound natural and hence it should NOT use fixed templates. It should handle the 7 customer needs below but soon more needs will arise.
58+
HARD REQUIREMENT FROM PO: The bot MUST sound like a real human, NEVER like a bot. No robotic templates, no "Dear customer", no numbered menus. Responses must feel like texting a friendly store employee. This is a non-negotiable UX requirement.
59+
The bot should handle the 7 customer needs below but soon more needs will arise.
5260
5361
### Customer Needs (7 observed patterns)
5462
@@ -77,6 +85,7 @@ def auto_human_input(prompt: str = "") -> str:
7785
- Language: All user-facing text in Brazilian Portuguese
7886
- LLM providers: OpenAI (gpt-4.1, gpt-4.1-mini), Google (Gemini Flash), Groq — can use different models for different tasks
7987
- Latency: Sub-10 second end-to-end response time (WhatsApp UX constraint)
88+
- Tone: ALL bot responses MUST sound natural and human — like a friendly store employee texting back. NEVER use robotic templates, canned greetings ("Dear customer"), numbered option menus, or formulaic patterns. The architecture must ensure LLM-generated free-form responses for every interaction, not template-based routing.
8089
8190
### Required Outputs (DOCUMENTS ONLY — NO CODE)
8291
1. PRD (product requirements document)
@@ -92,8 +101,8 @@ def auto_human_input(prompt: str = "") -> str:
92101

93102
project_path = generate_repo(
94103
idea=IDEA,
95-
investment=10.0,
96-
n_round=20,
104+
investment=1.0,
105+
n_round=5,
97106
code_review=False,
98107
run_tests=False,
99108
implement=False,

0 commit comments

Comments
 (0)