bone-agent 1.3.3 → 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.
Files changed (121) hide show
  1. package/bin/bone.js +39 -0
  2. package/package.json +25 -39
  3. package/LICENSE +0 -21
  4. package/README.md +0 -184
  5. package/bin/npm-wrapper.js +0 -235
  6. package/bin/rg +0 -0
  7. package/bin/rg.exe +0 -0
  8. package/config.yaml.example +0 -141
  9. package/prompts/main/ask_questions.md +0 -31
  10. package/prompts/main/batch_independent_calls.md +0 -5
  11. package/prompts/main/casual_interactions.md +0 -11
  12. package/prompts/main/code_references.md +0 -8
  13. package/prompts/main/communication_style.md +0 -12
  14. package/prompts/main/context_reliability.md +0 -12
  15. package/prompts/main/conversational_tool_calling.md +0 -15
  16. package/prompts/main/dream.md +0 -36
  17. package/prompts/main/editing_pattern.md +0 -13
  18. package/prompts/main/error_handling.md +0 -6
  19. package/prompts/main/exploration_pattern.md +0 -21
  20. package/prompts/main/intro.md +0 -1
  21. package/prompts/main/obsidian.md +0 -16
  22. package/prompts/main/obsidian_project.md +0 -79
  23. package/prompts/main/professional_objectivity.md +0 -3
  24. package/prompts/main/targeted_searching.md +0 -10
  25. package/prompts/main/task_lists_pattern.md +0 -8
  26. package/prompts/main/temp_folder.md +0 -9
  27. package/prompts/main/think_before_acting.md +0 -10
  28. package/prompts/main/tone_and_style.md +0 -4
  29. package/prompts/main/tool_preferences.md +0 -24
  30. package/prompts/main/trust_subagent_context.md +0 -21
  31. package/prompts/main/when_to_use_sub_agent.md +0 -7
  32. package/prompts/micro/ask_questions.md +0 -1
  33. package/prompts/micro/batch_independent_calls.md +0 -1
  34. package/prompts/micro/casual_interactions.md +0 -1
  35. package/prompts/micro/code_references.md +0 -1
  36. package/prompts/micro/communication_style.md +0 -1
  37. package/prompts/micro/context_reliability.md +0 -1
  38. package/prompts/micro/conversational_tool_calling.md +0 -1
  39. package/prompts/micro/editing_pattern.md +0 -1
  40. package/prompts/micro/error_handling.md +0 -1
  41. package/prompts/micro/exploration_pattern.md +0 -1
  42. package/prompts/micro/intro.md +0 -1
  43. package/prompts/micro/obsidian.md +0 -4
  44. package/prompts/micro/obsidian_project.md +0 -5
  45. package/prompts/micro/professional_objectivity.md +0 -1
  46. package/prompts/micro/targeted_searching.md +0 -1
  47. package/prompts/micro/task_lists_pattern.md +0 -1
  48. package/prompts/micro/temp_folder.md +0 -1
  49. package/prompts/micro/think_before_acting.md +0 -5
  50. package/prompts/micro/tone_and_style.md +0 -1
  51. package/prompts/micro/tool_preferences.md +0 -1
  52. package/prompts/micro/trust_subagent_context.md +0 -1
  53. package/prompts/micro/when_to_use_sub_agent.md +0 -1
  54. package/requirements.txt +0 -9
  55. package/src/__init__.py +0 -11
  56. package/src/core/__init__.py +0 -1
  57. package/src/core/agentic.py +0 -985
  58. package/src/core/chat_manager.py +0 -1564
  59. package/src/core/config_manager.py +0 -253
  60. package/src/core/cron.py +0 -582
  61. package/src/core/cron_allowlist.py +0 -118
  62. package/src/core/memory.py +0 -145
  63. package/src/core/retry.py +0 -71
  64. package/src/core/sub_agent.py +0 -326
  65. package/src/core/tool_approval.py +0 -220
  66. package/src/core/tool_feedback.py +0 -778
  67. package/src/exceptions.py +0 -79
  68. package/src/llm/__init__.py +0 -1
  69. package/src/llm/client.py +0 -171
  70. package/src/llm/config.py +0 -492
  71. package/src/llm/prompts.py +0 -489
  72. package/src/llm/providers.py +0 -436
  73. package/src/llm/streaming.py +0 -163
  74. package/src/llm/token_tracker.py +0 -384
  75. package/src/tools/__init__.py +0 -212
  76. package/src/tools/constants.py +0 -59
  77. package/src/tools/create_file.py +0 -136
  78. package/src/tools/directory.py +0 -389
  79. package/src/tools/edit.py +0 -545
  80. package/src/tools/file_reader.py +0 -322
  81. package/src/tools/helpers/__init__.py +0 -105
  82. package/src/tools/helpers/base.py +0 -550
  83. package/src/tools/helpers/converters.py +0 -44
  84. package/src/tools/helpers/file_helpers.py +0 -189
  85. package/src/tools/helpers/formatters.py +0 -411
  86. package/src/tools/helpers/loader.py +0 -231
  87. package/src/tools/helpers/parallel_executor.py +0 -231
  88. package/src/tools/helpers/path_resolver.py +0 -232
  89. package/src/tools/helpers/plugin_manifest.py +0 -156
  90. package/src/tools/obsidian.py +0 -96
  91. package/src/tools/review_sub_agent.py +0 -189
  92. package/src/tools/rg_search.py +0 -460
  93. package/src/tools/search_plugins.py +0 -109
  94. package/src/tools/select_option.py +0 -600
  95. package/src/tools/shell.py +0 -302
  96. package/src/tools/sub_agent.py +0 -139
  97. package/src/tools/task_list.py +0 -269
  98. package/src/tools/web_search.py +0 -61
  99. package/src/ui/__init__.py +0 -1
  100. package/src/ui/banner.py +0 -87
  101. package/src/ui/commands.py +0 -2809
  102. package/src/ui/displays.py +0 -214
  103. package/src/ui/loader.py +0 -284
  104. package/src/ui/main.py +0 -647
  105. package/src/ui/prompt_utils.py +0 -113
  106. package/src/ui/setting_selector.py +0 -590
  107. package/src/ui/setup_wizard.py +0 -294
  108. package/src/ui/sub_agent_panel.py +0 -234
  109. package/src/ui/tool_confirmation.py +0 -215
  110. package/src/utils/__init__.py +0 -1
  111. package/src/utils/citation_parser.py +0 -199
  112. package/src/utils/editor.py +0 -158
  113. package/src/utils/gitignore_filter.py +0 -149
  114. package/src/utils/logger.py +0 -254
  115. package/src/utils/paths.py +0 -30
  116. package/src/utils/result_parsers.py +0 -108
  117. package/src/utils/safe_commands.py +0 -243
  118. package/src/utils/settings.py +0 -191
  119. package/src/utils/user_message_logger.py +0 -120
  120. package/src/utils/validation.py +0 -191
  121. package/src/utils/web_search.py +0 -173
