feat: initial commit

This commit is contained in:
2026-06-23 20:29:02 +08:00
commit ea8f6066c4
217 changed files with 60754 additions and 0 deletions
+9
View File
@@ -0,0 +1,9 @@
# AI IDE Configurators
ONW 5.0 组件:Cursor/Windsurf AI IDE 直接挂载适配器
本目录包含与主流 AI IDE 集成的适配器,实现:
- 项目上下文自动注入
- 代码生成规则同步
- RAG 检索结果直接挂载
- Genesis Contract IDE 层强制执行
@@ -0,0 +1,98 @@
"""
Cursor IDE Adapter
NovelMaster Core Engine - Configurators
为 Cursor IDE 生成 .cursorrules 和项目配置
"""
from pathlib import Path
from typing import Dict, Any, Optional
import json
def generate_cursorrules_content(project_config: Dict[str, Any]) -> str:
"""生成 .cursorrules 文件内容"""
genesis = project_config.get("genesis_contract", {})
rules = f"""# NovelMaster Cursor Rules
## 项目概览
- 项目名称: {project_config.get("project_name", "未命名")}
- 类型: {project_config.get("genre", "网文")}
- 目标字数: {project_config.get("target_word_count", "未知")}
## 核心设定 (Genesis Contract)
### 核心欲望
{_format_dict(genesis.get("core_desire", {}))}
### 伦理沙盒
{_format_dict(genesis.get("ethical_inversion", {}))}
### 奇观日常化
{_format_dict(genesis.get("core_spectacle", {}))}
## 写作规范
- 使用中文思维写作
- 章节字数: 2000-2500 字
- 优先使用第三人称
- 爽点密度: 每1000字至少1个情感释放点
- 追读力 (Reading Power): 监控 Hook/Cool-point 平衡
## 状态管理
- 数据目录: .noma/
- 使用 handoff.py 进行帧交接
- 使用 ledger.py 管理资产/负债
- 使用 retcon_manager.py 处理设定修改
## 敏感内容
- 禁止: 政治敏感、真实暴力、未成年人性内容
- 伦理沙盒内创作自由
"""
return rules
def _format_dict(d: Dict[str, Any], indent: int = 2) -> str:
if not d:
return " (未设置)"
lines = []
for key, value in d.items():
if isinstance(value, dict):
lines.append(f" {key}:")
lines.append(_format_dict(value, indent + 2))
elif isinstance(value, list):
lines.append(f" {key}: {', '.join(str(v) for v in value)}")
else:
lines.append(f" {key}: {value}")
return "\n".join(lines)
def generate_project_config(project_root: Path, config: Dict[str, Any]) -> Path:
"""生成 Cursor 项目配置文件"""
config_dir = project_root / ".cursor"
config_dir.mkdir(exist_ok=True)
config_file = config_dir / "novelmaster.json"
with open(config_file, "w", encoding="utf-8") as f:
json.dump(config, f, ensure_ascii=False, indent=2)
rules_file = project_root / ".cursorrules"
rules_content = generate_cursorrules_content(config)
with open(rules_file, "w", encoding="utf-8") as f:
f.write(rules_content)
return rules_file
def detect_cursor_environment() -> bool:
"""检测是否在 Cursor 环境中"""
cursor_markers = [
".cursor",
".cursorrules",
"cursor_rules",
]
for marker in cursor_markers:
if Path(marker).exists():
return True
return False
@@ -0,0 +1,101 @@
"""
Universal IDE Adapter
NovelMaster Core Engine - Configurators
跨IDE统一接口 (Cursor, Windsurf, VS Code, JetBrains)
"""
from pathlib import Path
from typing import Dict, Any, Optional, List
from enum import Enum
from .cursor_adapter import generate_project_config as cursor_generate
from .windsurf_adapter import setup_windsurf
class IDEType(Enum):
CURSOR = "cursor"
WINDSURF = "windsurf"
VSCODE = "vscode"
JETBRAINS = "jetbrains"
UNKNOWN = "unknown"
def detect_ide() -> IDEType:
"""检测当前 IDE 环境"""
markers = Path.cwd()
cursor_markers = [".cursorrules", ".cursor"]
windsurf_markers = [".windsurfrules", ".windsurf"]
for marker in cursor_markers:
if (markers / marker).exists():
return IDEType.CURSOR
for marker in windsurf_markers:
if (markers / marker).exists():
return IDEType.WINDSURF
if "cursor" in Path.cwd().parts or "cursor" in str(Path(__file__)):
return IDEType.CURSOR
elif "windsurf" in Path.cwd().parts or "windsurf" in str(Path(__file__)):
return IDEType.WINDSURF
return IDEType.UNKNOWN
def setup_ide(project_root: Path, config: Dict[str, Any]) -> bool:
"""为检测到的 IDE 设置项目"""
ide = detect_ide()
if ide == IDEType.CURSOR:
cursor_generate(project_root, config)
return True
elif ide == IDEType.WINDSURF:
setup_windsurf(project_root, config)
return True
else:
return False
def generate_ide_rules(ide: IDEType, project_config: Dict[str, Any]) -> str:
"""为指定 IDE 生成规则"""
if ide == IDEType.CURSOR:
from .cursor_adapter import generate_cursorrules_content
return generate_cursorrules_content(project_config)
elif ide == IDEType.WINDSURF:
from .windsurf_adapter import generate_windsurfrules
return generate_windsurfrules(project_config)
else:
return ""
def get_supported_ides() -> List[str]:
"""获取支持的 IDE 列表"""
return [e.value for e in IDEType if e != IDEType.UNKNOWN]
def auto_setup(project_root: Path, config: Dict[str, Any]) -> Dict[str, bool]:
"""自动为所有支持的 IDE 生成配置"""
results = {}
results["cursor"] = _setup_cursor(project_root, config)
results["windsurf"] = _setup_windsurf(project_root, config)
return results
def _setup_cursor(project_root: Path, config: Dict[str, Any]) -> bool:
try:
cursor_generate(project_root, config)
return True
except Exception:
return False
def _setup_windsurf(project_root: Path, config: Dict[str, Any]) -> bool:
try:
setup_windsurf(project_root, config)
return True
except Exception:
return False
@@ -0,0 +1,77 @@
"""
Windsurf IDE Adapter
NovelMaster Core Engine - Configurators
为 Windsurf IDE 生成配置和 Cascade 上下文
"""
from pathlib import Path
from typing import Dict, Any
import json
def generate_windsurfrules(project_config: Dict[str, Any]) -> str:
"""生成 .windsurfrules 文件内容"""
genesis = project_config.get("genesis_contract", {})
rules = f"""# NovelMaster Windsurf Rules
## 项目配置
- 名称: {project_config.get("project_name", "未命名")}
- 题材: {project_config.get("genre", "网文")}
## Genesis Contract
{genesis.get("description", "")}
## Cascade 上下文
使用以下上下文进行创作:
1. 核心欲望: {genesis.get("core_desire", {}).get("primary", "未设置")}
2. 伦理沙盒: {genesis.get("ethical_inversion", {}).get("inverted_norms", [])}
3. 奇观设定: {genesis.get("core_spectacle", {}).get("ordinary_state", "未设置")}
## 写作工作流
1. Planner Agent 调度 catharsis_model
2. Writer Agent 生成章节
3. Handoff 帧交接
4. Dashboard 监控
## 状态文件
- 状态文件: .noma/state.json
- 账本: .noma/ledger.json
- Hook池: .noma/hooks_pool.json
"""
return rules
def generate_cascade_context(project_root: Path) -> Dict[str, Any]:
"""生成 Cascade 上下文"""
state_file = project_root / ".noma" / "state.json"
context = {
"project_root": str(project_root),
"noma_dir": str(project_root / ".noma"),
"genesis_contract": {},
"current_chapter": 1,
"hooks": [],
"ledger": {}
}
if state_file.exists():
try:
with open(state_file, "r", encoding="utf-8") as f:
state = json.load(f)
context.update(state)
except Exception:
pass
return context
def setup_windsurf(project_root: Path, config: Dict[str, Any]) -> None:
"""设置 Windsurf 项目"""
rules_file = project_root / ".windsurfrules"
rules_content = generate_windsurfrules(config)
with open(rules_file, "w", encoding="utf-8") as f:
f.write(rules_content)