specmodule 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- llm/__init__.py +21 -0
- llm/client.py +654 -0
- llm/config.py +213 -0
- module_harness/__init__.py +201 -0
- module_harness/align.py +39 -0
- module_harness/builtins.py +29 -0
- module_harness/checkpoint.py +336 -0
- module_harness/cli.py +1492 -0
- module_harness/command.py +115 -0
- module_harness/config.py +95 -0
- module_harness/consistency.py +123 -0
- module_harness/entry.py +74 -0
- module_harness/events.py +149 -0
- module_harness/feed.py +197 -0
- module_harness/graph_builder.py +334 -0
- module_harness/harness.py +181 -0
- module_harness/loader.py +215 -0
- module_harness/module.py +452 -0
- module_harness/outputfmt.py +139 -0
- module_harness/prompt.py +84 -0
- module_harness/query.py +216 -0
- module_harness/registry.py +180 -0
- module_harness/scaffold.py +404 -0
- module_harness/spec.py +209 -0
- module_harness/status.py +96 -0
- module_harness/store.py +482 -0
- module_harness/submodule.py +268 -0
- module_harness/templates/builtin/codereview.json +32 -0
- module_harness/templates/builtin/docwrite.json +30 -0
- module_harness/templates/builtin/summarize.json +24 -0
- module_harness/templates/builtin/translate.json +27 -0
- module_harness/translator.py +314 -0
- specmodule-0.1.0.dist-info/METADATA +321 -0
- specmodule-0.1.0.dist-info/RECORD +38 -0
- specmodule-0.1.0.dist-info/WHEEL +5 -0
- specmodule-0.1.0.dist-info/entry_points.txt +2 -0
- specmodule-0.1.0.dist-info/licenses/LICENSE +21 -0
- specmodule-0.1.0.dist-info/top_level.txt +2 -0
llm/config.py
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"""LLM 客户端配置
|
|
2
|
+
|
|
3
|
+
支持多种LLM后端:Anthropic、OpenAI 及兼容接口。
|
|
4
|
+
通过项目根目录的 config.json 和 rules.txt 配置::
|
|
5
|
+
|
|
6
|
+
config.json — Provider + Model 注册表
|
|
7
|
+
rules.txt — 框架级输出格式约束(注入 system prompt)
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import json
|
|
13
|
+
import logging
|
|
14
|
+
import os
|
|
15
|
+
from dataclasses import dataclass, field
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
from typing import Any
|
|
18
|
+
|
|
19
|
+
log = logging.getLogger(__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _load_dotenv(roots: Path | list[Path]) -> None:
|
|
23
|
+
"""按候选根顺序加载 .env 到 os.environ(若存在)。
|
|
24
|
+
|
|
25
|
+
roots:单个根(旧签名兼容)或候选根列表(store 根 → 项目根,前者优先)。
|
|
26
|
+
既有约定保持:已存在于 os.environ 的键不被 .env 覆盖。
|
|
27
|
+
"""
|
|
28
|
+
if isinstance(roots, Path):
|
|
29
|
+
roots = [roots]
|
|
30
|
+
for root in roots:
|
|
31
|
+
env_path = root / ".env"
|
|
32
|
+
if not env_path.exists():
|
|
33
|
+
continue
|
|
34
|
+
try:
|
|
35
|
+
with open(env_path, encoding="utf-8") as f:
|
|
36
|
+
for line in f:
|
|
37
|
+
line = line.strip()
|
|
38
|
+
if not line or line.startswith("#") or "=" not in line:
|
|
39
|
+
continue
|
|
40
|
+
key, _, value = line.partition("=")
|
|
41
|
+
key = key.strip()
|
|
42
|
+
value = value.strip().strip("\"'")
|
|
43
|
+
if key and key not in os.environ:
|
|
44
|
+
os.environ[key] = value
|
|
45
|
+
except OSError:
|
|
46
|
+
pass
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _load_config_json(roots: Path | list[Path]) -> dict[str, Any]:
|
|
50
|
+
"""按候选根顺序加载 config.json。全部缺失/格式错误时返回空 dict。"""
|
|
51
|
+
if isinstance(roots, Path):
|
|
52
|
+
roots = [roots]
|
|
53
|
+
for root in roots:
|
|
54
|
+
config_path = root / "config.json"
|
|
55
|
+
if not config_path.exists():
|
|
56
|
+
continue
|
|
57
|
+
try:
|
|
58
|
+
with open(config_path, encoding="utf-8") as f:
|
|
59
|
+
return json.load(f)
|
|
60
|
+
except (json.JSONDecodeError, OSError) as exc:
|
|
61
|
+
log.warning("config.json 解析失败: %s", exc)
|
|
62
|
+
return {}
|
|
63
|
+
log.warning("config.json 未找到(候选: %s)", ", ".join(str(r) for r in roots))
|
|
64
|
+
return {}
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _load_rules_txt(roots: Path | list[Path]) -> str:
|
|
68
|
+
"""按候选根顺序加载 rules.txt(取第一个存在的)。"""
|
|
69
|
+
if isinstance(roots, Path):
|
|
70
|
+
roots = [roots]
|
|
71
|
+
for root in roots:
|
|
72
|
+
rules_path = root / "rules.txt"
|
|
73
|
+
if not rules_path.exists():
|
|
74
|
+
continue
|
|
75
|
+
try:
|
|
76
|
+
return rules_path.read_text(encoding="utf-8").strip()
|
|
77
|
+
except OSError:
|
|
78
|
+
return ""
|
|
79
|
+
return ""
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@dataclass
|
|
83
|
+
class LLMConfig:
|
|
84
|
+
"""LLM 配置
|
|
85
|
+
|
|
86
|
+
优先级:HarnessConfig.api_params > LLMConfig 默认值 > config.json > 硬编码默认值
|
|
87
|
+
API key 通过 .env 中的环境变量注入(provider.api_key_env 指定变量名)。
|
|
88
|
+
|
|
89
|
+
支持的 sdktype:
|
|
90
|
+
- openai / openai-compatible: OpenAI 及兼容接口(DeepSeek 等)
|
|
91
|
+
- anthropic: Anthropic Claude API
|
|
92
|
+
"""
|
|
93
|
+
# ── 连接信息(来自 config.json providers)──
|
|
94
|
+
provider: str = "openai"
|
|
95
|
+
api_key: str = ""
|
|
96
|
+
base_url: str | None = None
|
|
97
|
+
timeout: float = 60.0
|
|
98
|
+
max_retries: int = 3
|
|
99
|
+
|
|
100
|
+
# ── 默认模型参数(harness 未指定时兜底)──
|
|
101
|
+
model: str = ""
|
|
102
|
+
max_tokens: int = 4096
|
|
103
|
+
temperature: float = 0.7
|
|
104
|
+
|
|
105
|
+
# ── 模型注册表(来自 config.json models)──
|
|
106
|
+
models: dict[str, dict[str, Any]] = field(default_factory=dict)
|
|
107
|
+
"""{model_name: {provider, think, multimodal, max_tokens, ...}}。"""
|
|
108
|
+
|
|
109
|
+
# ── 框架规则(来自 rules.txt)──
|
|
110
|
+
system_rules: str = ""
|
|
111
|
+
"""框架级输出格式约束,注入每次 LLM 调用的 system prompt 最前面。"""
|
|
112
|
+
|
|
113
|
+
def model_info(self, name: str) -> dict[str, Any]:
|
|
114
|
+
"""获取指定模型的能力声明。"""
|
|
115
|
+
return self.models.get(name, {})
|
|
116
|
+
|
|
117
|
+
@classmethod
|
|
118
|
+
def from_env(
|
|
119
|
+
cls,
|
|
120
|
+
project_root: Path | None = None,
|
|
121
|
+
store_root: Path | None = None,
|
|
122
|
+
**overrides: Any,
|
|
123
|
+
) -> "LLMConfig":
|
|
124
|
+
"""从 config.json + rules.txt + .env 加载配置(配置回退链)。
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
project_root: 项目根目录(最高候选)
|
|
128
|
+
store_root: store 家目录(用户级回退;项目根缺失时生效)
|
|
129
|
+
**overrides: 覆盖配置项
|
|
130
|
+
|
|
131
|
+
回退链:os.environ(最高,不覆盖已有键)→ 项目根 → store 根。
|
|
132
|
+
"""
|
|
133
|
+
if project_root is None:
|
|
134
|
+
project_root = Path.cwd()
|
|
135
|
+
|
|
136
|
+
# 候选根:项目根优先,store 根兜底(None 过滤)
|
|
137
|
+
roots = [project_root]
|
|
138
|
+
if store_root is not None:
|
|
139
|
+
roots.append(store_root)
|
|
140
|
+
|
|
141
|
+
# 1. 加载 .env -> os.environ(API key 等密钥)
|
|
142
|
+
_load_dotenv(roots)
|
|
143
|
+
|
|
144
|
+
# 2. 加载 config.json
|
|
145
|
+
cfg = _load_config_json(roots)
|
|
146
|
+
providers: list[dict[str, Any]] = cfg.get("providers", [])
|
|
147
|
+
models: list[dict[str, Any]] = cfg.get("models", [])
|
|
148
|
+
|
|
149
|
+
if not providers:
|
|
150
|
+
raise ValueError(
|
|
151
|
+
"config.json 中 providers 为空或缺失。"
|
|
152
|
+
"请参照 config.example.json 配置。"
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
# 3. 加载 rules.txt
|
|
156
|
+
system_rules = _load_rules_txt(roots)
|
|
157
|
+
|
|
158
|
+
# ── 选中 provider(取第一个)──
|
|
159
|
+
p = providers[0]
|
|
160
|
+
|
|
161
|
+
# ── 解析 API key ──
|
|
162
|
+
api_key = overrides.pop("api_key", None)
|
|
163
|
+
if api_key is None:
|
|
164
|
+
key_env = p.get("api_key_env", "")
|
|
165
|
+
api_key = os.environ.get(key_env, "") if key_env else ""
|
|
166
|
+
|
|
167
|
+
# ── 构建 models 注册表 ──
|
|
168
|
+
models_map: dict[str, dict[str, Any]] = {}
|
|
169
|
+
default_model = ""
|
|
170
|
+
default_temperature = 0.7
|
|
171
|
+
|
|
172
|
+
for m in models:
|
|
173
|
+
name = m.get("name", "")
|
|
174
|
+
if name:
|
|
175
|
+
models_map[name] = m
|
|
176
|
+
if not default_model:
|
|
177
|
+
default_model = name
|
|
178
|
+
default_temperature = float(m.get("temperature", 0.7))
|
|
179
|
+
|
|
180
|
+
config = cls(
|
|
181
|
+
provider=p.get("sdktype", "openai"),
|
|
182
|
+
api_key=api_key,
|
|
183
|
+
base_url=p.get("base_url"),
|
|
184
|
+
timeout=float(p.get("timeout", 60.0)),
|
|
185
|
+
max_retries=int(p.get("max_retries", 3)),
|
|
186
|
+
model=overrides.pop("model", None) or default_model,
|
|
187
|
+
max_tokens=int(overrides.pop("max_tokens", None) or 4096),
|
|
188
|
+
temperature=float(overrides.pop("temperature", None) or default_temperature),
|
|
189
|
+
models=models_map,
|
|
190
|
+
system_rules=system_rules,
|
|
191
|
+
)
|
|
192
|
+
for key, value in overrides.items():
|
|
193
|
+
if hasattr(config, key) and value is not None:
|
|
194
|
+
setattr(config, key, value)
|
|
195
|
+
return config
|
|
196
|
+
|
|
197
|
+
def to_client_kwargs(self) -> dict[str, Any]:
|
|
198
|
+
"""转为客户端构造参数"""
|
|
199
|
+
kwargs: dict[str, Any] = {
|
|
200
|
+
"model": self.model,
|
|
201
|
+
"api_key": self.api_key,
|
|
202
|
+
"max_tokens": self.max_tokens,
|
|
203
|
+
"temperature": self.temperature,
|
|
204
|
+
"timeout": self.timeout,
|
|
205
|
+
}
|
|
206
|
+
if self.base_url:
|
|
207
|
+
kwargs["base_url"] = self.base_url
|
|
208
|
+
return kwargs
|
|
209
|
+
|
|
210
|
+
@property
|
|
211
|
+
def is_configured(self) -> bool:
|
|
212
|
+
"""是否已配置 API Key"""
|
|
213
|
+
return bool(self.api_key)
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# module_harness/__init__.py
|
|
2
|
+
"""ModuleHarness — tickflow 上层抽象:harness 与 script 执行元件。"""
|
|
3
|
+
|
|
4
|
+
from .config import HarnessConfig
|
|
5
|
+
from .outputfmt import OutputFormat, OutputValidator
|
|
6
|
+
from .prompt import PromptRenderer
|
|
7
|
+
from .events import (
|
|
8
|
+
EventBus,
|
|
9
|
+
HarnessEvent,
|
|
10
|
+
PromptRendered,
|
|
11
|
+
LlmCallStarted,
|
|
12
|
+
LlmToken,
|
|
13
|
+
LlmCallCompleted,
|
|
14
|
+
OutputValidated,
|
|
15
|
+
HarnessFailed,
|
|
16
|
+
ConsistencyReviewed,
|
|
17
|
+
ScriptEvent,
|
|
18
|
+
ScriptStarted,
|
|
19
|
+
ScriptCompleted,
|
|
20
|
+
ScriptFailed,
|
|
21
|
+
CommandStarted,
|
|
22
|
+
CommandCompleted,
|
|
23
|
+
CommandFailed,
|
|
24
|
+
)
|
|
25
|
+
from .command import Command, CommandConfig
|
|
26
|
+
from .harness import Harness
|
|
27
|
+
from .registry import HarnessRegistry
|
|
28
|
+
from .spec import (
|
|
29
|
+
Spec,
|
|
30
|
+
TaskDefinition,
|
|
31
|
+
Tasklist,
|
|
32
|
+
TranslationSpec,
|
|
33
|
+
TasklistTemplate,
|
|
34
|
+
)
|
|
35
|
+
from .consistency import (
|
|
36
|
+
ConsistencyError,
|
|
37
|
+
ConsistencyReport,
|
|
38
|
+
ConsistencyReviewer,
|
|
39
|
+
REVIEW_HARNESS_CONFIG,
|
|
40
|
+
register_review_harness,
|
|
41
|
+
)
|
|
42
|
+
from .align import ALIGN_CHECK_CONFIG, register_align_check_harness
|
|
43
|
+
from .builtins import BUILTIN_HARNESS_NAMES, register_builtin_harnesses
|
|
44
|
+
from .translator import TasklistValidator, TemplateLoader, Translator
|
|
45
|
+
from .graph_builder import TasklistTranslator
|
|
46
|
+
from .module import Module
|
|
47
|
+
from .submodule import SubModule, SpecValidationError, script
|
|
48
|
+
from .loader import ModuleLoader, ModuleManifestError, ModuleRequirementError
|
|
49
|
+
from .spec import SpecSchema
|
|
50
|
+
from .status import ModuleStatus, query_run_status
|
|
51
|
+
from .entry import ModuleEntry, discover_modules
|
|
52
|
+
from .query import (
|
|
53
|
+
CheckpointEntry,
|
|
54
|
+
CheckpointList,
|
|
55
|
+
ReviewEntry,
|
|
56
|
+
ReviewTimeline,
|
|
57
|
+
build_checkpoints,
|
|
58
|
+
build_timeline,
|
|
59
|
+
checkpoints_to_dict,
|
|
60
|
+
filter_failed,
|
|
61
|
+
filter_node,
|
|
62
|
+
filter_tick,
|
|
63
|
+
timeline_to_dict,
|
|
64
|
+
)
|
|
65
|
+
from .checkpoint import (
|
|
66
|
+
ModuleInputStore,
|
|
67
|
+
ResumeCheck,
|
|
68
|
+
ResumeError,
|
|
69
|
+
check_resume_compat,
|
|
70
|
+
)
|
|
71
|
+
from . import store as store_module
|
|
72
|
+
from .store import (
|
|
73
|
+
ENTRY_POINT_GROUP,
|
|
74
|
+
ModuleSource,
|
|
75
|
+
apply_update,
|
|
76
|
+
cache_dir,
|
|
77
|
+
check_updates,
|
|
78
|
+
file_sha256,
|
|
79
|
+
install_pack,
|
|
80
|
+
list_modules,
|
|
81
|
+
load_manifest,
|
|
82
|
+
manifests_dir,
|
|
83
|
+
modules_dir,
|
|
84
|
+
parse_dotenv,
|
|
85
|
+
pip_entry_point_dirs,
|
|
86
|
+
resolve_module,
|
|
87
|
+
search_paths,
|
|
88
|
+
store_home,
|
|
89
|
+
uninstall_pack,
|
|
90
|
+
validate_pack_dir,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
__all__ = [
|
|
94
|
+
# 配置
|
|
95
|
+
"HarnessConfig",
|
|
96
|
+
# 输出格式
|
|
97
|
+
"OutputFormat",
|
|
98
|
+
"OutputValidator",
|
|
99
|
+
# Prompt
|
|
100
|
+
"PromptRenderer",
|
|
101
|
+
# 事件
|
|
102
|
+
"EventBus",
|
|
103
|
+
"HarnessEvent",
|
|
104
|
+
"PromptRendered",
|
|
105
|
+
"LlmCallStarted",
|
|
106
|
+
"LlmToken",
|
|
107
|
+
"LlmCallCompleted",
|
|
108
|
+
"OutputValidated",
|
|
109
|
+
"HarnessFailed",
|
|
110
|
+
"ScriptEvent",
|
|
111
|
+
"ScriptStarted",
|
|
112
|
+
"ScriptCompleted",
|
|
113
|
+
"ScriptFailed",
|
|
114
|
+
# 核心
|
|
115
|
+
"Harness",
|
|
116
|
+
"HarnessRegistry",
|
|
117
|
+
"Command",
|
|
118
|
+
"CommandConfig",
|
|
119
|
+
# Command 事件
|
|
120
|
+
"CommandStarted",
|
|
121
|
+
"CommandCompleted",
|
|
122
|
+
"CommandFailed",
|
|
123
|
+
# 数据模型
|
|
124
|
+
"Spec",
|
|
125
|
+
"TaskDefinition",
|
|
126
|
+
"Tasklist",
|
|
127
|
+
"TranslationSpec",
|
|
128
|
+
"TasklistTemplate",
|
|
129
|
+
# 翻译
|
|
130
|
+
"TasklistValidator",
|
|
131
|
+
"TemplateLoader",
|
|
132
|
+
"Translator",
|
|
133
|
+
# Graph 构建
|
|
134
|
+
"TasklistTranslator",
|
|
135
|
+
# 编排
|
|
136
|
+
"Module",
|
|
137
|
+
# 一致性审核
|
|
138
|
+
"ConsistencyReviewed",
|
|
139
|
+
"ConsistencyError",
|
|
140
|
+
"ConsistencyReport",
|
|
141
|
+
"ConsistencyReviewer",
|
|
142
|
+
"REVIEW_HARNESS_CONFIG",
|
|
143
|
+
"register_review_harness",
|
|
144
|
+
# 对齐检查
|
|
145
|
+
"ALIGN_CHECK_CONFIG",
|
|
146
|
+
"register_align_check_harness",
|
|
147
|
+
# 内置 harness(翻译/审核/对齐):宿主需显式注册到自己的 registry
|
|
148
|
+
"BUILTIN_HARNESS_NAMES",
|
|
149
|
+
"register_builtin_harnesses",
|
|
150
|
+
# 运行状态查询
|
|
151
|
+
"ModuleStatus",
|
|
152
|
+
"query_run_status",
|
|
153
|
+
# submodule
|
|
154
|
+
"SubModule",
|
|
155
|
+
"script",
|
|
156
|
+
"SpecValidationError",
|
|
157
|
+
"SpecSchema",
|
|
158
|
+
"ModuleLoader",
|
|
159
|
+
"ModuleManifestError",
|
|
160
|
+
"ModuleRequirementError",
|
|
161
|
+
# 快照/回滚(roadmap #5)
|
|
162
|
+
"ModuleInputStore",
|
|
163
|
+
"ResumeCheck",
|
|
164
|
+
"ResumeError",
|
|
165
|
+
"check_resume_compat",
|
|
166
|
+
# 模块入口(roadmap Phase 0:CLI 使用)
|
|
167
|
+
"ModuleEntry",
|
|
168
|
+
"discover_modules",
|
|
169
|
+
# 共享查询层(roadmap Phase 0:CLI/MCP/Web 复用)
|
|
170
|
+
"ReviewEntry",
|
|
171
|
+
"ReviewTimeline",
|
|
172
|
+
"build_timeline",
|
|
173
|
+
"filter_failed",
|
|
174
|
+
"filter_node",
|
|
175
|
+
"filter_tick",
|
|
176
|
+
"timeline_to_dict",
|
|
177
|
+
# 共享查询层(回退点列表:resume/rollback 目标清单)
|
|
178
|
+
"CheckpointEntry",
|
|
179
|
+
"CheckpointList",
|
|
180
|
+
"build_checkpoints",
|
|
181
|
+
"checkpoints_to_dict",
|
|
182
|
+
# store 共享层(module-user-store:家目录/枚举/安装管理)
|
|
183
|
+
"store_home",
|
|
184
|
+
"search_paths",
|
|
185
|
+
"list_modules",
|
|
186
|
+
"resolve_module",
|
|
187
|
+
"ModuleSource",
|
|
188
|
+
"ENTRY_POINT_GROUP",
|
|
189
|
+
"pip_entry_point_dirs",
|
|
190
|
+
"modules_dir",
|
|
191
|
+
"manifests_dir",
|
|
192
|
+
"cache_dir",
|
|
193
|
+
"validate_pack_dir",
|
|
194
|
+
"install_pack",
|
|
195
|
+
"load_manifest",
|
|
196
|
+
"uninstall_pack",
|
|
197
|
+
"check_updates",
|
|
198
|
+
"apply_update",
|
|
199
|
+
"file_sha256",
|
|
200
|
+
"parse_dotenv",
|
|
201
|
+
]
|
module_harness/align.py
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# module_harness/align.py
|
|
2
|
+
"""对齐检查 — 内置 align_check harness 节点(roadmap #2)。
|
|
3
|
+
|
|
4
|
+
普通 harness 节点:模板设计者在 flow 中自行插入(通常放在关键产出节点之后),
|
|
5
|
+
框架不额外调度。不插入即不执行。
|
|
6
|
+
|
|
7
|
+
前置输出注入:prompt_core 不含 {字段} 占位符(无隐式行为);模板设计者通过
|
|
8
|
+
task.prompt(Layer 3)注入前置节点输出,例如模板中
|
|
9
|
+
"inputs": {"output_a": "A"} + "prompt": "节点 A 输出:{output_a}"
|
|
10
|
+
(input_aliases 机制,运行时把 A 的输出渲染进 {output_a})。
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
from .config import HarnessConfig
|
|
16
|
+
from .outputfmt import OutputFormat
|
|
17
|
+
from .registry import HarnessRegistry
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
ALIGN_CHECK_CONFIG = HarnessConfig(
|
|
21
|
+
name="align_check",
|
|
22
|
+
prompt_core=(
|
|
23
|
+
"你是对齐检查器。判断当前节点产出是否偏离 spec 目标。\n"
|
|
24
|
+
"spec: {spec}\n"
|
|
25
|
+
"tasklist: {tasklist}\n"
|
|
26
|
+
"当前位置: {node}\n"
|
|
27
|
+
"结合已提供的前置节点输出判断(若有),输出 JSON:"
|
|
28
|
+
'{"aligned": true/false, "suggestions": "..."}'
|
|
29
|
+
),
|
|
30
|
+
output_format=OutputFormat(type="json_object"),
|
|
31
|
+
temperature=0.1,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def register_align_check_harness(
|
|
36
|
+
reg: HarnessRegistry, name: str = "align_check"
|
|
37
|
+
) -> None:
|
|
38
|
+
"""注册内置对齐检查 harness(默认名 align_check)。"""
|
|
39
|
+
reg.harness(name, ALIGN_CHECK_CONFIG)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# module_harness/builtins.py
|
|
2
|
+
"""内置 harness 集 — requires 的默认提供方。"""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
from .align import register_align_check_harness
|
|
7
|
+
from .config import HarnessConfig, OutputFormat
|
|
8
|
+
from .consistency import register_review_harness
|
|
9
|
+
from .registry import HarnessRegistry
|
|
10
|
+
|
|
11
|
+
BUILTIN_HARNESS_NAMES: frozenset[str] = frozenset({
|
|
12
|
+
"spec_to_tasklist", "spec_tasklist_review", "align_check",
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
# 翻译 harness 最小骨架;模板的 prompt_core 在翻译时覆盖(translator.py)
|
|
16
|
+
SPEC_TO_TASKLIST_CONFIG = HarnessConfig(
|
|
17
|
+
name="spec_to_tasklist",
|
|
18
|
+
prompt_core="根据 spec 生成 tasklist JSON。",
|
|
19
|
+
output_format=OutputFormat(type="json_object"),
|
|
20
|
+
temperature=0.3,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def register_builtin_harnesses(reg: HarnessRegistry) -> None:
|
|
25
|
+
"""注册内置 harness(spec_to_tasklist、spec_tasklist_review、align_check)。
|
|
26
|
+
幂等,可重复调用。"""
|
|
27
|
+
reg.harness("spec_to_tasklist", SPEC_TO_TASKLIST_CONFIG)
|
|
28
|
+
register_review_harness(reg)
|
|
29
|
+
register_align_check_harness(reg)
|