cognitive-modules 0.1.1__py3-none-any.whl → 0.3.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.
cognitive/loader.py CHANGED
@@ -1,17 +1,22 @@
1
1
  """
2
- Module Loader - Load cognitive modules in both old and new formats.
2
+ Module Loader - Load cognitive modules in all formats.
3
3
 
4
- Old format (6 files):
4
+ Format v2 (recommended):
5
+ - module.yaml (machine-readable manifest)
6
+ - prompt.md (human-readable prompt)
7
+ - schema.json (input + output + error)
8
+ - tests/ (golden tests)
9
+
10
+ Format v1 (legacy, still supported):
11
+ - MODULE.md (YAML frontmatter + prompt)
12
+ - schema.json (input + output)
13
+
14
+ Format v0 (old, deprecated):
5
15
  - module.md (YAML frontmatter)
6
16
  - input.schema.json
7
17
  - output.schema.json
8
18
  - constraints.yaml
9
19
  - prompt.txt
10
- - examples/
11
-
12
- New format (2 files):
13
- - MODULE.md (YAML frontmatter + prompt)
14
- - schema.json (input + output combined)
15
20
  """
16
21
 
17
22
  import json
@@ -22,13 +27,15 @@ import yaml
22
27
 
23
28
 
24
29
  def detect_format(module_path: Path) -> str:
25
- """Detect module format: 'new' or 'old'."""
26
- if (module_path / "MODULE.md").exists():
27
- return "new"
30
+ """Detect module format: 'v2', 'v1', or 'v0'."""
31
+ if (module_path / "module.yaml").exists():
32
+ return "v2"
33
+ elif (module_path / "MODULE.md").exists():
34
+ return "v1"
28
35
  elif (module_path / "module.md").exists():
29
- return "old"
36
+ return "v0"
30
37
  else:
31
- raise FileNotFoundError(f"No MODULE.md or module.md found in {module_path}")
38
+ raise FileNotFoundError(f"No module.yaml, MODULE.md, or module.md found in {module_path}")
32
39
 
33
40
 
34
41
  def parse_frontmatter(content: str) -> tuple[dict, str]:
@@ -45,8 +52,90 @@ def parse_frontmatter(content: str) -> tuple[dict, str]:
45
52
  return frontmatter, body
46
53
 
47
54
 
48
- def load_new_format(module_path: Path) -> dict:
49
- """Load module in new format (MODULE.md + schema.json)."""
55
+ def load_v2_format(module_path: Path) -> dict:
56
+ """Load module in v2 format (module.yaml + prompt.md + schema.json)."""
57
+ # Load module.yaml
58
+ with open(module_path / "module.yaml", 'r', encoding='utf-8') as f:
59
+ manifest = yaml.safe_load(f)
60
+
61
+ # Load prompt.md
62
+ prompt_path = module_path / "prompt.md"
63
+ if prompt_path.exists():
64
+ with open(prompt_path, 'r', encoding='utf-8') as f:
65
+ prompt = f.read()
66
+ else:
67
+ prompt = ""
68
+
69
+ # Load schema.json
70
+ schema_path = module_path / "schema.json"
71
+ if schema_path.exists():
72
+ with open(schema_path, 'r', encoding='utf-8') as f:
73
+ schema = json.load(f)
74
+ input_schema = schema.get("input", {})
75
+ output_schema = schema.get("output", {})
76
+ error_schema = schema.get("error", {})
77
+ else:
78
+ input_schema = {}
79
+ output_schema = {}
80
+ error_schema = {}
81
+
82
+ # Extract constraints (supports both old and new format)
83
+ constraints_raw = manifest.get("constraints", {})
84
+ policies_raw = manifest.get("policies", {})
85
+
86
+ constraints = {
87
+ "operational": {
88
+ "no_external_network": constraints_raw.get("no_network", True) or policies_raw.get("network") == "deny",
89
+ "no_side_effects": constraints_raw.get("no_side_effects", True) or policies_raw.get("side_effects") == "deny",
90
+ "no_file_write": constraints_raw.get("no_file_write", True) or policies_raw.get("filesystem_write") == "deny",
91
+ "no_inventing_data": constraints_raw.get("no_inventing_data", True),
92
+ },
93
+ "output_quality": {
94
+ "require_confidence": manifest.get("output", {}).get("require_confidence", True),
95
+ "require_rationale": manifest.get("output", {}).get("require_rationale", True),
96
+ "require_behavior_equivalence": manifest.get("output", {}).get("require_behavior_equivalence", False),
97
+ },
98
+ "behavior_equivalence_false_max_confidence": constraints_raw.get("behavior_equivalence_false_max_confidence", 0.7),
99
+ }
100
+
101
+ # Extract policies (v2.1)
102
+ policies = manifest.get("policies", {})
103
+
104
+ # Extract tools policy
105
+ tools = manifest.get("tools", {})
106
+
107
+ # Extract output contract
108
+ output_contract = manifest.get("output", {})
109
+
110
+ # Extract failure contract
111
+ failure_contract = manifest.get("failure", {})
112
+
113
+ # Extract runtime requirements
114
+ runtime_requirements = manifest.get("runtime_requirements", {})
115
+
116
+ return {
117
+ "name": manifest.get("name", module_path.name),
118
+ "version": manifest.get("version", "1.0.0"),
119
+ "responsibility": manifest.get("responsibility", ""),
120
+ "excludes": manifest.get("excludes", []),
121
+ "path": module_path,
122
+ "format": "v2",
123
+ "metadata": manifest,
124
+ "input_schema": input_schema,
125
+ "output_schema": output_schema,
126
+ "error_schema": error_schema,
127
+ "constraints": constraints,
128
+ "policies": policies,
129
+ "tools": tools,
130
+ "output_contract": output_contract,
131
+ "failure_contract": failure_contract,
132
+ "runtime_requirements": runtime_requirements,
133
+ "prompt": prompt,
134
+ }
135
+
136
+
137
+ def load_v1_format(module_path: Path) -> dict:
138
+ """Load module in v1 format (MODULE.md + schema.json)."""
50
139
  # Load MODULE.md
