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.
- package/bin/bone.js +39 -0
- package/package.json +25 -39
- package/LICENSE +0 -21
- package/README.md +0 -184
- package/bin/npm-wrapper.js +0 -235
- package/bin/rg +0 -0
- package/bin/rg.exe +0 -0
- package/config.yaml.example +0 -141
- 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 -36
- 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/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/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 -985
- package/src/core/chat_manager.py +0 -1564
- package/src/core/config_manager.py +0 -253
- package/src/core/cron.py +0 -582
- package/src/core/cron_allowlist.py +0 -118
- package/src/core/memory.py +0 -145
- package/src/core/retry.py +0 -71
- package/src/core/sub_agent.py +0 -326
- package/src/core/tool_approval.py +0 -220
- package/src/core/tool_feedback.py +0 -778
- package/src/exceptions.py +0 -79
- package/src/llm/__init__.py +0 -1
- package/src/llm/client.py +0 -171
- package/src/llm/config.py +0 -492
- package/src/llm/prompts.py +0 -489
- package/src/llm/providers.py +0 -436
- package/src/llm/streaming.py +0 -163
- package/src/llm/token_tracker.py +0 -384
- package/src/tools/__init__.py +0 -212
- 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 -545
- package/src/tools/file_reader.py +0 -322
- package/src/tools/helpers/__init__.py +0 -105
- package/src/tools/helpers/base.py +0 -550
- 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 -231
- package/src/tools/helpers/parallel_executor.py +0 -231
- package/src/tools/helpers/path_resolver.py +0 -232
- package/src/tools/helpers/plugin_manifest.py +0 -156
- package/src/tools/obsidian.py +0 -96
- package/src/tools/review_sub_agent.py +0 -189
- package/src/tools/rg_search.py +0 -460
- package/src/tools/search_plugins.py +0 -109
- 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 -2809
- package/src/ui/displays.py +0 -214
- package/src/ui/loader.py +0 -284
- package/src/ui/main.py +0 -647
- 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 -215
- package/src/utils/__init__.py +0 -1
- package/src/utils/citation_parser.py +0 -199
- package/src/utils/editor.py +0 -158
- 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 -191
- package/src/utils/user_message_logger.py +0 -120
- package/src/utils/validation.py +0 -191
- package/src/utils/web_search.py +0 -173
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
"""Tool approval workflows for edit_file and execute_command."""
|
|
2
|
-
|
|
3
|
-
from rich.text import Text
|
|
4
|
-
|
|
5
|
-
from tools import confirm_tool
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def handle_edit_approval(preview, file_path, args_dict, console, thinking_indicator,
|
|
9
|
-
approve_mode, cycle_approve_mode, repo_root, gitignore_spec,
|
|
10
|
-
vault_root_str):
|
|
11
|
-
"""Handle edit_file approval workflow.
|
|
12
|
-
|
|
13
|
-
Args:
|
|
14
|
-
preview: Either a rich Text object or a plain string to display.
|
|
15
|
-
file_path: The file path being edited (for the confirm prompt).
|
|
16
|
-
args_dict: Tool arguments dict (path, search, replace, context_lines).
|
|
17
|
-
console: Rich console for display.
|
|
18
|
-
thinking_indicator: ThinkingIndicator instance (may be None).
|
|
19
|
-
approve_mode: Current approval mode string.
|
|
20
|
-
cycle_approve_mode: Callable to cycle approval mode.
|
|
21
|
-
repo_root: Repository root path string.
|
|
22
|
-
gitignore_spec: Gitignore spec object.
|
|
23
|
-
vault_root_str: Callable returning vault root path string.
|
|
24
|
-
|
|
25
|
-
Returns:
|
|
26
|
-
(result_str, should_exit) tuple where should_exit=True means cancel the agentic loop.
|
|
27
|
-
"""
|
|
28
|
-
# Display preview
|
|
29
|
-
console.print(preview)
|
|
30
|
-
console.print()
|
|
31
|
-
|
|
32
|
-
# Stop thinking indicator while waiting for user input
|
|
33
|
-
if thinking_indicator:
|
|
34
|
-
thinking_indicator.stop()
|
|
35
|
-
|
|
36
|
-
action, guidance = confirm_tool(
|
|
37
|
-
f"edit_file: {file_path}",
|
|
38
|
-
console,
|
|
39
|
-
reason=args_dict.get('reason', 'Apply file edit with above changes'),
|
|
40
|
-
requires_approval=True,
|
|
41
|
-
approve_mode=approve_mode,
|
|
42
|
-
is_edit_tool=True,
|
|
43
|
-
cycle_approve_mode=cycle_approve_mode
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
if action == "accept":
|
|
47
|
-
from tools.edit import _execute_edit_file
|
|
48
|
-
final_result = _execute_edit_file(
|
|
49
|
-
path=args_dict.get('path'),
|
|
50
|
-
search=args_dict.get('search'),
|
|
51
|
-
replace=args_dict.get('replace'),
|
|
52
|
-
repo_root=repo_root,
|
|
53
|
-
console=console,
|
|
54
|
-
gitignore_spec=gitignore_spec,
|
|
55
|
-
context_lines=args_dict.get('context_lines', 3),
|
|
56
|
-
vault_root=vault_root_str()
|
|
57
|
-
)
|
|
58
|
-
# Strip exit_code line from final result before displaying
|
|
59
|
-
if final_result and isinstance(final_result, str):
|
|
60
|
-
result_lines = [line for line in final_result.split('\n') if not line.startswith('exit_code=')]
|
|
61
|
-
final_result = '\n'.join(result_lines).strip()
|
|
62
|
-
result_str, should_exit = final_result, False
|
|
63
|
-
elif action == "advise":
|
|
64
|
-
console.print(f"[dim]Edit not applied. User advice: {guidance}[/dim]")
|
|
65
|
-
result_str = f"exit_code=1\nEdit not applied. User advice: {guidance}"
|
|
66
|
-
should_exit = False
|
|
67
|
-
else: # cancel
|
|
68
|
-
console.print("[dim]Operation canceled by user.[/dim]")
|
|
69
|
-
result_str = "exit_code=1\nOperation canceled by user. Do not retry this operation."
|
|
70
|
-
should_exit = True
|
|
71
|
-
|
|
72
|
-
# Restart thinking indicator after user input
|
|
73
|
-
if thinking_indicator:
|
|
74
|
-
thinking_indicator.start()
|
|
75
|
-
|
|
76
|
-
return result_str, should_exit
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
def resolve_edit_preview(result):
|
|
80
|
-
"""Extract a displayable preview from an edit_file tool result.
|
|
81
|
-
|
|
82
|
-
Handles both Rich Text objects (new format) and legacy string format.
|
|
83
|
-
|
|
84
|
-
Args:
|
|
85
|
-
result: Either a rich Text object or a string.
|
|
86
|
-
|
|
87
|
-
Returns:
|
|
88
|
-
(preview, is_valid) tuple.
|
|
89
|
-
- preview: Text object, plain string, or None if error.
|
|
90
|
-
- is_valid: False if the result is an error (non-zero exit_code).
|
|
91
|
-
"""
|
|
92
|
-
if isinstance(result, Text):
|
|
93
|
-
return result, True
|
|
94
|
-
elif isinstance(result, str) and result.startswith("exit_code=0"):
|
|
95
|
-
lines = result.split('\n')
|
|
96
|
-
preview_lines = [line for line in lines if not line.startswith("exit_code=")]
|
|
97
|
-
preview = '\n'.join(preview_lines).strip()
|
|
98
|
-
return preview, True
|
|
99
|
-
else:
|
|
100
|
-
# Error occurred during preview - don't show to user
|
|
101
|
-
return None, False
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
def handle_command_approval(command, arguments, tool, context, console,
|
|
105
|
-
thinking_indicator, approve_mode, debug_mode,
|
|
106
|
-
cron_job_id=None, cron_allowlist=None,
|
|
107
|
-
cron_interactive=False):
|
|
108
|
-
"""Handle execute_command approval workflow.
|
|
109
|
-
|
|
110
|
-
Checks for silent blocks, auto-approval, and prompts user if needed.
|
|
111
|
-
When a cron_job_id and cron_allowlist are provided, commands on the
|
|
112
|
-
job's allow list are auto-approved; unlisted commands are blocked
|
|
113
|
-
(in scheduled mode) or prompted interactively (in test-run mode).
|
|
114
|
-
|
|
115
|
-
Args:
|
|
116
|
-
command: The shell command string.
|
|
117
|
-
arguments: Tool arguments dict (includes 'reason').
|
|
118
|
-
tool: The tool object to execute on approval.
|
|
119
|
-
context: Tool execution context dict.
|
|
120
|
-
console: Rich console for display.
|
|
121
|
-
thinking_indicator: ThinkingIndicator instance (may be None).
|
|
122
|
-
approve_mode: Current approval mode string.
|
|
123
|
-
debug_mode: Whether debug mode is active (for silent block logging).
|
|
124
|
-
cron_job_id: Optional cron job ID for allow list checking.
|
|
125
|
-
cron_allowlist: Optional CronAllowlist instance for cron command gating.
|
|
126
|
-
cron_interactive: If True, cron job is in interactive test-run mode.
|
|
127
|
-
|
|
128
|
-
Returns:
|
|
129
|
-
(result, should_exit, command_executed) tuple.
|
|
130
|
-
- result: Tool result string.
|
|
131
|
-
- should_exit: True if the user canceled (break the agentic loop).
|
|
132
|
-
- command_executed: True if the command was actually executed (display output).
|
|
133
|
-
"""
|
|
134
|
-
from utils.validation import is_auto_approved_command, check_for_silent_blocked_command
|
|
135
|
-
|
|
136
|
-
# Check if command should be silently blocked (redirect to native tool)
|
|
137
|
-
is_blocked, reprompt_msg = check_for_silent_blocked_command(command)
|
|
138
|
-
if is_blocked:
|
|
139
|
-
if debug_mode:
|
|
140
|
-
console.print(f"[dim]Silently blocked command: {command.split()[0]}[/dim]")
|
|
141
|
-
result = f"exit_code=1\n{reprompt_msg}"
|
|
142
|
-
return result, False, False
|
|
143
|
-
|
|
144
|
-
# Check if command should be auto-approved (global safe commands)
|
|
145
|
-
auto_approve = is_auto_approved_command(command)
|
|
146
|
-
|
|
147
|
-
# Check cron allow list
|
|
148
|
-
cron_auto_approved = False
|
|
149
|
-
if cron_job_id and cron_allowlist:
|
|
150
|
-
if cron_allowlist.is_allowed(cron_job_id, command):
|
|
151
|
-
cron_auto_approved = True
|
|
152
|
-
elif not auto_approve:
|
|
153
|
-
# Command not on allow list and not globally safe
|
|
154
|
-
# Determine if we're in interactive test-run or scheduled mode
|
|
155
|
-
if cron_interactive:
|
|
156
|
-
# Interactive test run (/cron run) — prompt the user
|
|
157
|
-
pass # Fall through to normal interactive approval below
|
|
158
|
-
else:
|
|
159
|
-
# Scheduled run — block the command, let agent adapt
|
|
160
|
-
allowed_cmds = cron_allowlist.get_commands(cron_job_id)
|
|
161
|
-
allowed_preview = ", ".join(f"'{c}'" for c in allowed_cmds[:5])
|
|
162
|
-
if len(allowed_cmds) > 5:
|
|
163
|
-
allowed_preview += f", ... ({len(allowed_cmds)} total)"
|
|
164
|
-
if not allowed_preview:
|
|
165
|
-
allowed_preview = "(none - run '/cron run <id>' to build the allow list)"
|
|
166
|
-
result = (
|
|
167
|
-
f"exit_code=1\n"
|
|
168
|
-
f"Command not in cron allow list for job '{cron_job_id}'.\n"
|
|
169
|
-
f"Command: {command}\n"
|
|
170
|
-
f"Allowed: {allowed_preview}\n"
|
|
171
|
-
f"Do not retry this command. Use only approved commands or "
|
|
172
|
-
f"ask the user to run '/cron run {cron_job_id}' to add it."
|
|
173
|
-
)
|
|
174
|
-
return result, False, False
|
|
175
|
-
|
|
176
|
-
if cron_auto_approved or auto_approve:
|
|
177
|
-
# Auto-approved command - execute without prompting
|
|
178
|
-
result = tool.execute(arguments, context)
|
|
179
|
-
command_executed = True
|
|
180
|
-
|
|
181
|
-
# In cron test-run mode, auto-save newly approved commands to allow list
|
|
182
|
-
# Skip globally-safe commands — they're auto-approved regardless of the allow list
|
|
183
|
-
if cron_job_id and cron_allowlist and cron_interactive and not auto_approve:
|
|
184
|
-
cron_allowlist.add_command(cron_job_id, command)
|
|
185
|
-
|
|
186
|
-
return result, False, command_executed
|
|
187
|
-
|
|
188
|
-
# Interactive approval (test-run mode or normal session)
|
|
189
|
-
# Stop thinking indicator while waiting for user input
|
|
190
|
-
if thinking_indicator:
|
|
191
|
-
thinking_indicator.stop()
|
|
192
|
-
|
|
193
|
-
action, guidance = confirm_tool(
|
|
194
|
-
f"execute_command: {command[:80]}{'...' if len(command) > 80 else ''}",
|
|
195
|
-
console,
|
|
196
|
-
reason=arguments.get('reason', 'Execute shell command'),
|
|
197
|
-
requires_approval=True,
|
|
198
|
-
approve_mode=approve_mode
|
|
199
|
-
)
|
|
200
|
-
|
|
201
|
-
if action == "accept":
|
|
202
|
-
result = tool.execute(arguments, context)
|
|
203
|
-
command_executed = True
|
|
204
|
-
# Auto-save approved command to cron allow list during test run
|
|
205
|
-
if cron_job_id and cron_allowlist:
|
|
206
|
-
cron_allowlist.add_command(cron_job_id, command)
|
|
207
|
-
elif action == "advise":
|
|
208
|
-
result = f"Command not executed. User advice: {guidance}"
|
|
209
|
-
command_executed = False
|
|
210
|
-
elif action == "cancel":
|
|
211
|
-
result = "Command canceled by user. Do not retry this operation."
|
|
212
|
-
if thinking_indicator:
|
|
213
|
-
thinking_indicator.start()
|
|
214
|
-
return result, True, False
|
|
215
|
-
|
|
216
|
-
# Restart thinking indicator after user input
|
|
217
|
-
if thinking_indicator:
|
|
218
|
-
thinking_indicator.start()
|
|
219
|
-
|
|
220
|
-
return result, False, command_executed
|