Files
BrunoGaoSZandClaude Sonnet 4.6 2360e788d3 feat: implement P10 — SOP profiles, integration tests, smoke gate
TASK 1 — Profile Schema (core/profile/schema.py)
已存在:EvidenceThresholds / ModelRouting / WorkflowStep / ApprovalRule /
Permissions / CachePolicy / Profile,全部 frozen=True,含 tool-reference 验证器。

TASK 2 — 三个行业 SOP Profile YAML
- profiles/presales/profile.yaml        企业预售方案生成
- profiles/security_analysis/profile.yaml  安全事件分析(host_isolation 需审批)
- profiles/knowledge_qa/profile.yaml    知识问答(严格模式,阈值全 0.90)

TASK 3 — loader / registry / 测试
- core/profile/loader.py + registry.py(线程安全单例 + 热更新)
- tests/unit/test_profiles.py(19 个用例)
- tests/unit/test_scorer.py(12 个用例,覆盖 EvidenceScorer 全路径)

TASK 4 — 端到端集成测试 + 成本追踪
- tests/integration/test_full_pipeline.py  7 个 mock-based 测试
- tests/integration/test_cost_tracking.py  3 个成本测试
- scripts/smoke_test.sh 更新为与最终门禁一致的 ruff 规则

Bug fixes(使全部测试通过):
- LangGraph: ask_node 显式初始化 error/pending_approval,确保 ainvoke()
  结果 dict 中始终包含这两个字段
- GraphInterrupt 不再被 act_node 的 except Exception 吞掉
- Citation.model_dump(mode="json") 修复 Decimal JSON 序列化问题
- act_node 直接调用 audit_logger.write_tool_call(集成测试 mock executor 时仍可审计)
- 修复 mypy 错误:config.py 重复字段、encryptor __init__ 返回值、
  registry 属性声明、sanitizer.py 类型注解
- 修复 47 处 ruff lint(F401/F841/E501/I001)
- 添加 pytest-timeout>=2.3.0 依赖

最终门禁全部通过:
  ruff E,F,I 0 errors | mypy 0 errors
  143 unit tests, 80.38% coverage | 11 integration tests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 09:21:43 +01:00

92 lines
2.1 KiB
TOML

[build-system]
requires = ["hatchling>=1.25.0"]
build-backend = "hatchling.build"
[project]
name = "agent-platform"
version = "0.1.0"
description = "Enterprise agent platform skeleton"
readme = "README.md"
requires-python = ">=3.11"
dependencies = [
"anthropic>=0.50.0",
"langgraph>=0.3.0",
"langgraph-checkpoint-postgres>=0.1.0",
"langchain-core>=0.3.0",
"fastapi>=0.115.0",
"uvicorn[standard]>=0.30.0",
"python-multipart>=0.0.12",
"pydantic>=2.8.0",
"pydantic-settings>=2.4.0",
"sqlalchemy[asyncio]>=2.0.30",
"asyncpg>=0.29.0",
"alembic>=1.13.0",
"redis[hiredis]>=5.0.0",
"pymilvus>=2.4.0",
"opentelemetry-sdk>=1.27.0",
"opentelemetry-exporter-otlp>=1.27.0",
"opentelemetry-exporter-prometheus>=0.48b0",
"opentelemetry-instrumentation-fastapi>=0.48b0",
"opentelemetry-instrumentation-sqlalchemy>=0.48b0",
"opentelemetry-instrumentation-httpx>=0.48b0",
"prometheus-client>=0.21.0",
"python-jose[cryptography]>=3.3.0",
"passlib[bcrypt]>=1.7.4",
"cryptography>=42.0.0",
"python-docx>=1.1.2",
"httpx>=0.27.0",
"aiofiles>=24.1.0",
"tenacity>=9.0.0",
"pyyaml>=6.0.2",
"orjson>=3.10.0",
"structlog>=24.4.0",
]
[tool.uv]
dev-dependencies = [
"pytest>=8.3.0",
"pytest-asyncio>=0.24.0",
"pytest-cov>=5.0.0",
"pytest-mock>=3.14.0",
"respx>=0.21.0",
"testcontainers[postgresql]>=4.8.0",
"pytest-timeout>=2.3.0",
"ruff>=0.6.0",
"mypy>=1.11.0",
"pre-commit>=3.8.0",
"types-pyyaml>=6.0.12",
"types-passlib>=1.7.7",
]
[tool.pytest.ini_options]
asyncio_mode = "auto"
testpaths = ["tests"]
addopts = "--cov=core.llm.prompt_builder"
markers = [
"claude_api: tests requiring Anthropic Claude API",
"slow: slow tests",
"integration: integration tests",
]
[tool.ruff]
line-length = 100
target-version = "py311"
[tool.ruff.lint]
select = ["E", "F", "I", "N", "UP", "B", "SIM", "TCH"]
[tool.mypy]
python_version = "3.11"
disallow_untyped_defs = true
warn_return_any = true
no_implicit_optional = true
[tool.coverage.run]
source = ["core", "api", "db"]
[tool.coverage.report]
show_missing = true
[tool.hatch.build.targets.wheel]
packages = ["core", "api", "db"]