51
140
  with open(module_path / "MODULE.md", 'r', encoding='utf-8') as f:
52
141
  content = f.read()
@@ -79,8 +168,11 @@ def load_new_format(module_path: Path) -> dict:
79
168
 
80
169
  return {
81
170
  "name": metadata.get("name", module_path.name),
171
+ "version": metadata.get("version", "1.0.0"),
172
+ "responsibility": metadata.get("responsibility", ""),
173
+ "excludes": metadata.get("excludes", []),
82
174
  "path": module_path,
83
- "format": "new",
175
+ "format": "v1",
84
176
  "metadata": metadata,
85
177
  "input_schema": input_schema,
86
178
  "output_schema": output_schema,
@@ -89,8 +181,8 @@ def load_new_format(module_path: Path) -> dict:
89
181
  }
90
182
 
91
183
 
92
- def load_old_format(module_path: Path) -> dict:
93
- """Load module in old format (6 files)."""
184
+ def load_v0_format(module_path: Path) -> dict:
185
+ """Load module in v0 format (old 6-file format)."""
94
186
  # Load module.md
95
187
  with open(module_path / "module.md", 'r', encoding='utf-8') as f:
96
188
  content = f.read()
@@ -114,8 +206,11 @@ def load_old_format(module_path: Path) -> dict:
114
206
 
