fix: delete agent 500 error + dynamic personality + deployment guide

- Fix delete agent 500: clean up FK records (agent_llm_logs, permissions,
  schedules, executions, team_members) and unbind goals/tasks before delete
- Remove hardcoded personality templates in Android, replace with dynamic
  system prompt generation from name + description
- Set promptSectionsEnabled=false to bypass PromptComposer for personality
- Add Tencent Cloud Linux deployment guide (Docker Compose)
- Accumulated backend service updates, frontend UI fixes, Android app changes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-29 01:17:21 +08:00
parent 86b98865e3
commit beff3fac8d
1084 changed files with 117315 additions and 1281 deletions

View File

@@ -263,8 +263,8 @@ class TestToolRegistryExecute:
@pytest.mark.unit
@pytest.mark.asyncio
async def test_execute_builtin(self, registry):
def hello(**kwargs):
return f"Hello, {kwargs.get('name', 'world')}!"
def hello(name="world"):
return f"Hello, {name}!"
registry.register_builtin_tool("hello", hello, {"function": {"name": "hello"}})
result = await registry.execute_tool("hello", {"name": "Test"})
@@ -291,3 +291,98 @@ class TestToolRegistryExecute:
registry._custom_tool_configs["wf"] = config
result = await registry.execute_tool("wf", {})
assert "暂不支持" in result
class TestToolRegistryParameterFiltering:
"""工具参数过滤测试 —— LLM 生成错误参数名 → 过滤 → 正常执行"""
@pytest.mark.unit
@pytest.mark.asyncio
async def test_unknown_params_filtered(self, registry):
"""未知参数被过滤,工具正常执行"""
def greet(name="world"):
return f"Hello, {name}!"
registry.register_builtin_tool("greet", greet, {"function": {"name": "greet"}})
# LLM 生成了未知参数 extra_field
result = await registry._run_function(greet, "greet", {
"name": "Test", "extra_field": "should_be_filtered"
})
assert "Hello, Test!" in result
@pytest.mark.unit
@pytest.mark.asyncio
async def test_missing_params_use_defaults(self, registry):
"""缺少参数时使用函数默认值"""
def greet(name="world"):
return f"Hello, {name}!"
registry.register_builtin_tool("greet", greet, {"function": {"name": "greet"}})
result = await registry._run_function(greet, "greet", {})
assert "Hello, world!" in result
@pytest.mark.unit
@pytest.mark.asyncio
async def test_no_valid_params_does_not_crash(self, registry):
"""全部参数都无效时不崩溃"""
def greet(name="world"):
return f"Hello, {name}!"
registry.register_builtin_tool("greet", greet, {"function": {"name": "greet"}})
# 所有参数都不匹配
result = await registry._run_function(greet, "greet", {
"bad_param_1": 1, "bad_param_2": 2
})
assert "Hello, world!" in result
@pytest.mark.unit
@pytest.mark.asyncio
async def test_mixed_valid_and_invalid_params(self, registry):
"""混合有效/无效参数时只使用有效参数"""
def calc(x=0, y=0):
return str(x + y)
registry.register_builtin_tool("calc", calc, {"function": {"name": "calc"}})
result = await registry._run_function(calc, "calc", {
"x": 3, "y": 4, "z": 100, "unused": "ignored"
})
assert "7" in result
@pytest.mark.unit
@pytest.mark.asyncio
async def test_type_coercion_handled_gracefully(self, registry):
"""类型不匹配时使用 Python 默认行为"""
def add(x=0, y=0):
return str(x + y)
registry.register_builtin_tool("add", add, {"function": {"name": "add"}})
# 字符串参数可能导致 TypeError但不应崩溃
result = await registry._run_function(add, "add", {
"x": "hello", "y": "world"
})
# 要么成功(字符串拼接),要么失败但不崩溃
assert isinstance(result, str)
@pytest.mark.unit
@pytest.mark.asyncio
async def test_empty_args_dict(self, registry):
"""空参数字典正常执行"""
def status():
return "ok"
registry.register_builtin_tool("status", status, {"function": {"name": "status"}})
result = await registry._run_function(status, "status", {})
assert "ok" in result
@pytest.mark.unit
@pytest.mark.asyncio
async def test_extra_positional_not_in_sig(self, registry):
"""参数名不在函数签名中时被过滤"""
def read_file(path=""):
return f"read: {path}"
registry.register_builtin_tool("read_file", read_file, {"function": {"name": "read_file"}})
result = await registry._run_function(read_file, "read_file", {
"path": "/data.txt", "encoding": "utf-8", "mode": "r"
})
assert "read: /data.txt" in result