mirror of
https://github.com/val1813/kwcode.git
synced 2026-09-06 08:01:48 +08:00
P1: KWCODE.md规则注入、/plan风险评估、Checkpoint快照、DocReader P2: 模型能力自适应、飞轮通知、价值量化仪表盘 搜索: 四级提取管道、并行搜索+BM25重排、意图感知、ChatExpert门控 UI: spinner动画、结果摘要、静默日志、重影大字Header 新增: kwcode setup-search 一键安装SearXNG 测试: 282/282 PASS (含17个E2E真实模型测试) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
144 lines
4.2 KiB
Python
144 lines
4.2 KiB
Python
"""
|
||
KWCODE.md project rules loader.
|
||
Loads user-defined rules from KWCODE.md, parses by section tags,
|
||
injects relevant sections into expert prompts.
|
||
P1-RED-1: Injected tokens must not exceed 15% of model context window.
|
||
"""
|
||
|
||
import logging
|
||
from pathlib import Path
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
# Supported section tags
|
||
_SECTION_KEYS = ("all", "bugfix", "codegen", "test", "refactor", "doc", "office")
|
||
|
||
# Map expert_type to section key
|
||
_TYPE_TO_SECTION = {
|
||
"locator_repair": "bugfix",
|
||
"codegen": "codegen",
|
||
"refactor": "refactor",
|
||
"doc": "doc",
|
||
"test": "test",
|
||
"office": "office",
|
||
}
|
||
|
||
|
||
def load_kwcode_md(project_root: str) -> dict[str, str]:
|
||
"""
|
||
Load KWCODE.md, parse by [section] tags.
|
||
Returns {"all": "...", "bugfix": "...", ...}.
|
||
Falls back to ~/.kwcode/KWCODE.md if not found in project root.
|
||
Returns empty dict if no file found (silent).
|
||
"""
|
||
path = Path(project_root) / "KWCODE.md"
|
||
if not path.exists():
|
||
path = Path.home() / ".kwcode" / "KWCODE.md"
|
||
if not path.exists():
|
||
return {}
|
||
|
||
try:
|
||
content = path.read_text(encoding="utf-8", errors="ignore")
|
||
except Exception as e:
|
||
logger.debug("[kwcode_md] Failed to read %s: %s", path, e)
|
||
return {}
|
||
|
||
sections: dict[str, list[str]] = {k: [] for k in _SECTION_KEYS}
|
||
current = "all"
|
||
|
||
for line in content.splitlines():
|
||
stripped = line.strip()
|
||
# Detect section tag: ## [bugfix] or ## [all]
|
||
matched = False
|
||
for key in _SECTION_KEYS:
|
||
if stripped.startswith(f"## [{key}]"):
|
||
current = key
|
||
matched = True
|
||
break
|
||
if not matched:
|
||
# Skip the file title line
|
||
if not stripped.startswith("# KWCODE.md"):
|
||
sections[current].append(line)
|
||
|
||
return {k: "\n".join(v).strip() for k, v in sections.items() if v and "\n".join(v).strip()}
|
||
|
||
|
||
def build_kwcode_system(expert_type: str, kwcode_sections: dict[str, str]) -> str:
|
||
"""
|
||
Build system prompt injection from KWCODE.md sections.
|
||
Always injects [all], plus the section matching expert_type.
|
||
P1-RED-1: Total tokens capped at ~15% of 8K window (1200 tokens ≈ 4800 chars).
|
||
"""
|
||
if not kwcode_sections:
|
||
return ""
|
||
|
||
parts = []
|
||
|
||
# Always inject [all]
|
||
if "all" in kwcode_sections:
|
||
parts.append(f"## 项目规则\n{kwcode_sections['all']}")
|
||
|
||
# Inject task-type-specific section
|
||
section_key = _TYPE_TO_SECTION.get(expert_type)
|
||
if section_key and section_key in kwcode_sections:
|
||
parts.append(f"## {expert_type}规则\n{kwcode_sections[section_key]}")
|
||
|
||
if not parts:
|
||
return ""
|
||
|
||
injected = "\n\n".join(parts)
|
||
|
||
# P1-RED-1: token cap (rough estimate: 1 token ≈ 4 chars)
|
||
MAX_CHARS = 4800 # ~1200 tokens, 15% of 8K
|
||
if len(injected) > MAX_CHARS:
|
||
injected = injected[:MAX_CHARS] + "\n...(已截断)"
|
||
|
||
return injected
|
||
|
||
|
||
def generate_kwcode_template(project_root: str) -> str:
|
||
"""
|
||
Generate KWCODE.md template in project root.
|
||
Auto-detects test framework. Returns status message.
|
||
"""
|
||
kwcode_path = Path(project_root) / "KWCODE.md"
|
||
if kwcode_path.exists():
|
||
return "KWCODE.md已存在,跳过"
|
||
|
||
# Auto-detect test command
|
||
test_cmd = "pytest tests/ -v"
|
||
if (Path(project_root) / "package.json").exists():
|
||
test_cmd = "npm test"
|
||
elif (Path(project_root) / "go.mod").exists():
|
||
test_cmd = "go test ./..."
|
||
elif (Path(project_root) / "Cargo.toml").exists():
|
||
test_cmd = "cargo test"
|
||
|
||
template = f"""# KWCODE.md
|
||
# 项目规则文件,KWCode启动时自动加载
|
||
# 编辑此文件来告诉KWCode你的项目规范
|
||
|
||
## [all] 通用规则
|
||
- 运行测试:{test_cmd}
|
||
- 在这里写你的项目约定,比如:
|
||
- 认证逻辑在:src/auth/
|
||
- 数据库操作在:src/db/
|
||
|
||
## [bugfix] Bug修复规则
|
||
- 修复前先理解错误原因
|
||
|
||
## [codegen] 代码生成规则
|
||
- 在这里写新代码的规范
|
||
|
||
## [test] 测试规则
|
||
- 使用pytest
|
||
|
||
## [refactor] 重构规则
|
||
- 每次只做一种重构
|
||
"""
|
||
try:
|
||
kwcode_path.write_text(template, encoding="utf-8")
|
||
return f"[green]✓[/green] 已生成 KWCODE.md,请编辑填写你的项目规范"
|
||
except Exception as e:
|
||
return f"[red]生成失败:{e}[/red]"
|