cortx 1.0.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.
@@ -0,0 +1,11 @@
1
+ """
2
+ Cortex Agent — Python Package
3
+ ══════════════════════════════════
4
+
5
+ Harness Agent 架构 + Agentic Loop 运行时
6
+ """
7
+
8
+ from .cortex_agent import CortexAgent, AgentConfig, LLMProvider, registry
9
+ from .policy import PolicyEngine
10
+
11
+ __version__ = '1.0.0'
cortex_agent/config.py ADDED
@@ -0,0 +1,163 @@
1
+ """
2
+ 配置加载器 — 从 settings.json 读取配置,合并到 AgentConfig
3
+
4
+ 加载优先级(从低到高):
5
+ 1. 代码默认值 (AgentConfig dataclass defaults)
6
+ 2. settings.json(项目级: {cwd}/.cortex/settings.json)
7
+ 3. settings.json(用户级: ~/.cortex/settings.json)
8
+ 4. 环境变量 (CORTEX_API_KEY, CORTEX_MODEL, etc.)
9
+ 5. CLI 参数
10
+
11
+ settings.json 结构:
12
+ {
13
+ "model": "flash",
14
+ "provider": "deepseek",
15
+ "providers": {
16
+ "deepseek": {
17
+ "api_key": "sk-...",
18
+ "base_url": "https://api.deepseek.com/v1",
19
+ "models": { "flash": "deepseek-v4-flash", "pro": "deepseek-v4-pro" }
20
+ },
21
+ "openai": {
22
+ "api_key": "sk-...",
23
+ "base_url": "https://api.openai.com/v1",
24
+ "models": { "gpt4": "gpt-4o", "gpt4m": "gpt-4o-mini" }
25
+ }
26
+ },
27
+ "max_steps": 10,
28
+ "work_dir": "./cortex_workspace",
29
+ "loop_timeout": 120,
30
+ "think_timeout": 60,
31
+ "auto_extract_memory": true,
32
+ "memory_enabled": true,
33
+ "sessions_enabled": true
34
+ }
35
+ """
36
+
37
+ import os, json
38
+ from typing import Optional
39
+
40
+
41
+ def _find_upwards(filename: str, start: str = None) -> Optional[str]:
42
+ """从 start 向上搜索 filename,返回完整路径或 None。"""
43
+ d = os.path.abspath(start or os.getcwd())
44
+ while True:
45
+ candidate = os.path.join(d, filename)
46
+ if os.path.isfile(candidate):
47
+ return candidate
48
+ parent = os.path.dirname(d)
49
+ if parent == d:
50
+ return None
51
+ d = parent
52
+
53
+
54
+ def load_settings(project_dir: str = None) -> dict:
55
+ """加载合并后的设置字典。用户级覆盖项目级。"""
56
+ merged = {}
57
+
58
+ # 1. 项目级
59
+ proj = _find_upwards(".cortex/settings.json", project_dir or os.getcwd())
60
+ if proj:
61
+ try:
62
+ with open(proj, "r", encoding="utf-8") as f:
63
+ merged.update(json.load(f))
64
+ except Exception:
65
+ pass
66
+
67
+ # 2. 用户级 (~)
68
+ user = os.path.join(os.path.expanduser("~"), ".cortex", "settings.json")
69
+ if os.path.isfile(user):
70
+ try:
71
+ with open(user, "r", encoding="utf-8") as f:
72
+ merged.update(json.load(f))
73
+ except Exception:
74
+ pass
75
+
76
+ # 3. 环境变量覆盖
77
+ if os.environ.get("CORTEX_API_KEY"):
78
+ merged.setdefault("providers", {})
79
+ provider = merged.get("provider", "deepseek")
80
+ merged["providers"].setdefault(provider, {})
81
+ merged["providers"][provider]["api_key"] = os.environ["CORTEX_API_KEY"]
82
+ if os.environ.get("CORTEX_MODEL"):
83
+ merged["model"] = os.environ["CORTEX_MODEL"]
84
+
85
+ return merged
86
+
87
+
88
+ def apply_to_config(config, settings: dict):
89
+ """将 settings dict 应用到 AgentConfig 对象。"""
90
+ from .cortex_agent import LLMProvider
91
+
92
+ # Provider 注册
93
+ LLMProvider.setup(
94
+ providers=settings.get("providers"),
95
+ active=settings.get("provider", "deepseek"),
96
+ )
97
+
98
+ # API key:先取当前 provider 的 api_key,再取 settings 顶层,再取 config 已有值
99
+ active_provider = LLMProvider.provider_name()
100
+ providers = settings.get("providers", {})
101
+ provider_cfg = providers.get(active_provider, {})
102
+ api_key = provider_cfg.get("api_key", "") or settings.get("api_key", "") or config.api_key
103
+ config.api_key = api_key
104
+
105
+ # 简单字段
106
+ for key in ("model", "max_steps", "tool_timeout", "system_prompt",
107
+ "max_context_msgs", "loop_timeout", "think_timeout",
108
+ "work_dir", "memory_dir", "sessions_dir", "skills_dir",
109
+ "memory_enabled", "sessions_enabled", "auto_extract_memory",
110
+ "permission_mode", "permission_remember", "workspace_only",
111
+ "context_limit"):
112
+ if key in settings:
113
+ setattr(config, key, settings[key])
114
+
115
+
116
+ def create_default_settings(path: str) -> dict:
117
+ """在 path 路径创建默认 settings.json。返回写入的 dict。"""
118
+ default = {
119
+ "model": "pro",
120
+ "provider": "deepseek",
121
+ "providers": {
122
+ "deepseek": {
123
+ "api_key": "",
124
+ "base_url": "https://api.deepseek.com/v1",
125
+ "models": {"flash": "deepseek-v4-flash", "pro": "deepseek-v4-pro"},
126
+ }
127
+ },
128
+ "max_steps": 10,
129
+ "loop_timeout": 120,
130
+ "think_timeout": 60,
131
+ "auto_extract_memory": True,
132
+ "memory_enabled": True,
133
+ "sessions_enabled": True,
134
+ "permission_mode": "standard",
135
+ "permission_remember": True,
136
+ "workspace_only": False,
137
+ "context_limit": 1000000,
138
+ "mcpServers": {
139
+ "playwright": {
140
+ "command": "npx",
141
+ "args": ["-y", "@playwright/mcp@latest"],
142
+ "description": "浏览器自动化(Microsoft 官方)"
143
+ },
144
+ "fetch": {
145
+ "command": "python",
146
+ "args": ["-m", "mcp_server_fetch"],
147
+ "description": "HTTP 抓取 + HTML→Markdown"
148
+ },
149
+ "sqlite": {
150
+ "command": "npx",
151
+ "args": ["-y", "@modelcontextprotocol/server-sqlite"],
152
+ "description": "SQLite 数据库查询"
153
+ },
154
+ "context7": {
155
+ "url": "https://mcp.context7.com/mcp",
156
+ "description": "实时库/框架文档查询"
157
+ }
158
+ }
159
+ }
160
+ os.makedirs(os.path.dirname(path), exist_ok=True)
161
+ with open(path, "w", encoding="utf-8") as f:
162
+ json.dump(default, f, ensure_ascii=False, indent=2)
163
+ return default