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
package/src/exceptions.py DELETED
@@ -1,79 +0,0 @@
1
- """Custom exception hierarchy for bone-agent."""
2
-
3
- class BoneAgentError(Exception):
4
- """Base exception for all bone-agent application errors.
5
-
6
- All custom exceptions should inherit from this class.
7
- Provides consistent error handling and allows catching
8
- all bone-agent-specific errors with a single except clause.
9
- """
10
- def __init__(self, message: str, *, details: dict = None):
11
- """Initialize exception with optional details.
12
-
13
- Args:
14
- message: Human-readable error message
15
- details: Optional dictionary with additional error context
16
- """
17
- super().__init__(message)
18
- self.details = details or {}
19
-
20
- def __str__(self):
21
- base_msg = super().__str__()
22
- if self.details:
23
- # Skip multi-line values from the compact string representation
24
- # (they're included separately in detailed error formatting)
25
- single_line_details = {k: v for k, v in self.details.items() if "\n" not in str(v)}
26
- if single_line_details:
27
- details_str = ", ".join(f"{k}={v}" for k, v in single_line_details.items())
28
- return f"{base_msg} ({details_str})"
29
- return base_msg
30
-
31
-
32
- class ConfigurationError(BoneAgentError):
33
- """Raised when configuration is invalid, missing, or cannot be loaded."""
34
- pass
35
-
36
-
37
- class LLMError(BoneAgentError):
38
- """Raised when LLM API communication fails or returns unexpected data."""
39
- pass
40
-
41
-
42
- class LLMConnectionError(LLMError):
43
- """Raised when network connection to LLM provider fails."""
44
- pass
45
-
46
-
47
- class LLMResponseError(LLMError):
48
- """Raised when LLM response is malformed or invalid."""
49
- pass
50
-
51
-
52
- class ToolExecutionError(BoneAgentError):
53
- """Raised when tool execution fails."""
54
- pass
55
-
56
-
57
- class CommandExecutionError(ToolExecutionError):
58
- """Raised when shell command execution fails."""
59
- pass
60
-
61
-
62
- class FileEditError(ToolExecutionError):
63
- """Raised when file edit operation fails."""
64
- pass
65
-
66
-
67
- class ValidationError(BoneAgentError):
68
- """Raised when input validation fails."""
69
- pass
70
-
71
-
72
- class PathValidationError(ValidationError):
73
- """Raised when path validation fails (blocked by gitignore, etc.)."""
74
- pass
75
-
76
-
77
- class CommandValidationError(ValidationError):
78
- """Raised when command validation fails (dangerous operators, etc.)."""
79
- pass
@@ -1 +0,0 @@
1
- """LLM integration layer for bone-agent."""
package/src/llm/client.py DELETED
@@ -1,171 +0,0 @@
1
- """LLM client for making API requests to various providers."""
2
-
3
- import logging
4
-
5
- import requests
6
- from llm import config as config_module
7
- from llm.config import PROVIDER_REGISTRY, get_provider_config, get_providers
8
- from llm.providers import get_handler
9
- from exceptions import LLMConnectionError, LLMResponseError, ConfigurationError
10
- from utils.validation import validate_api_url
11
-
12
- logger = logging.getLogger(__name__)
13
-
14
- # Connection/read timeouts (seconds)
15
- _CONNECT_TIMEOUT = 10
16
- _READ_TIMEOUT = 120
17
-
18
-
19
- class StreamWrapper:
20
- """Wraps streaming response generator with cleanup capability."""
21
-
22
- def __init__(self, response, generator):
23
- self._response = response
24
- self._generator = generator
25
-
26
- def __iter__(self):
27
- return self
28
-
29
- def __next__(self):
30
- return next(self._generator)
31
-
32
- def close(self):
33
- """Close underlying HTTP connection."""
34
- if self._response:
35
- self._response.close()
36
-
37
-
38
- class LLMClient:
39
- def __init__(self, provider=None):
40
- """Initialize LLM client.
41
-
42
- Args:
43
- provider: Provider name. If None, uses global LLM_PROVIDER from config.
44
- """
45
- self.provider = provider or config_module.LLM_PROVIDER
46
- self.handler = get_handler(self.provider)
47
- self.config = self._get_provider_config()
48
-
49
- @property
50
- def model(self) -> str:
51
- """Return configured model name, if any."""
52
- return str(self.config.get("payload", {}).get("model") or "")
53
-
54
- def _get_provider_config(self):
55
- """Build provider config from PROVIDER_REGISTRY."""
56
- registry = get_provider_config(self.provider)
57
- if not registry:
58
- raise ConfigurationError(f"Unknown provider: {self.provider}")
59
-
60
- # Build headers using handler
61
- headers = self.handler.build_headers(registry)
62
-
63
- # Build payload with model name
64
- payload = {}
65
- model_name = registry.get("api_model") or registry.get("model")
66
- if model_name:
67
- payload["model"] = model_name
68
-
69
- url = f"{registry['api_base']}{registry['endpoint']}"
70
- valid, err = validate_api_url(url)
71
- if not valid:
72
- raise ConfigurationError(
73
- f"Insecure API endpoint for provider '{self.provider}': {err}"
74
- )
75
-
76
- return {
77
- "url": url,
78
- "headers": headers,
79
- "payload": payload,
80
- "error_prefix": registry["error_prefix"],
81
- "registry": registry
82
- }
83
-
84
- def chat_completion(self, messages, stream=True, tools=None):
85
- """Make a chat completion request.
86
-
87
- Args:
88
- messages: List of message dicts
89
- stream: Whether to stream the response
90
- tools: Optional list of tool definitions
91
-
92
- Returns:
93
- StreamWrapper if stream=True, else response dict
94
- """
95
- config = self.config
96
- registry = config["registry"]
97
-
98
- # Build payload using handler
99
- payload = self.handler.build_payload(registry, messages, tools, stream)
100
-
101
- try:
102
- response = requests.post(
103
- config["url"],
104
- headers=config["headers"],
105
- json=payload,
106
- stream=stream,
107
- verify=True,
108
- timeout=(_CONNECT_TIMEOUT, _READ_TIMEOUT),
109
- )
110
-
111
- # For better debugging, include response text on 4xx errors
112
- if not response.ok:
113
- error_details = response.text if response.text else str(response.status_code)
114
- raise LLMConnectionError(
115
- f"Error communicating with {config['error_prefix']}",
116
- details={
117
- "provider": self.provider,
118
- "original_error": error_details,
119
- "status_code": response.status_code,
120
- }
121
- )
122
- response.raise_for_status()
123
-
124
- if stream:
125
- return StreamWrapper(
126
- response,
127
- self.handler.parse_stream(response)
128
- )
129
- else:
130
- response_json = response.json()
131
- return self.handler.parse_response(response_json)
132
-
133
- except requests.exceptions.RequestException as e:
134
- raise LLMConnectionError(
135
- f"Error communicating with {config['error_prefix']}",
136
- details={"provider": self.provider, "original_error": str(e)}
137
- )
138
-
139
- def switch_provider(self, new_provider):
140
- """Switch to a different provider.
141
-
142
- Args:
143
- new_provider: Name of the provider to switch to.
144
-
145
- Returns:
146
- True if successful, False if provider not found.
147
- """
148
- if new_provider in get_providers():
149
- self.provider = new_provider
150
- self.handler = get_handler(new_provider)
151
- self.config = self._get_provider_config()
152
- return True
153
- return False
154
-
155
- def sync_provider_from_config(self):
156
- """Sync this client's provider and config with the current config.
157
-
158
- This should be called after config is reloaded from disk.
159
- """
160
- current_provider = config_module.LLM_PROVIDER
161
- if self.provider != current_provider:
162
- self.provider = current_provider
163
- self.handler = get_handler(current_provider)
164
- self.config = self._get_provider_config()
165
- return True
166
- # Even if provider hasn't changed, config values (model, api_key) might have
167
- self.config = self._get_provider_config()
168
- return False
169
-
170
-
171
- __all__ = ['LLMClient']