bone-agent 1.4.0 → 2.0.0
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.
- package/bin/bone.js +39 -0
- package/package.json +25 -39
- package/LICENSE +0 -21
- package/README.md +0 -201
- package/bin/npm-wrapper.js +0 -235
- package/bin/rg +0 -0
- package/bin/rg.exe +0 -0
- package/config.yaml.example +0 -144
- package/prompts/main/ask_questions.md +0 -31
- package/prompts/main/batch_independent_calls.md +0 -5
- package/prompts/main/casual_interactions.md +0 -11
- package/prompts/main/code_references.md +0 -8
- package/prompts/main/communication_style.md +0 -12
- package/prompts/main/context_reliability.md +0 -12
- package/prompts/main/conversational_tool_calling.md +0 -15
- package/prompts/main/dream.md +0 -50
- package/prompts/main/editing_pattern.md +0 -13
- package/prompts/main/error_handling.md +0 -6
- package/prompts/main/exploration_pattern.md +0 -21
- package/prompts/main/intro.md +0 -1
- package/prompts/main/obsidian.md +0 -16
- package/prompts/main/obsidian_project.md +0 -79
- package/prompts/main/professional_objectivity.md +0 -3
- package/prompts/main/skills.md +0 -3
- package/prompts/main/targeted_searching.md +0 -10
- package/prompts/main/task_lists_pattern.md +0 -8
- package/prompts/main/temp_folder.md +0 -9
- package/prompts/main/think_before_acting.md +0 -10
- package/prompts/main/tone_and_style.md +0 -4
- package/prompts/main/tool_preferences.md +0 -24
- package/prompts/main/trust_subagent_context.md +0 -21
- package/prompts/main/when_to_use_sub_agent.md +0 -7
- package/prompts/micro/ask_questions.md +0 -1
- package/prompts/micro/batch_independent_calls.md +0 -1
- package/prompts/micro/casual_interactions.md +0 -1
- package/prompts/micro/code_references.md +0 -1
- package/prompts/micro/communication_style.md +0 -1
- package/prompts/micro/context_reliability.md +0 -1
- package/prompts/micro/conversational_tool_calling.md +0 -1
- package/prompts/micro/editing_pattern.md +0 -1
- package/prompts/micro/error_handling.md +0 -1
- package/prompts/micro/exploration_pattern.md +0 -1
- package/prompts/micro/intro.md +0 -1
- package/prompts/micro/obsidian.md +0 -4
- package/prompts/micro/obsidian_project.md +0 -5
- package/prompts/micro/professional_objectivity.md +0 -1
- package/prompts/micro/skills.md +0 -1
- package/prompts/micro/targeted_searching.md +0 -1
- package/prompts/micro/task_lists_pattern.md +0 -1
- package/prompts/micro/temp_folder.md +0 -1
- package/prompts/micro/think_before_acting.md +0 -5
- package/prompts/micro/tone_and_style.md +0 -1
- package/prompts/micro/tool_preferences.md +0 -1
- package/prompts/micro/trust_subagent_context.md +0 -1
- package/prompts/micro/when_to_use_sub_agent.md +0 -1
- package/requirements.txt +0 -9
- package/src/__init__.py +0 -11
- package/src/core/__init__.py +0 -1
- package/src/core/agentic.py +0 -1085
- package/src/core/chat_manager.py +0 -1577
- package/src/core/config_manager.py +0 -260
- package/src/core/cron.py +0 -578
- package/src/core/cron_allowlist.py +0 -118
- package/src/core/memory.py +0 -145
- package/src/core/metadata.py +0 -75
- package/src/core/retry.py +0 -71
- package/src/core/skills.py +0 -463
- package/src/core/sub_agent.py +0 -376
- package/src/core/tool_approval.py +0 -220
- package/src/core/tool_feedback.py +0 -789
- package/src/exceptions.py +0 -79
- package/src/llm/__init__.py +0 -1
- package/src/llm/client.py +0 -176
- package/src/llm/codex_provider.py +0 -350
- package/src/llm/config.py +0 -536
- package/src/llm/prompts.py +0 -494
- package/src/llm/providers.py +0 -438
- package/src/llm/streaming.py +0 -163
- package/src/llm/token_tracker.py +0 -399
- package/src/tools/__init__.py +0 -151
- package/src/tools/constants.py +0 -59
- package/src/tools/create_file.py +0 -136
- package/src/tools/directory.py +0 -389
- package/src/tools/edit.py +0 -549
- package/src/tools/file_reader.py +0 -322
- package/src/tools/helpers/__init__.py +0 -99
- package/src/tools/helpers/base.py +0 -599
- package/src/tools/helpers/converters.py +0 -44
- package/src/tools/helpers/file_helpers.py +0 -189
- package/src/tools/helpers/formatters.py +0 -411
- package/src/tools/helpers/loader.py +0 -145
- package/src/tools/helpers/parallel_executor.py +0 -231
- package/src/tools/helpers/path_resolver.py +0 -283
- package/src/tools/helpers/plugin_manifest.py +0 -185
- package/src/tools/obsidian.py +0 -96
- package/src/tools/review_sub_agent.py +0 -190
- package/src/tools/rg_search.py +0 -477
- package/src/tools/search_plugins.py +0 -177
- package/src/tools/select_option.py +0 -600
- package/src/tools/shell.py +0 -302
- package/src/tools/sub_agent.py +0 -139
- package/src/tools/task_list.py +0 -269
- package/src/tools/web_search.py +0 -61
- package/src/ui/__init__.py +0 -1
- package/src/ui/banner.py +0 -87
- package/src/ui/commands.py +0 -3131
- package/src/ui/displays.py +0 -239
- package/src/ui/loader.py +0 -284
- package/src/ui/main.py +0 -643
- package/src/ui/prompt_utils.py +0 -113
- package/src/ui/setting_selector.py +0 -590
- package/src/ui/setup_wizard.py +0 -294
- package/src/ui/sub_agent_panel.py +0 -234
- package/src/ui/tool_confirmation.py +0 -226
- package/src/utils/__init__.py +0 -1
- package/src/utils/citation_parser.py +0 -199
- package/src/utils/editor.py +0 -207
- package/src/utils/gitignore_filter.py +0 -149
- package/src/utils/logger.py +0 -254
- package/src/utils/paths.py +0 -30
- package/src/utils/result_parsers.py +0 -108
- package/src/utils/safe_commands.py +0 -243
- package/src/utils/settings.py +0 -195
- package/src/utils/user_message_logger.py +0 -120
- package/src/utils/validation.py +0 -201
- package/src/utils/web_search.py +0 -173
package/src/llm/config.py
DELETED
|
@@ -1,536 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import platform
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
import yaml
|
|
5
|
-
|
|
6
|
-
# Provider selection - loaded from config (see after PROVIDER_REGISTRY definition)
|
|
7
|
-
|
|
8
|
-
def resolve_config_path() -> Path:
|
|
9
|
-
"""Resolve config.yaml path.
|
|
10
|
-
|
|
11
|
-
Resolution order:
|
|
12
|
-
1. BONE_CONFIG_PATH — explicit user config path (set by npm wrapper)
|
|
13
|
-
2. ~/.bone/config.yaml — user home dotfile (dev and npm installs)
|
|
14
|
-
"""
|
|
15
|
-
_user_cfg = os.environ.get('BONE_CONFIG_PATH')
|
|
16
|
-
if _user_cfg:
|
|
17
|
-
return Path(_user_cfg).resolve()
|
|
18
|
-
return Path.home() / '.bone' / 'config.yaml'
|
|
19
|
-
|
|
20
|
-
# Module-level config path (single source of truth)
|
|
21
|
-
CONFIG_PATH = resolve_config_path()
|
|
22
|
-
|
|
23
|
-
# Environment variable names for API keys (env vars take precedence over config file)
|
|
24
|
-
ENV_API_KEYS = {
|
|
25
|
-
'ANTHROPIC_API_KEY': os.environ.get('ANTHROPIC_API_KEY'),
|
|
26
|
-
'OPENAI_API_KEY': os.environ.get('OPENAI_API_KEY'),
|
|
27
|
-
'GLM_PLAN_API_KEY': os.environ.get('GLM_PLAN_API_KEY'),
|
|
28
|
-
'GLM_API_KEY': os.environ.get('GLM_API_KEY'),
|
|
29
|
-
'GEMINI_API_KEY': os.environ.get('GEMINI_API_KEY'),
|
|
30
|
-
'OPENROUTER_API_KEY': os.environ.get('OPENROUTER_API_KEY'),
|
|
31
|
-
'KIMI_API_KEY': os.environ.get('KIMI_API_KEY'),
|
|
32
|
-
'MINIMAX_PLAN_API_KEY': os.environ.get('MINIMAX_PLAN_API_KEY'),
|
|
33
|
-
'MINIMAX_API_KEY': os.environ.get('MINIMAX_API_KEY'),
|
|
34
|
-
'BONE_PROXY_API_KEY': os.environ.get('BONE_PROXY_API_KEY'),
|
|
35
|
-
'CODEX_PLAN_API_KEY': os.environ.get('CODEX_PLAN_API_KEY'),
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
# Detect platform for llama.cpp paths
|
|
39
|
-
_IS_WINDOWS = platform.system() == "Windows"
|
|
40
|
-
_IS_LINUX = platform.system() == "Linux"
|
|
41
|
-
|
|
42
|
-
# Set llama.cpp paths based on platform
|
|
43
|
-
if _IS_WINDOWS:
|
|
44
|
-
_LLAMA_SERVER_NAME = "llama-server.exe"
|
|
45
|
-
_LLAMA_BUILD_DIR = "build"
|
|
46
|
-
elif _IS_LINUX:
|
|
47
|
-
_LLAMA_SERVER_NAME = "llama-server"
|
|
48
|
-
_LLAMA_BUILD_DIR = "build-linux"
|
|
49
|
-
else:
|
|
50
|
-
# Fallback for macOS or other platforms
|
|
51
|
-
_LLAMA_SERVER_NAME = "llama-server"
|
|
52
|
-
_LLAMA_BUILD_DIR = "build"
|
|
53
|
-
|
|
54
|
-
def _load_config():
|
|
55
|
-
"""Load config from YAML file, with environment variable overrides for API keys.
|
|
56
|
-
|
|
57
|
-
Environment variables take precedence over values in config.yaml.
|
|
58
|
-
"""
|
|
59
|
-
config_path = resolve_config_path()
|
|
60
|
-
if not config_path.exists():
|
|
61
|
-
return {}
|
|
62
|
-
try:
|
|
63
|
-
config = yaml.safe_load(config_path.read_text(encoding="utf-8-sig")) or {}
|
|
64
|
-
except yaml.YAMLError:
|
|
65
|
-
config = {}
|
|
66
|
-
|
|
67
|
-
# Override API keys from environment variables (env vars take precedence)
|
|
68
|
-
for key, env_value in ENV_API_KEYS.items():
|
|
69
|
-
if env_value: # Only override if env var is set and non-empty
|
|
70
|
-
config[key] = env_value
|
|
71
|
-
|
|
72
|
-
return config
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
_CONFIG = _load_config()
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
def _get_codex_token() -> str:
|
|
79
|
-
"""Read access token from Codex CLI's cached auth (~/.codex/auth.json).
|
|
80
|
-
|
|
81
|
-
Returns the access_token if available, empty string otherwise.
|
|
82
|
-
Codex CLI stores OAuth tokens here after `codex login`.
|
|
83
|
-
"""
|
|
84
|
-
try:
|
|
85
|
-
auth_path = Path.home() / ".codex" / "auth.json"
|
|
86
|
-
if not auth_path.exists():
|
|
87
|
-
return ""
|
|
88
|
-
import json
|
|
89
|
-
data = json.loads(auth_path.read_text(encoding="utf-8"))
|
|
90
|
-
return data.get("tokens", {}).get("access_token", "")
|
|
91
|
-
except Exception:
|
|
92
|
-
return ""
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
# Cache for provider registry (built once at module load)
|
|
96
|
-
_provider_registry_cache = None
|
|
97
|
-
_cached_provider = None
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
def get_model_cost(model_name: str, config: dict | None = None) -> tuple[float, float]:
|
|
101
|
-
"""Get model-specific (cost_in, cost_out) per 1M tokens from MODEL_PRICES.
|
|
102
|
-
|
|
103
|
-
Shared utility — used by both the provider registry builder and config_manager.
|
|
104
|
-
Returns (0.0, 0.0) for unknown models.
|
|
105
|
-
|
|
106
|
-
Args:
|
|
107
|
-
model_name: Model name to look up.
|
|
108
|
-
config: Optional config dict (defaults to _CONFIG). Pass a fresh config
|
|
109
|
-
after runtime edits to get up-to-date pricing.
|
|
110
|
-
"""
|
|
111
|
-
model_prices = (config if config is not None else _CONFIG).get("MODEL_PRICES", {})
|
|
112
|
-
if model_name in model_prices:
|
|
113
|
-
mc = model_prices[model_name]
|
|
114
|
-
return float(mc.get("cost_in", 0.0)), float(mc.get("cost_out", 0.0))
|
|
115
|
-
return 0.0, 0.0
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
def _model_cost(model_config_key):
|
|
119
|
-
"""Return {cost_in, cost_out} dict for use in provider registry via **spread.
|
|
120
|
-
|
|
121
|
-
Reads from module-level _CONFIG (not an injected config). Safe because
|
|
122
|
-
reload_config() invalidates the provider registry cache, forcing a rebuild.
|
|
123
|
-
"""
|
|
124
|
-
ci, co = get_model_cost(_CONFIG.get(model_config_key, ""))
|
|
125
|
-
return {"cost_in": ci, "cost_out": co}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
def _get_provider_registry():
|
|
129
|
-
"""Build PROVIDER_REGISTRY from current config (cached)."""
|
|
130
|
-
global _provider_registry_cache
|
|
131
|
-
if _provider_registry_cache is not None:
|
|
132
|
-
return _provider_registry_cache
|
|
133
|
-
|
|
134
|
-
_provider_registry_cache = {
|
|
135
|
-
"local": {
|
|
136
|
-
"type": "local",
|
|
137
|
-
"api_key": None,
|
|
138
|
-
"model": _CONFIG.get("LOCAL_MODEL_PATH", ""),
|
|
139
|
-
"api_model": "model",
|
|
140
|
-
"api_base": "http://127.0.0.1:8080",
|
|
141
|
-
"endpoint": "/v1/chat/completions",
|
|
142
|
-
"error_prefix": "local server",
|
|
143
|
-
"config_keys": {
|
|
144
|
-
"LOCAL_MODEL_PATH": "",
|
|
145
|
-
"LOCAL_SERVER_PATH": str(
|
|
146
|
-
Path(__file__).resolve().parents[2] /
|
|
147
|
-
f"llama.cpp/{_LLAMA_BUILD_DIR}/bin/{_LLAMA_SERVER_NAME}"
|
|
148
|
-
),
|
|
149
|
-
},
|
|
150
|
-
"extra": {
|
|
151
|
-
"host": "127.0.0.1",
|
|
152
|
-
"port": 8080,
|
|
153
|
-
},
|
|
154
|
-
"default_temperature": 0.1,
|
|
155
|
-
"default_top_p": 0.9,
|
|
156
|
-
"allow_top_p": False,
|
|
157
|
-
"allow_temperature": False,
|
|
158
|
-
"cost_in": 0.0,
|
|
159
|
-
"cost_out": 0.0
|
|
160
|
-
},
|
|
161
|
-
"openrouter": {
|
|
162
|
-
"type": "api",
|
|
163
|
-
"api_key": _CONFIG.get("OPENROUTER_API_KEY", ""),
|
|
164
|
-
"model": _CONFIG.get("OPENROUTER_MODEL", ""),
|
|
165
|
-
"api_base": _CONFIG.get("OPENROUTER_API_BASE", "https://openrouter.ai/api/v1"),
|
|
166
|
-
"endpoint": "/chat/completions",
|
|
167
|
-
"error_prefix": "OpenRouter",
|
|
168
|
-
"headers_extra": {
|
|
169
|
-
"HTTP-Referer": "http://localhost:8080",
|
|
170
|
-
"X-Title": "Chat App"
|
|
171
|
-
},
|
|
172
|
-
"config_keys": {
|
|
173
|
-
"OPENROUTER_API_KEY": "",
|
|
174
|
-
"OPENROUTER_MODEL": "",
|
|
175
|
-
"OPENROUTER_API_BASE": "https://openrouter.ai/api/v1",
|
|
176
|
-
},
|
|
177
|
-
"default_temperature": 0.1,
|
|
178
|
-
"default_top_p": 0.9,
|
|
179
|
-
"allow_top_p": True,
|
|
180
|
-
"allow_temperature": True,
|
|
181
|
-
**_model_cost("OPENROUTER_MODEL"),
|
|
182
|
-
},
|
|
183
|
-
"glm_plan": {
|
|
184
|
-
"type": "api",
|
|
185
|
-
"api_key": _CONFIG.get("GLM_PLAN_API_KEY", ""),
|
|
186
|
-
"model": _CONFIG.get("GLM_PLAN_MODEL", ""),
|
|
187
|
-
"api_base": _CONFIG.get("GLM_PLAN_API_BASE", "https://open.bigmodel.cn/api/paas/v4"),
|
|
188
|
-
"endpoint": "/chat/completions",
|
|
189
|
-
"error_prefix": "GLM",
|
|
190
|
-
"config_keys": {
|
|
191
|
-
"GLM_PLAN_API_KEY": "",
|
|
192
|
-
"GLM_PLAN_MODEL": "",
|
|
193
|
-
"GLM_PLAN_API_BASE": "https://open.bigmodel.cn/api/paas/v4",
|
|
194
|
-
},
|
|
195
|
-
"default_temperature": 0.1,
|
|
196
|
-
"default_top_p": 0.9,
|
|
197
|
-
"allow_top_p": True,
|
|
198
|
-
"allow_temperature": True,
|
|
199
|
-
**_model_cost("GLM_PLAN_MODEL"),
|
|
200
|
-
},
|
|
201
|
-
"glm": {
|
|
202
|
-
"type": "api",
|
|
203
|
-
"api_key": _CONFIG.get("GLM_API_KEY", ""),
|
|
204
|
-
"model": _CONFIG.get("GLM_MODEL", ""),
|
|
205
|
-
"api_base": _CONFIG.get("GLM_API_BASE", "https://open.bigmodel.cn/api/paas/v4"),
|
|
206
|
-
"endpoint": "/chat/completions",
|
|
207
|
-
"error_prefix": "GLM",
|
|
208
|
-
"config_keys": {
|
|
209
|
-
"GLM_API_KEY": "",
|
|
210
|
-
"GLM_MODEL": "",
|
|
211
|
-
"GLM_API_BASE": "https://open.bigmodel.cn/api/paas/v4",
|
|
212
|
-
},
|
|
213
|
-
"default_temperature": 0.1,
|
|
214
|
-
"default_top_p": 0.9,
|
|
215
|
-
"allow_top_p": True,
|
|
216
|
-
"allow_temperature": True,
|
|
217
|
-
**_model_cost("GLM_MODEL"),
|
|
218
|
-
},
|
|
219
|
-
"openai": {
|
|
220
|
-
"type": "api",
|
|
221
|
-
"api_key": _CONFIG.get("OPENAI_API_KEY", ""),
|
|
222
|
-
"model": _CONFIG.get("OPENAI_MODEL", ""),
|
|
223
|
-
"api_base": _CONFIG.get("OPENAI_API_BASE", "https://api.openai.com/v1"),
|
|
224
|
-
"endpoint": "/chat/completions",
|
|
225
|
-
"error_prefix": "OpenAI",
|
|
226
|
-
"config_keys": {
|
|
227
|
-
"OPENAI_API_KEY": "",
|
|
228
|
-
"OPENAI_MODEL": "",
|
|
229
|
-
"OPENAI_API_BASE": "https://api.openai.com/v1",
|
|
230
|
-
},
|
|
231
|
-
"default_temperature": 0.1,
|
|
232
|
-
"default_top_p": 0.9,
|
|
233
|
-
"allow_top_p": False,
|
|
234
|
-
"allow_temperature": False,
|
|
235
|
-
**_model_cost("OPENAI_MODEL"),
|
|
236
|
-
},
|
|
237
|
-
"gemini": {
|
|
238
|
-
"type": "api",
|
|
239
|
-
"api_key": _CONFIG.get("GEMINI_API_KEY", ""),
|
|
240
|
-
"model": _CONFIG.get("GEMINI_MODEL", ""),
|
|
241
|
-
"api_base": _CONFIG.get("GEMINI_API_BASE", "https://generativelanguage.googleapis.com/v1beta"),
|
|
242
|
-
"endpoint": "/chat/completions",
|
|
243
|
-
"error_prefix": "Gemini",
|
|
244
|
-
"config_keys": {
|
|
245
|
-
"GEMINI_API_KEY": "",
|
|
246
|
-
"GEMINI_MODEL": "",
|
|
247
|
-
"GEMINI_API_BASE": "https://generativelanguage.googleapis.com/v1beta",
|
|
248
|
-
},
|
|
249
|
-
"default_temperature": 0.1,
|
|
250
|
-
"default_top_p": 0.9,
|
|
251
|
-
"allow_top_p": True,
|
|
252
|
-
"allow_temperature": True,
|
|
253
|
-
**_model_cost("GEMINI_MODEL"),
|
|
254
|
-
},
|
|
255
|
-
"minimax_plan": {
|
|
256
|
-
"type": "api",
|
|
257
|
-
"api_key": _CONFIG.get("MINIMAX_PLAN_API_KEY", ""),
|
|
258
|
-
"model": _CONFIG.get("MINIMAX_PLAN_MODEL", ""),
|
|
259
|
-
"api_base": _CONFIG.get("MINIMAX_PLAN_API_BASE", "https://api.minimax.io/anthropic/v1"),
|
|
260
|
-
"endpoint": "/messages",
|
|
261
|
-
"error_prefix": "MiniMax",
|
|
262
|
-
"config_keys": {
|
|
263
|
-
"MINIMAX_PLAN_API_KEY": "",
|
|
264
|
-
"MINIMAX_PLAN_MODEL": "",
|
|
265
|
-
"MINIMAX_PLAN_API_BASE": "https://api.minimax.io/anthropic/v1",
|
|
266
|
-
},
|
|
267
|
-
"default_temperature": 0.1,
|
|
268
|
-
"default_top_p": 0.9,
|
|
269
|
-
"allow_top_p": False,
|
|
270
|
-
"allow_temperature": True,
|
|
271
|
-
"max_tokens": 4096,
|
|
272
|
-
**_model_cost("MINIMAX_PLAN_MODEL"),
|
|
273
|
-
},
|
|
274
|
-
"minimax": {
|
|
275
|
-
"type": "api",
|
|
276
|
-
"api_key": _CONFIG.get("MINIMAX_API_KEY", ""),
|
|
277
|
-
"model": _CONFIG.get("MINIMAX_MODEL", ""),
|
|
278
|
-
"api_base": _CONFIG.get("MINIMAX_API_BASE", "https://api.minimax.io/anthropic/v1"),
|
|
279
|
-
"endpoint": "/messages",
|
|
280
|
-
"error_prefix": "MiniMax",
|
|
281
|
-
"config_keys": {
|
|
282
|
-
"MINIMAX_API_KEY": "",
|
|
283
|
-
"MINIMAX_MODEL": "",
|
|
284
|
-
"MINIMAX_API_BASE": "https://api.minimax.io/anthropic/v1",
|
|
285
|
-
},
|
|
286
|
-
"default_temperature": 0.1,
|
|
287
|
-
"default_top_p": 0.9,
|
|
288
|
-
"allow_top_p": False,
|
|
289
|
-
"allow_temperature": True,
|
|
290
|
-
"max_tokens": 4096,
|
|
291
|
-
**_model_cost("MINIMAX_MODEL"),
|
|
292
|
-
},
|
|
293
|
-
"anthropic": {
|
|
294
|
-
"type": "api",
|
|
295
|
-
"api_key": _CONFIG.get("ANTHROPIC_API_KEY", ""),
|
|
296
|
-
"model": _CONFIG.get("ANTHROPIC_MODEL", ""),
|
|
297
|
-
"api_base": _CONFIG.get("ANTHROPIC_API_BASE", "https://api.anthropic.com/v1"),
|
|
298
|
-
"endpoint": "/messages",
|
|
299
|
-
"error_prefix": "Anthropic",
|
|
300
|
-
"headers_extra": {
|
|
301
|
-
"anthropic-version": "2023-06-01"
|
|
302
|
-
},
|
|
303
|
-
"config_keys": {
|
|
304
|
-
"ANTHROPIC_API_KEY": "",
|
|
305
|
-
"ANTHROPIC_MODEL": "",
|
|
306
|
-
"ANTHROPIC_API_BASE": "https://api.anthropic.com/v1",
|
|
307
|
-
},
|
|
308
|
-
"default_temperature": 0.1,
|
|
309
|
-
"default_top_p": 0.9,
|
|
310
|
-
"allow_top_p": False,
|
|
311
|
-
"allow_temperature": True,
|
|
312
|
-
"max_tokens": 4096,
|
|
313
|
-
**_model_cost("ANTHROPIC_MODEL"),
|
|
314
|
-
},
|
|
315
|
-
"kimi": {
|
|
316
|
-
"type": "api",
|
|
317
|
-
"api_key": _CONFIG.get("KIMI_API_KEY", ""),
|
|
318
|
-
"model": _CONFIG.get("KIMI_MODEL", ""),
|
|
319
|
-
"api_base": _CONFIG.get("KIMI_API_BASE", "https://api.moonshot.cn/v1"),
|
|
320
|
-
"endpoint": "/chat/completions",
|
|
321
|
-
"error_prefix": "Kimi",
|
|
322
|
-
"config_keys": {
|
|
323
|
-
"KIMI_API_KEY": "",
|
|
324
|
-
"KIMI_MODEL": "",
|
|
325
|
-
"KIMI_API_BASE": "https://api.moonshot.cn/v1",
|
|
326
|
-
},
|
|
327
|
-
"default_temperature": 0.1,
|
|
328
|
-
"default_top_p": 0.9,
|
|
329
|
-
"allow_top_p": True,
|
|
330
|
-
"allow_temperature": True,
|
|
331
|
-
**_model_cost("KIMI_MODEL"),
|
|
332
|
-
},
|
|
333
|
-
"codex": {
|
|
334
|
-
"type": "api",
|
|
335
|
-
"api_key": _CONFIG.get("CODEX_PLAN_API_KEY", "") or _get_codex_token(),
|
|
336
|
-
"model": _CONFIG.get("CODEX_PLAN_MODEL", "gpt-5.4-mini"),
|
|
337
|
-
"api_base": _CONFIG.get("CODEX_PLAN_API_BASE", "https://chatgpt.com/backend-api/codex"),
|
|
338
|
-
"endpoint": "/responses",
|
|
339
|
-
"error_prefix": "Codex",
|
|
340
|
-
"config_keys": {
|
|
341
|
-
"CODEX_PLAN_API_KEY": "",
|
|
342
|
-
"CODEX_PLAN_MODEL": "",
|
|
343
|
-
"CODEX_PLAN_API_BASE": "https://chatgpt.com/backend-api/codex",
|
|
344
|
-
},
|
|
345
|
-
"allow_temperature": False,
|
|
346
|
-
"allow_top_p": False,
|
|
347
|
-
**_model_cost("CODEX_PLAN_MODEL"),
|
|
348
|
-
},
|
|
349
|
-
"bone": {
|
|
350
|
-
"type": "api",
|
|
351
|
-
"api_key": _CONFIG.get("BONE_PROXY_API_KEY", ""),
|
|
352
|
-
"model": _CONFIG.get("BONE_PROXY_MODEL", "openai/gpt-4o-mini"),
|
|
353
|
-
"api_base": _CONFIG.get("BONE_PROXY_API_BASE", "https://api.vmcode.dev"),
|
|
354
|
-
"endpoint": "/v1/chat/completions",
|
|
355
|
-
"error_prefix": "bone-agent Proxy",
|
|
356
|
-
"config_keys": {
|
|
357
|
-
"BONE_PROXY_API_KEY": "",
|
|
358
|
-
"BONE_PROXY_MODEL": "openai/gpt-4o-mini",
|
|
359
|
-
"BONE_PROXY_API_BASE": "https://api.vmcode.dev",
|
|
360
|
-
},
|
|
361
|
-
"default_temperature": 0.1,
|
|
362
|
-
"default_top_p": 0.9,
|
|
363
|
-
"allow_top_p": True,
|
|
364
|
-
"allow_temperature": True,
|
|
365
|
-
**_model_cost("BONE_PROXY_MODEL"),
|
|
366
|
-
},
|
|
367
|
-
}
|
|
368
|
-
return _provider_registry_cache
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
def _get_provider():
|
|
372
|
-
"""Get the current provider from config (cached)."""
|
|
373
|
-
global _cached_provider
|
|
374
|
-
if _cached_provider is not None:
|
|
375
|
-
return _cached_provider
|
|
376
|
-
|
|
377
|
-
last_provider = _CONFIG.get("LAST_PROVIDER")
|
|
378
|
-
if last_provider and last_provider in _provider_registry_cache:
|
|
379
|
-
_cached_provider = last_provider
|
|
380
|
-
return _cached_provider
|
|
381
|
-
_cached_provider = "glm_plan"
|
|
382
|
-
return _cached_provider
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
def reload_config():
|
|
386
|
-
"""Reload config from disk and invalidate caches.
|
|
387
|
-
|
|
388
|
-
Reloads both the config.yaml file and environment variables.
|
|
389
|
-
|
|
390
|
-
Note: This is a manual operation - call after config changes.
|
|
391
|
-
"""
|
|
392
|
-
global _CONFIG, _provider_registry_cache, _cached_provider, PROVIDER_REGISTRY, LLM_PROVIDER, STATUS_BAR_SETTINGS, MEMORY_SETTINGS
|
|
393
|
-
_CONFIG = _load_config()
|
|
394
|
-
_provider_registry_cache = None
|
|
395
|
-
_cached_provider = None
|
|
396
|
-
# Rebuild module-level variables
|
|
397
|
-
PROVIDER_REGISTRY = _get_provider_registry()
|
|
398
|
-
LLM_PROVIDER = _get_provider()
|
|
399
|
-
# Rebuild status bar settings
|
|
400
|
-
STATUS_BAR_SETTINGS = _build_status_bar_settings()
|
|
401
|
-
# Rebuild memory settings
|
|
402
|
-
MEMORY_SETTINGS = _build_memory_settings()
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
def _build_status_bar_settings():
|
|
406
|
-
"""Build STATUS_BAR_SETTINGS dict from current _CONFIG."""
|
|
407
|
-
sbs = _CONFIG.get("STATUS_BAR_SETTINGS", {})
|
|
408
|
-
return {
|
|
409
|
-
"show_curr_tokens": sbs.get("show_curr_tokens", True),
|
|
410
|
-
"show_in_tokens": sbs.get("show_in_tokens", True),
|
|
411
|
-
"show_out_tokens": sbs.get("show_out_tokens", True),
|
|
412
|
-
"show_total_tokens": sbs.get("show_total_tokens", True),
|
|
413
|
-
"show_cost": sbs.get("show_cost", True),
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
def _build_memory_settings():
|
|
418
|
-
"""Build MEMORY_SETTINGS dict from current _CONFIG."""
|
|
419
|
-
ms = _CONFIG.get("MEMORY_SETTINGS", {})
|
|
420
|
-
return {
|
|
421
|
-
"enabled": ms.get("enabled", True),
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
def update_memory_settings(settings_dict):
|
|
426
|
-
"""Update MEMORY_SETTINGS at runtime.
|
|
427
|
-
|
|
428
|
-
Returns:
|
|
429
|
-
Updated MEMORY_SETTINGS dict
|
|
430
|
-
"""
|
|
431
|
-
global MEMORY_SETTINGS
|
|
432
|
-
MEMORY_SETTINGS.update(settings_dict)
|
|
433
|
-
return MEMORY_SETTINGS
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
def update_status_bar_settings(settings_dict):
|
|
437
|
-
"""Update STATUS_BAR_SETTINGS at runtime.
|
|
438
|
-
|
|
439
|
-
Args:
|
|
440
|
-
settings_dict: Dict of settings to update (e.g., {"show_cost": False})
|
|
441
|
-
|
|
442
|
-
Returns:
|
|
443
|
-
Updated STATUS_BAR_SETTINGS dict
|
|
444
|
-
"""
|
|
445
|
-
global STATUS_BAR_SETTINGS
|
|
446
|
-
STATUS_BAR_SETTINGS.update(settings_dict)
|
|
447
|
-
return STATUS_BAR_SETTINGS
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
def get_providers():
|
|
451
|
-
"""Get list of available providers.
|
|
452
|
-
|
|
453
|
-
Returns:
|
|
454
|
-
list: List of provider names from PROVIDER_REGISTRY.
|
|
455
|
-
"""
|
|
456
|
-
return list(PROVIDER_REGISTRY.keys())
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
def get_provider_display_name(provider: str) -> str:
|
|
460
|
-
"""Return the user-facing provider name for a provider key."""
|
|
461
|
-
display_names = {
|
|
462
|
-
"codex": "Codex",
|
|
463
|
-
}
|
|
464
|
-
return display_names.get(provider, provider.replace("_", " ").title())
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
# ============================================================================
|
|
468
|
-
# PROVIDER REGISTRY - Centralized provider configuration
|
|
469
|
-
# ============================================================================
|
|
470
|
-
|
|
471
|
-
# Build provider registry and export as module-level constants (loaded once)
|
|
472
|
-
PROVIDER_REGISTRY = _get_provider_registry()
|
|
473
|
-
LLM_PROVIDER = _get_provider()
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
__all__ = [
|
|
477
|
-
"CONFIG_PATH",
|
|
478
|
-
"PROVIDER_REGISTRY",
|
|
479
|
-
"get_providers",
|
|
480
|
-
"get_provider_display_name",
|
|
481
|
-
"get_model_cost",
|
|
482
|
-
"LLM_PROVIDER",
|
|
483
|
-
"TOOLS_ENABLED",
|
|
484
|
-
"TOOLS_REQUIRE_CONFIRMATION",
|
|
485
|
-
"WEB_SEARCH_REQUIRE_CONFIRMATION",
|
|
486
|
-
"APPROVE_MODES",
|
|
487
|
-
"APPROVE_MODE_LABELS",
|
|
488
|
-
|
|
489
|
-
"get_provider_config",
|
|
490
|
-
"generate_config_template",
|
|
491
|
-
"reload_config",
|
|
492
|
-
"STATUS_BAR_SETTINGS",
|
|
493
|
-
"update_status_bar_settings",
|
|
494
|
-
"MEMORY_SETTINGS",
|
|
495
|
-
"update_memory_settings",
|
|
496
|
-
]
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
def generate_config_template():
|
|
500
|
-
"""Generate default template for config.json from provider registry."""
|
|
501
|
-
template = {}
|
|
502
|
-
for provider, config in PROVIDER_REGISTRY.items():
|
|
503
|
-
if "config_keys" in config:
|
|
504
|
-
template.update(config["config_keys"])
|
|
505
|
-
return template
|
|
506
|
-
|
|
507
|
-
# Tooling configuration
|
|
508
|
-
TOOLS_ENABLED = True
|
|
509
|
-
TOOLS_REQUIRE_CONFIRMATION = False
|
|
510
|
-
WEB_SEARCH_REQUIRE_CONFIRMATION = False
|
|
511
|
-
|
|
512
|
-
# Status bar configuration
|
|
513
|
-
STATUS_BAR_SETTINGS = _build_status_bar_settings()
|
|
514
|
-
|
|
515
|
-
# Memory configuration
|
|
516
|
-
MEMORY_SETTINGS = _build_memory_settings()
|
|
517
|
-
|
|
518
|
-
# Tool approval modes
|
|
519
|
-
APPROVE_MODES = ("safe", "accept_edits", "danger")
|
|
520
|
-
CYCLEABLE_APPROVE_MODES = ("safe", "accept_edits")
|
|
521
|
-
APPROVE_MODE_LABELS = {
|
|
522
|
-
"safe": "Safe",
|
|
523
|
-
"accept_edits": "Accept Edits",
|
|
524
|
-
"danger": "Danger",
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
def get_provider_config(provider: str):
|
|
528
|
-
"""Retrieve the configuration dictionary for a given provider.
|
|
529
|
-
|
|
530
|
-
Args:
|
|
531
|
-
provider (str): Provider name (e.g., 'local', 'openrouter', 'glm', 'openai').
|
|
532
|
-
|
|
533
|
-
Returns:
|
|
534
|
-
dict: Provider config from the PROVIDER_REGISTRY.
|
|
535
|
-
"""
|
|
536
|
-
return PROVIDER_REGISTRY.get(provider, {})
|