115
207
  return {
116
208
  "name": metadata.get("name", module_path.name),
209
+ "version": metadata.get("version", "1.0.0"),
210
+ "responsibility": metadata.get("responsibility", ""),
211
+ "excludes": [],
117
212
  "path": module_path,
118
- "format": "old",
213
+ "format": "v0",
119
214
  "metadata": metadata,
120
215
  "input_schema": input_schema,
121
216
  "output_schema": output_schema,
@@ -127,7 +222,37 @@ def load_old_format(module_path: Path) -> dict:
127
222
  def load_module(module_path: Path) -> dict:
128
223
  """Load a module, auto-detecting format."""
129
224
  fmt = detect_format(module_path)
130
- if fmt == "new":
131
- return load_new_format(module_path)
225
+ if fmt == "v2":
226
+ return load_v2_format(module_path)
227
+ elif fmt == "v1":
228
+ return load_v1_format(module_path)
132
229
  else:
133
- return load_old_format(module_path)
230
+ return load_v0_format(module_path)
231
+
232
+
233
+ def find_module(name: str, search_paths: list[Path]) -> Optional[dict]:
234
+ """Find and load a module by name from search paths."""
235
+ for base_path in search_paths:
236
+ module_path = base_path / name
237
+ if module_path.exists():
238
+ try:
239
+ return load_module(module_path)
240
+ except FileNotFoundError:
241
+ continue
242
+ return None
243
+
244
+
245
+ def list_modules(search_paths: list[Path]) -> list[dict]:
246
+ """List all modules in search paths."""
247
+ modules = []
248
+ for base_path in search_paths:
249
+ if not base_path.exists():
250
+ continue
251
+ for module_dir in base_path.iterdir():
252
+ if module_dir.is_dir():
253
+ try:
254
+ module = load_module(module_dir)
255
+ modules.append(module)
256
+ except FileNotFoundError:
257
+ continue
258
+ return modules
cognitive/runner.py CHANGED
@@ -1,11 +1,11 @@
1
1
  """
2
2
  Module Runner - Execute cognitive modules with validation.
3
- Supports both old and new module formats.
3
+ Supports v2 envelope format and legacy formats.
4
4
  """
5
5
 
6
6
  import json
7
7
  from pathlib import Path
8
- from typing import Optional
8
+ from typing import Optional, TypedDict, Union
9
9
 
10
10
  import jsonschema
11
11
  import yaml
@@ -15,6 +15,25 @@ from .loader import load_module
15
15
  from .providers import call_llm
16
16
 
17
17
 
18
+ class EnvelopeError(TypedDict):
19
+ code: str
20
+ message: str
21
+
22
+
23
+ class EnvelopeSuccess(TypedDict):
24
+ ok: bool # True
25
+ data: dict
26
+
27
+
28
+ class EnvelopeFailure(TypedDict):
29
+ ok: bool # False
30
+ error: EnvelopeError
31
+ partial_data: Optional[dict]
32
+
33
+
34
+ EnvelopeResponse = Union[EnvelopeSuccess, EnvelopeFailure]
35
+
36
+
18
37
  def validate_data(data: dict, schema: dict, label: str = "Data") -> list[str]:
19
38
  """Validate data against schema. Returns list of errors."""
20
39
  errors = []
@@ -32,7 +51,7 @@ def validate_data(data: dict, schema: dict, label: str = "Data") -> list[str]:
32
51
  def substitute_arguments(text: str, input_data: dict) -> str:
33
52
  """Substitute $ARGUMENTS and $N placeholders in text."""
34
53
  # Get arguments
35
- args_value = input_data.get("$ARGUMENTS", input_data.get("query", ""))
54
+ args_value = input_data.get("$ARGUMENTS", input_data.get("query", input_data.get("code", "")))
36
55
 
37
56
  # Replace $ARGUMENTS
38
57
  text = text.replace("$ARGUMENTS", str(args_value))
@@ -47,7 +66,7 @@ def substitute_arguments(text: str, input_data: dict) -> str:
47
66
  return text
48
67
 
49
68
 
50
- def build_prompt(module: dict, input_data: dict) -> str:
69
+ def build_prompt(module: dict, input_data: dict, use_envelope: bool = False) -> str:
51
70
  """Build the complete prompt for the LLM."""
52
71
  # Substitute $ARGUMENTS in prompt
53
72
  prompt = substitute_arguments(module["prompt"], input_data)
@@ -60,10 +79,23 @@ def build_prompt(module: dict, input_data: dict) -> str:
60
79
  "```json\n",
61
80
  json.dumps(input_data, indent=2, ensure_ascii=False),
62
81
  "\n```\n",
63
- "\n## Instructions\n",
64
- "Analyze the input and generate output matching the required schema.",
65
- "Return ONLY valid JSON. Do not include any text before or after the JSON.",
66
82
  ]
83
+
84
+ if use_envelope:
85
+ parts.extend([
86
+ "\n## Response Format (Envelope)\n",
87
+ "You MUST wrap your response in the envelope format:\n",
88
+ "- Success: { \"ok\": true, \"data\": { ...your output... } }\n",
89
+ "- Error: { \"ok\": false, \"error\": { \"code\": \"ERROR_CODE\", \"message\": \"...\" } }\n",
90
+ "Return ONLY valid JSON.\n",
91
+ ])
92
+ else:
93
+ parts.extend([
94
+ "\n## Instructions\n",
95
+ "Analyze the input and generate output matching the required schema.",
96
+ "Return ONLY valid JSON. Do not include any text before or after the JSON.",
97
+ ])
98
+
67
99
  return "".join(parts)
68
100
 
69
101
 