@@ -1,253 +0,0 @@
1
-
2
-
3
- from pathlib import Path
4
- import shutil
5
- from typing import Dict, Any, Optional
6
- import logging
7
- import yaml
8
- from llm import config as llm_config
9
-
10
- logger = logging.getLogger(__name__)
11
-
12
-
13
- class ConfigManager:
14
-
15
- def __init__(self, config_path: Optional[Path] = None):
16
- self.config_path = config_path or llm_config.CONFIG_PATH
17
- self._cached_data = None
18
-
19
- def load(self, force_reload: bool = False) -> Dict[str, Any]:
20
- """Load configuration from file, using cache if available.
21
-
22
- Args:
23
- force_reload: If True, bypass cache and reload from disk
24
-
25
- Returns:
26
- Configuration dictionary
27
- """
28
- if not force_reload and self._cached_data is not None:
29
- return self._cached_data
30
-
31
- if not self.config_path.exists():
32
- self._cached_data = llm_config.generate_config_template()
33
- return self._cached_data
34
-
35
- try:
36
- with open(self.config_path, 'r', encoding='utf-8-sig') as f:
37
- self._cached_data = yaml.safe_load(f) or {}
38
-
39
- # Migrate: rename old provider IDs -> bone (provider ID rename)
40
- old_provider = self._cached_data.get('LAST_PROVIDER')
41
- if old_provider in ('vmcode_proxy', 'vmcode_free', 'vmcode'):
42
- logger.info("Migrating provider name '%s' -> 'bone'", old_provider)
43
- self._cached_data['LAST_PROVIDER'] = 'bone'
44
- self.save(self._cached_data, create_backup=True)
45
-
46
- return self._cached_data
47
- except yaml.YAMLError as e:
48
- logger.error(f"Failed to parse config file {self.config_path}: {e}")
49
- logger.warning("Using default configuration template")
50
- self._cached_data = llm_config.generate_config_template()
51
- return self._cached_data
52
-
53
- def save(self, config_data: Dict[str, Any], create_backup: bool = False):
54
- if create_backup and self.config_path.exists():
55
- backup_path = self.config_path.with_suffix('.backup')
56
- shutil.copy2(self.config_path, backup_path)
57
-
58
- with open(self.config_path, 'w', encoding='utf-8-sig') as f:
59
- yaml.dump(config_data, f, default_flow_style=False, sort_keys=False, allow_unicode=True)
60
-
61
- self._cached_data = config_data
62
- # Note: Config is read from disk on reload. Call reload_config() after changes.
63
-
64
- def update_field(self, key: str, value: Any, create_backup: bool = False) -> Optional[Path]:
65
- """Update a single configuration field.
66
-
67
- Args:
68
- key: Configuration key to update
69
- value: New value for the key
70
- create_backup: If True, create a backup before saving
71
-
72
- Returns:
73
- Backup path if backup was created, None otherwise
74
- """
75
- config_data = self.load(force_reload=True)
76
- config_data[key] = value
77
-
78
- backup_path = None
79
- if create_backup and self.config_path.exists():
80
- backup_path = self.config_path.with_suffix('.backup')
81
-
82
- self.save(config_data, create_backup=create_backup)
83
- return backup_path
84
-
85
- def set_provider(self, provider_name: str) -> Optional[Path]:
86
- return self.update_field('LAST_PROVIDER', provider_name)
87
-
88
- def _extract_model_pricing(self, model_name: str, config: Dict[str, Any] | None = None) -> Dict[str, float]:
89
- """Extract pricing for a model from MODEL_PRICES.
90
-
91
- Delegates to llm_config.get_model_cost() — single source of truth.
92
- """
93
- cost_in, cost_out = llm_config.get_model_cost(model_name, config=config)
94
- return {'in': cost_in, 'out': cost_out}
95
-
96
- def get_usage_costs(self, provider: str = None, model: str = None) -> Dict[str, float]:
97
- """Get usage costs for a specific model.
98
-
99
- Args:
100
- provider: Provider name (e.g., 'openrouter', 'glm', 'openai').
101
- If None, uses the last provider from config.
102
- model: Model name (e.g., 'minimax/minimax-m2.5', 'GLM-4.7').
103
- If None, uses the current model from the provider.
104
-
105
- Returns:
106
- Dict with 'in' and 'out' cost values per 1M tokens
107
- """
108
- config_data = self.load()
109
-
110
- if provider is None:
111
- provider = config_data.get('LAST_PROVIDER', 'glm')
112
-
113
- # Get model name from config if not provided
114
- if model is None:
115
- provider_model_map = {
116
- 'bone': 'BONE_PROXY_MODEL',
117
- 'openrouter': 'OPENROUTER_MODEL',
118
- 'glm': 'GLM_MODEL',
119
- 'glm_plan': 'GLM_PLAN_MODEL',
120
- 'openai': 'OPENAI_MODEL',
121
- 'gemini': 'GEMINI_MODEL',
122
- 'minimax': 'MINIMAX_MODEL',
123
- 'minimax_plan': 'MINIMAX_PLAN_MODEL',
124
- 'anthropic': 'ANTHROPIC_MODEL',
125
- 'kimi': 'KIMI_MODEL'
126
- }
127
- model_key = provider_model_map.get(provider.lower())
128
- if model_key:
129
- model = config_data.get(model_key, '')
130
-
131
- return self._extract_model_pricing(model, config=config_data)
132
-
133
- def set_model(self, provider_name: str, model: str) -> Optional[Path]:
134
- """Set model for a specific provider.
135
-
136
- Args:
137
- provider_name: Provider name (e.g., 'openrouter', 'glm', 'local', 'openai')
138
- model: Model name/path to set
139
-
140
- Returns:
141
- Backup path if backup was created, None otherwise
142
- """
143
- # Map provider names to their config keys
144
- provider_keys = {
145
- 'local': 'LOCAL_MODEL_PATH',
146
- 'bone': 'BONE_PROXY_MODEL',
147
- 'openrouter': 'OPENROUTER_MODEL',
148
- 'glm': 'GLM_MODEL',
149
- 'glm_plan': 'GLM_PLAN_MODEL',
150
- 'openai': 'OPENAI_MODEL',
151
- 'gemini': 'GEMINI_MODEL',
152
- 'minimax': 'MINIMAX_MODEL',
153
- 'minimax_plan': 'MINIMAX_PLAN_MODEL',
154
- 'anthropic': 'ANTHROPIC_MODEL',
155
- 'kimi': 'KIMI_MODEL'
156
- }
157
-
158
- if provider_name not in provider_keys:
159
- raise ValueError(f"Unknown provider: {provider_name}")
160
-
161
- key = provider_keys[provider_name]
162
- return self.update_field(key, model)
163
-
164
- def set_api_key(self, provider_name: str, api_key: str) -> Optional[Path]:
165
- """Set API key for a specific provider.
166
-
167
- Args:
168
- provider_name: Provider name (e.g., 'openrouter', 'glm', 'openai')
169
- api_key: API key to set
170
-
171
- Returns:
172
- Backup path if backup was created, None otherwise
173
- """
174
- # Map provider names to their config keys
175
- provider_keys = {
176
- 'openrouter': 'OPENROUTER_API_KEY',
177
- 'bone': 'BONE_PROXY_API_KEY',
178
- 'glm': 'GLM_API_KEY',
179
- 'glm_plan': 'GLM_PLAN_API_KEY',
180
- 'openai': 'OPENAI_API_KEY',
181
- 'gemini': 'GEMINI_API_KEY',
182
- 'minimax': 'MINIMAX_API_KEY',
183
- 'minimax_plan': 'MINIMAX_PLAN_API_KEY',
184
- 'anthropic': 'ANTHROPIC_API_KEY',
185
- 'kimi': 'KIMI_API_KEY'
186
- }
187
-
188
- if provider_name not in provider_keys:
189
- raise ValueError(f"Unknown provider: {provider_name}")
190
-
191
- key = provider_keys[provider_name]
192
- return self.update_field(key, api_key)
193
-
194
- def get_model_price(self, model_name: str) -> Dict[str, float]:
195
- """Get pricing for a specific model.
196
-
197
- Args:
198
- model_name: Model name (e.g., 'minimax/minimax-m2.5', 'GLM-4.7')
199
-
200
- Returns:
201
- Dict with 'in' and 'out' cost values per 1M tokens
202
- """
203
- config_data = self.load()
204
- return self._extract_model_pricing(model_name, config=config_data)
205
-
206
- def set_model_price(self, model_name: str, cost_in: float, cost_out: float) -> Optional[Path]:
207
- """Set pricing for a specific model.
208
-
209
- Args:
210
- model_name: Model name (e.g., 'minimax/minimax-m2.5', 'GLM-4.7')
211
- cost_in: Cost per 1M input tokens
212
- cost_out: Cost per 1M output tokens
213
-
214
- Returns:
215
- Backup path if backup was created, None otherwise
216
- """
217
- config_data = self.load(force_reload=True)
218
-
219
- if 'MODEL_PRICES' not in config_data:
220
- config_data['MODEL_PRICES'] = {}
221
-
222
- config_data['MODEL_PRICES'][model_name] = {
223
- 'cost_in': cost_in,
224
- 'cost_out': cost_out
225
- }
226
-
227
- return self.save(config_data, create_backup=False)
228
-
229
- def list_model_prices(self) -> Dict[str, Dict[str, float]]:
230
- """Get all model-specific pricing.
231
-
232
- Returns:
233
- Dict mapping model names to their pricing (cost_in/cost_out per 1M tokens)
234
- """
235
- config_data = self.load()
236
- return config_data.get('MODEL_PRICES', {})
237
-
238
- def delete_model_price(self, model_name: str) -> Optional[Path]:
239
- """Delete pricing for a specific model.
240
-
241
- Args:
242
- model_name: Model name to remove from pricing
243
-
244
- Returns:
245
- Backup path if backup was created, None otherwise
246
- """
247
- config_data = self.load(force_reload=True)
248
-
249
- if 'MODEL_PRICES' in config_data and model_name in config_data['MODEL_PRICES']:
250
- del config_data['MODEL_PRICES'][model_name]
251
- return self.save(config_data, create_backup=False)
252
-
253
- return None