@@ -85,16 +117,56 @@ def parse_llm_response(response: str) -> dict:
85
117
  return json.loads(text)
86
118
 
87
119
 
120
+ def is_envelope_response(data: dict) -> bool:
121
+ """Check if response is in envelope format."""
122
+ return isinstance(data.get("ok"), bool)
123
+
124
+
125
+ def parse_envelope_response(data: dict) -> EnvelopeResponse:
126
+ """Parse and normalize envelope response."""
127
+ if data.get("ok") is True:
128
+ return {
129
+ "ok": True,
130
+ "data": data.get("data", {})
131
+ }
132
+ else:
133
+ return {
134
+ "ok": False,
135
+ "error": data.get("error", {"code": "UNKNOWN", "message": "Unknown error"}),
136
+ "partial_data": data.get("partial_data")
137
+ }
138
+
139
+
140
+ def convert_to_envelope(data: dict, is_error: bool = False) -> EnvelopeResponse:
141
+ """Convert legacy format to envelope format."""
142
+ if is_error or "error" in data:
143
+ error = data.get("error", {})
144
+ return {
145
+ "ok": False,
146
+ "error": {
147
+ "code": error.get("code", "UNKNOWN"),
148
+ "message": error.get("message", str(error))
149
+ },
150
+ "partial_data": None
151
+ }
152
+ else:
153
+ return {
154
+ "ok": True,
155
+ "data": data
156
+ }
157
+
158
+
88
159
  def run_module(
89
160
  name_or_path: str,
90
161
  input_data: dict,
91
162
  validate_input: bool = True,
92
163
  validate_output: bool = True,
93
164
  model: Optional[str] = None,
94
- ) -> dict:
165
+ use_envelope: Optional[bool] = None,
166
+ ) -> EnvelopeResponse:
95
167
  """
96
168
  Run a cognitive module with the given input.
97
- Supports both old and new module formats.
169
+ Returns envelope format response.
98
170
 
99
171
  Args:
100
172
  name_or_path: Module name or path to module directory
@@ -102,9 +174,10 @@ def run_module(
102
174
  validate_input: Whether to validate input against schema
103
175
  validate_output: Whether to validate output against schema
104
176
  model: Optional model override
177
+ use_envelope: Force envelope format (auto-detect if None)
105
178
 
106
179
  Returns:
107
- The module output as a dictionary
180
+ EnvelopeResponse with ok=True/False and data/error
108
181
  """
109
182
  # Find module path
110
183
  path = Path(name_or_path)
@@ -113,28 +186,91 @@ def run_module(
113
186
  else:
114
187
  module_path = find_module(name_or_path)
115
188
  if not module_path:
116
- raise FileNotFoundError(f"Module not found: {name_or_path}")
189
+ return {
190
+ "ok": False,
191
+ "error": {"code": "MODULE_NOT_FOUND", "message": f"Module not found: {name_or_path}"},
192
+ "partial_data": None
193
+ }
117
194
 
118
195
  # Load module (auto-detects format)
119
196
  module = load_module(module_path)
120
197
 
198
+ # Determine if we should use envelope format
199
+ should_use_envelope = use_envelope
200
+ if should_use_envelope is None:
201
+ # Auto-detect: use envelope for v2 format or if output.envelope is True
202
+ output_contract = module.get("output_contract", {})
203
+ should_use_envelope = (
204
+ module.get("format") == "v2" or
205
+ output_contract.get("envelope", False)
206
+ )
207
+
121
208
  # Validate input
122
209
  if validate_input and module["input_schema"]:
123
210
  errors = validate_data(input_data, module["input_schema"], "Input")
124
211
  if errors:
125
- raise ValueError(f"Input validation failed: {errors}")
212
+ return {
213
+ "ok": False,
214
+ "error": {"code": "INVALID_INPUT", "message": str(errors)},
215
+ "partial_data": None
216
+ }
126
217
 
127
218
  # Build prompt and call LLM
128
- full_prompt = build_prompt(module, input_data)
219
+ full_prompt = build_prompt(module, input_data, use_envelope=should_use_envelope)
129
220
  response = call_llm(full_prompt, model=model)
130
221
 
131
222
  # Parse response
132
- output_data = parse_llm_response(response)
223
+ try:
224
+ output_data = parse_llm_response(response)
225
+ except json.JSONDecodeError as e:
226
+ return {
227
+ "ok": False,
228
+ "error": {"code": "PARSE_ERROR", "message": f"Failed to parse JSON: {e}"},
229
+ "partial_data": None
230
+ }
133
231
 
134
- # Validate output
135
- if validate_output and module["output_schema"]:
136
- errors = validate_data(output_data, module["output_schema"], "Output")
232
+ # Handle envelope format
233
+ if is_envelope_response(output_data):
234
+ result = parse_envelope_response(output_data)
235
+ else:
236
+ # Convert legacy format to envelope
237
+ result = convert_to_envelope(output_data)
238
+
239
+ # Validate output (only for success responses)
240
+ if result["ok"] and validate_output and module["output_schema"]:
241
+ data_to_validate = result.get("data", {})
242
+ errors = validate_data(data_to_validate, module["output_schema"], "Output")
137
243
  if errors:
138
- raise ValueError(f"Output validation failed: {errors}")
244
+ return {
245
+ "ok": False,
246
+ "error": {"code": "OUTPUT_VALIDATION_ERROR", "message": str(errors)},
247
+ "partial_data": data_to_validate
248
+ }
249
+
250
+ return result
251
+
252
+
253
+ def run_module_legacy(
254
+ name_or_path: str,
255
+ input_data: dict,
256
+ validate_input: bool = True,
257
+ validate_output: bool = True,
258
+ model: Optional[str] = None,
259
+ ) -> dict:
260
+ """
261
+ Run a cognitive module (legacy API, returns raw output).
262
+ For backward compatibility.
263
+ """
264
+ result = run_module(
265
+ name_or_path,
266
+ input_data,
267
+ validate_input=validate_input,
268
+ validate_output=validate_output,
269
+ model=model,
270
+ use_envelope=False
271
+ )
139
272
 
140
- return output_data
273
+ if result["ok"]:
274
+ return result["data"]
275
+ else:
276
+ raise ValueError(f"{result['error']['code']}: {result['error']['message']}")
cognitive/templates.py CHANGED
@@ -83,7 +83,7 @@ EXAMPLE_OUTPUT = {
83
83
  def get_schema_template(name: str) -> dict:
84
84
  """Generate schema template as dict."""
85
85
  return {
86
- "$schema": "https://cognitive-modules.io/schema/v1",
86
+ "$schema": "https://ziel-io.github.io/cognitive-modules/schema/v1.json",
87
87
  "$id": name,
88
88
  "title": f"{name.replace('-', ' ').title()} Schema",
89
89
  "input": {
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cognitive-modules
3
- Version: 0.1.1
3
+ Version: 0.3.0
4
4
  Summary: Structured LLM task runner with schema validation, confidence scoring, and subagent orchestration
5
5
  Author: ziel-io
6
6
  License: MIT
@@ -151,6 +151,7 @@ cog doctor
151
151
  | 模块 | 功能 | 示例 |
152
152
  |------|------|------|
153
153
  | `code-reviewer` | 代码审查 | `cog run code-reviewer --args "你的代码"` |
154
+ | `code-simplifier` | 代码简化 | `cog run code-simplifier --args "复杂代码"` |
154
155
  | `task-prioritizer` | 任务优先级排序 | `cog run task-prioritizer --args "任务1,任务2"` |
155
156
  | `api-designer` | REST API 设计 | `cog run api-designer --args "订单系统"` |
156
157
  | `ui-spec-generator` | UI 规范生成 | `cog run ui-spec-generator --args "电商首页"` |
@@ -241,6 +242,134 @@ export LLM_PROVIDER=ollama
241
242
  cog doctor
242
243
  ```
243
244
 
245
+ ## 创建新模块(完整流程)
246
+
247
+ 以 `code-simplifier` 为例:
248
+
249
+ ### Step 1: 创建目录结构
250
+
251
+ ```bash
252
+ mkdir -p cognitive/modules/code-simplifier
253
+ ```
254
+
255
+ ### Step 2: 编写 MODULE.md
256
+
257
+ ```bash
258
+ cat > cognitive/modules/code-simplifier/MODULE.md << 'EOF'
259
+ ---
260
+ name: code-simplifier
261
+ version: 1.0.0
262
+ responsibility: Simplify complex code while preserving functionality
263
+
264
+ excludes:
265
+ - Changing the code's behavior
266
+ - Adding new features
267
+ - Removing functionality
268
+
269
+ constraints:
270
+ no_network: true
271
+ no_side_effects: true
272
+ require_confidence: true
273
+ require_rationale: true
274
+ ---
275
+
276
+ # Code Simplifier Module
277
+
278
+ You are an expert at refactoring and simplifying code.
279
+
280
+ ## Input
281
+
282
+ Code to simplify: $ARGUMENTS
283
+
284
+ ## Simplification Strategies
285
+
286
+ 1. **Remove redundancy** - Eliminate duplicate code
287
+ 2. **Improve naming** - Use clear, descriptive names
288
+ 3. **Reduce nesting** - Flatten deep conditionals
289
+ 4. **Simplify logic** - Use built-in functions
290
+
291
+ ## Output Requirements
292
+
293
+ Return JSON containing:
294
+ - `simplified_code`: The simplified version
295
+ - `changes`: List of changes made
296
+ - `summary`: Brief description
297
+ - `rationale`: Explanation of decisions
298
+ - `confidence`: Confidence score [0-1]
299
+ EOF
300
+ ```
301
+
302
+ ### Step 3: 编写 schema.json
303
+
304
+ ```bash
305
+ cat > cognitive/modules/code-simplifier/schema.json << 'EOF'
306
+ {
307
+ "$schema": "https://ziel-io.github.io/cognitive-modules/schema/v1.json",
308
+ "input": {
309
+ "type": "object",
310
+ "properties": {
311
+ "code": { "type": "string" },
312
+ "language": { "type": "string" },
313
+ "$ARGUMENTS": { "type": "string" }
314
+ }
315
+ },
316
+ "output": {
317
+ "type": "object",
318
+ "required": ["simplified_code", "changes", "summary", "rationale", "confidence"],
319
+ "properties": {
320
+ "simplified_code": { "type": "string" },
321
+ "changes": {
322
+ "type": "array",
323
+ "items": {
324
+ "type": "object",
325
+ "properties": {
326
+ "type": { "type": "string" },
327
+ "description": { "type": "string" }
328
+ }
329
+ }
330
+ },
331
+ "summary": { "type": "string" },
332
+ "rationale": { "type": "string" },
333
+ "confidence": { "type": "number", "minimum": 0, "maximum": 1 }
334
+ }
335
+ }
336
+ }
337
+ EOF
338
+ ```
339
+
340
+ ### Step 4: 验证模块
341
+
342
+ ```bash
343
+ cog validate code-simplifier
344
+ cog list # 确认模块出现在列表中
345
+ ```
346
+
347
+ ### Step 5: 测试运行
348
+
349
+ ```bash
350
+ cog run code-simplifier --args "def calc(x): if x > 0: if x < 10: return x * 2 else: return x else: return 0" --pretty
351
+ ```
352
+
353
+ ### Step 6: 添加示例(可选)
354
+
355
+ ```bash
356
+ mkdir -p cognitive/modules/code-simplifier/examples
357
+ # 添加 input.json 和 output.json 作为测试用例
358
+ ```
359
+
360
+ ### 模块设计要点
361
+
362
+ | 要素 | 必须 | 说明 |
363
+ |------|------|------|
364
+ | `name` | ✅ | 唯一标识符,kebab-case |
365
+ | `version` | ✅ | 语义化版本 |
366
+ | `responsibility` | ✅ | 一句话描述职责 |
367
+ | `excludes` | ✅ | 明确列出不做的事 |
368
+ | `$ARGUMENTS` | ✅ | 支持命令行参数 |
369
+ | `confidence` | ✅ | 输出必须包含 0-1 置信度 |
370
+ | `rationale` | ✅ | 输出必须包含推理过程 |
371
+ | `schema.json` | ✅ | 定义输入输出契约 |
372
+
244
373
  ## 开发
245
374
 
246
375
  ```bash
@@ -254,7 +383,7 @@ pip install -e ".[dev]"
254
383
  # 运行测试
255
384
  pytest tests/ -v
256
385
 
257
- # 创建新模块
386
+ # 创建新模块(使用模板)
258
387
  cog init my-module -d "模块描述"
259
388
  cog validate my-module
260
389
  ```
@@ -0,0 +1,15 @@
1
+ cognitive/__init__.py,sha256=uSX5NuOWyW0qtq1bnxbzabZ0OQakAtsjF0MWbjQBvwE,401
2
+ cognitive/cli.py,sha256=q0vHCHFmig9gQ85KRyIrX6vrJZFm5nXF_bW5qQRGEPU,14608
3
+ cognitive/loader.py,sha256=3_ShEfefOMP2EJjpQ1VGTGio4K_GUWLZMQHa0RgvBwg,8715
4
+ cognitive/registry.py,sha256=aBkkpg5PtL_tKDIOXpv6vblB7x_Ax0eVaWgejuQTfCE,8851
5
+ cognitive/runner.py,sha256=KFO_pV7YTluYaL98_5bPp_HTNgwsTvlUjgNYlI8mo-w,8467
6
+ cognitive/subagent.py,sha256=fb7LWwNF6YcJtC_T1dK0EvzqWMBnav-kiCIpvVohEBw,8142
7
+ cognitive/templates.py,sha256=lKC197X9aQIA-npUvVCaplSwvhxjsH_KYVCQtrTZrL4,4712
8
+ cognitive/validator.py,sha256=1v1HUHYOlAc2sYCkIq_gnUMMnca0fdtQwr7UMBFpp04,12200
9
+ cognitive/providers/__init__.py,sha256=hqhVA1IEXpVtyCAteXhO5yD8a8ikQpVIPEKJVHLtRFY,7492
10
+ cognitive_modules-0.3.0.dist-info/licenses/LICENSE,sha256=NXFYUy2hPJdh3NHRxMChTnMiQD9k8zFxkmR7gWefexc,1064
11
+ cognitive_modules-0.3.0.dist-info/METADATA,sha256=PcUIJeGz7wr78MHPEdmDRxqKuFLEzX5aEgpMRHfGN-w,11381
12
+ cognitive_modules-0.3.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
13
+ cognitive_modules-0.3.0.dist-info/entry_points.txt,sha256=PKHlfrFmve5K2349ryipySKbOOsKxo_vIq1NNT-iBV0,42
14
+ cognitive_modules-0.3.0.dist-info/top_level.txt,sha256=kGIfDucCKylo8cRBtxER_v3DHIea-Sol9x9YSJo1u3Y,10
15
+ cognitive_modules-0.3.0.dist-info/RECORD,,
@@ -1,15 +0,0 @@
1
- cognitive/__init__.py,sha256=uSX5NuOWyW0qtq1bnxbzabZ0OQakAtsjF0MWbjQBvwE,401
2
- cognitive/cli.py,sha256=q0vHCHFmig9gQ85KRyIrX6vrJZFm5nXF_bW5qQRGEPU,14608
3
- cognitive/loader.py,sha256=E_lSuy2ERBWfziOHr3f13nLq-wEYvBqIKrGlPk4PQyA,4031
4
- cognitive/registry.py,sha256=aBkkpg5PtL_tKDIOXpv6vblB7x_Ax0eVaWgejuQTfCE,8851
5
- cognitive/runner.py,sha256=9uxBAGd3gtXnwUm5x2CjhXi_S1gd2nfjRfM3Q_1f30Q,4362
6
- cognitive/subagent.py,sha256=fb7LWwNF6YcJtC_T1dK0EvzqWMBnav-kiCIpvVohEBw,8142
7
- cognitive/templates.py,sha256=fEd1Tj5A12PUE256dC7-cnsulWzm6MTrcQ0yLPWrtx0,4692
8
- cognitive/validator.py,sha256=1v1HUHYOlAc2sYCkIq_gnUMMnca0fdtQwr7UMBFpp04,12200
9
- cognitive/providers/__init__.py,sha256=hqhVA1IEXpVtyCAteXhO5yD8a8ikQpVIPEKJVHLtRFY,7492
10
- cognitive_modules-0.1.1.dist-info/licenses/LICENSE,sha256=NXFYUy2hPJdh3NHRxMChTnMiQD9k8zFxkmR7gWefexc,1064
11
- cognitive_modules-0.1.1.dist-info/METADATA,sha256=oonLUUD0fO3t7bo8DVZKlqC1vM5ZyHFUw7KXP46SLdI,8242
12
- cognitive_modules-0.1.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
13
- cognitive_modules-0.1.1.dist-info/entry_points.txt,sha256=PKHlfrFmve5K2349ryipySKbOOsKxo_vIq1NNT-iBV0,42
14
- cognitive_modules-0.1.1.dist-info/top_level.txt,sha256=kGIfDucCKylo8cRBtxER_v3DHIea-Sol9x9YSJo1u3Y,10
15
- cognitive_modules-0.1.1.dist-info/RECORD,,